"""Tag management API routes (Phase 4).

Implements HITL workflow and tag management per Spec Section 6.1.
"""

from typing import Optional
from uuid import UUID

import structlog
from fastapi import APIRouter, Depends, HTTPException, status
from sqlalchemy.ext.asyncio import AsyncSession

from src.api.dependencies import get_db_session
from src.api.schemas.tags import (
    RecordTagsResponse,
    TagCreate,
    TagCreateResponse,
    TagReview,
    TagReviewResponse,
)
from src.services.tag_management_service import TagManagementService
from src.services.tag_review_service import TagReviewService

logger = structlog.get_logger(__name__)

router = APIRouter(prefix="/v1/blocks", tags=["tags"])


@router.get(
    "/{record_id}/tags",
    response_model=RecordTagsResponse,
    summary="Get tags for a record",
    description="Retrieve all tags for a specific extracted record with metadata (confidence, status, history)",
)
async def get_record_tags(
    record_id: UUID,
    db: AsyncSession = Depends(get_db_session),
) -> RecordTagsResponse:
    """Get all tags for a record.

    Args:
        record_id: Record UUID
        db: Database session

    Returns:
        RecordTagsResponse with record_id and tags list

    Raises:
        HTTPException: 404 if record not found
    """
    service = TagReviewService(db)
    result = await service.get_record_tags(record_id)

    if result is None:
        raise HTTPException(
            status_code=status.HTTP_404_NOT_FOUND,
            detail=f"Record not found: {record_id}",
        )

    logger.info(
        "tags_retrieved",
        record_id=str(record_id),
        tag_count=len(result["tags"]),
    )

    return RecordTagsResponse(
        record_id=record_id,
        tags=result["tags"],
    )


@router.post(
    "/{record_id}/tags/review",
    response_model=TagReviewResponse,
    summary="Review a pending tag",
    description="Confirm or reject a pending tag (HITL workflow). Per Spec Section 4.3.",
)
async def review_tag(
    record_id: UUID,
    review: TagReview,
    db: AsyncSession = Depends(get_db_session),
) -> TagReviewResponse:
    """Review a pending tag (confirm or reject).

    Args:
        record_id: Record UUID
        review: Review decision with tag_id, decision, and optional reason
        db: Database session

    Returns:
        TagReviewResponse with success status and new tag status

    Raises:
        HTTPException: 404 if record/tag not found, 400 if already reviewed
    """
    service = TagReviewService(db)

    # TODO: Get user from auth context
    reviewer = "current_user"

    success, error = await service.review_tag(
        record_id=record_id,
        tag_id=review.tag_id,
        decision=review.decision,
        reviewer=reviewer,
        reason=review.reason,
    )

    if not success:
        if error == "record_not_found":
            raise HTTPException(
                status_code=status.HTTP_404_NOT_FOUND,
                detail=f"Record not found: {record_id}",
            )
        elif error == "tag_not_found":
            raise HTTPException(
                status_code=status.HTTP_404_NOT_FOUND,
                detail=f"Tag not found: {review.tag_id}",
            )
        elif error in ["tag_already_verified", "tag_already_rejected"]:
            raise HTTPException(
                status_code=status.HTTP_400_BAD_REQUEST,
                detail=f"Tag has already been reviewed: {error}",
            )
        else:
            raise HTTPException(
                status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
                detail=f"Review failed: {error}",
            )

    # Determine new status
    from src.api.schemas.tags import TagStatus

    new_status = (
        TagStatus.VERIFIED
        if review.decision.value == "confirm"
        else TagStatus.REJECTED
    )

    logger.info(
        "tag_reviewed",
        record_id=str(record_id),
        tag_id=review.tag_id,
        decision=review.decision.value,
        new_status=new_status.value,
        reviewer=reviewer,
    )

    return TagReviewResponse(
        success=True,
        tag_id=review.tag_id,
        new_status=new_status,
        message=f"Tag {review.decision.value}ed successfully",
    )


@router.post(
    "/{record_id}/tags",
    response_model=TagCreateResponse,
    status_code=status.HTTP_201_CREATED,
    summary="Add or edit a tag",
    description="Add a new tag or edit an existing tag on a record. Validates against taxonomy. Per Spec Section 6.1C.",
)
async def add_or_edit_tag(
    record_id: UUID,
    tag_create: TagCreate,
    db: AsyncSession = Depends(get_db_session),
) -> TagCreateResponse:
    """Add or edit a tag on a record.

    Args:
        record_id: Record UUID
        tag_create: Tag creation/edit request
        db: Database session

    Returns:
        TagCreateResponse with success status, tag, and optional warnings

    Raises:
        HTTPException: 404 if record not found, 400 if validation fails
    """
    service = TagManagementService(db)

    # TODO: Get user from auth context
    user = "current_user"

    success, tag, warnings = await service.add_tag(
        record_id=record_id,
        tag_name=tag_create.name,
        user=user,
        replace_tag_id=tag_create.replace_tag_id,
    )

    if not success:
        error_detail = warnings[0] if warnings else "Tag operation failed"
        if "not found" in error_detail.lower():
            raise HTTPException(
                status_code=status.HTTP_404_NOT_FOUND,
                detail=error_detail,
            )
        else:
            raise HTTPException(
                status_code=status.HTTP_400_BAD_REQUEST,
                detail=error_detail,
            )

    logger.info(
        "tag_created_or_edited",
        record_id=str(record_id),
        tag_name=tag_create.name,
        replace_tag_id=tag_create.replace_tag_id,
        user=user,
        warnings=warnings,
    )

    # Convert dict to TagAssignment for response
    from src.api.schemas.tags import TagAssignment

    tag_assignment = TagAssignment(**tag)

    return TagCreateResponse(
        success=True,
        tag=tag_assignment,
        validation_warnings=warnings,
    )


@router.delete(
    "/{record_id}/tags/{tag_id}",
    status_code=status.HTTP_204_NO_CONTENT,
    summary="Delete a tag",
    description="Soft delete a tag from a record (marks as deleted, preserves history)",
)
async def delete_tag(
    record_id: UUID,
    tag_id: str,
    db: AsyncSession = Depends(get_db_session),
) -> None:
    """Delete a tag from a record (soft delete).

    Args:
        record_id: Record UUID
        tag_id: Tag UUID to delete
        db: Database session

    Raises:
        HTTPException: 404 if record/tag not found
    """
    service = TagManagementService(db)

    # TODO: Get user from auth context
    user = "current_user"

    success, error = await service.delete_tag(
        record_id=record_id,
        tag_id=tag_id,
        user=user,
    )

    if not success:
        if error == "record_not_found":
            raise HTTPException(
                status_code=status.HTTP_404_NOT_FOUND,
                detail=f"Record not found: {record_id}",
            )
        elif error == "tag_not_found":
            raise HTTPException(
                status_code=status.HTTP_404_NOT_FOUND,
                detail=f"Tag not found: {tag_id}",
            )
        else:
            raise HTTPException(
                status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
                detail=f"Delete failed: {error}",
            )

    logger.info(
        "tag_deleted",
        record_id=str(record_id),
        tag_id=tag_id,
        user=user,
    )
