"""
Labeling API Routes

FastAPI endpoints for pre-labeling documents with expected field values.
"""

from __future__ import annotations

import json
import logging
from pathlib import Path
from typing import TYPE_CHECKING

from fastapi import APIRouter, Depends, File, Form, HTTPException, UploadFile, status

from backend.data.repositories import DocumentRepository
from backend.web.schemas.labeling import PreLabelResponse
from backend.web.schemas.common import ErrorResponse
from backend.web.services.storage_helpers import get_storage_helper

if TYPE_CHECKING:
    from backend.web.services import InferenceService
    from backend.web.config import StorageConfig

logger = logging.getLogger(__name__)


def _convert_pdf_to_images(
    document_id: str, content: bytes, page_count: int, dpi: int
) -> None:
    """Convert PDF pages to images for annotation using StorageHelper."""
    import fitz

    storage = get_storage_helper()
    pdf_doc = fitz.open(stream=content, filetype="pdf")

    for page_num in range(page_count):
        page = pdf_doc[page_num]
        mat = fitz.Matrix(dpi / 72, dpi / 72)
        pix = page.get_pixmap(matrix=mat)

        # Save to storage using StorageHelper
        image_bytes = pix.tobytes("png")
        storage.save_admin_image(document_id, page_num + 1, image_bytes)

    pdf_doc.close()


def get_doc_repository() -> DocumentRepository:
    """Get document repository instance."""
    return DocumentRepository()


def create_labeling_router(
    inference_service: "InferenceService",
    storage_config: "StorageConfig",
) -> APIRouter:
    """
    Create API router with labeling endpoints.

    Args:
        inference_service: Inference service instance
        storage_config: Storage configuration

    Returns:
        Configured APIRouter
    """
    router = APIRouter(prefix="/api/v1", tags=["labeling"])

    @router.post(
        "/pre-label",
        response_model=PreLabelResponse,
        responses={
            400: {"model": ErrorResponse, "description": "Invalid file or field values"},
            500: {"model": ErrorResponse, "description": "Processing error"},
        },
        summary="Pre-label document with expected values",
        description="Upload a document with expected field values for pre-labeling. Returns document_id for result retrieval.",
    )
    async def pre_label(
        file: UploadFile = File(..., description="PDF or image file to process"),
        field_values: str = Form(
            ...,
            description="JSON object with expected field values. "
            "Keys: InvoiceNumber, InvoiceDate, InvoiceDueDate, Amount, OCR, "
            "Bankgiro, Plusgiro, customer_number, supplier_organisation_number",
        ),
        doc_repo: DocumentRepository = Depends(get_doc_repository),
    ) -> PreLabelResponse:
        """
        Upload a document with expected field values for pre-labeling.

        Returns document_id which can be used to retrieve results later.

        Example field_values JSON:
        ```json
        {
            "InvoiceNumber": "12345",
            "Amount": "1500.00",
            "Bankgiro": "123-4567",
            "OCR": "1234567890"
        }
        ```
        """
        # Parse field_values JSON
        try:
            expected_values = json.loads(field_values)
            if not isinstance(expected_values, dict):
                raise ValueError("field_values must be a JSON object")
        except json.JSONDecodeError as e:
            raise HTTPException(
                status_code=status.HTTP_400_BAD_REQUEST,
                detail=f"Invalid JSON in field_values: {e}",
            )

        # Validate file extension
        if not file.filename:
            raise HTTPException(
                status_code=status.HTTP_400_BAD_REQUEST,
                detail="Filename is required",
            )

        file_ext = Path(file.filename).suffix.lower()
        if file_ext not in storage_config.allowed_extensions:
            raise HTTPException(
                status_code=status.HTTP_400_BAD_REQUEST,
                detail=f"Unsupported file type: {file_ext}. Allowed: {storage_config.allowed_extensions}",
            )

        # Read file content
        try:
            content = await file.read()
        except Exception as e:
            logger.error(f"Failed to read uploaded file: {e}")
            raise HTTPException(
                status_code=status.HTTP_400_BAD_REQUEST,
                detail="Failed to read file",
            )

        # Get page count for PDF
        page_count = 1
        if file_ext == ".pdf":
            try:
                import fitz
                pdf_doc = fitz.open(stream=content, filetype="pdf")
                page_count = len(pdf_doc)
                pdf_doc.close()
            except Exception as e:
                logger.warning(f"Failed to get PDF page count: {e}")

        # Create document record with field_values
        document_id = doc_repo.create(
            filename=file.filename,
            file_size=len(content),
            content_type=file.content_type or "application/octet-stream",
            file_path="",  # Will update after saving
            page_count=page_count,
            upload_source="api",
            csv_field_values=expected_values,
        )

        # Save file to storage using StorageHelper
        storage = get_storage_helper()
        filename = f"{document_id}{file_ext}"
        try:
            storage_path = storage.save_raw_pdf(content, filename)
        except Exception as e:
            logger.error(f"Failed to save file: {e}")
            raise HTTPException(
                status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
                detail="Failed to save file",
            )

        # Update file path in database (using storage path)
        doc_repo.update_file_path(document_id, storage_path)

        # Convert PDF to images for annotation UI
        if file_ext == ".pdf":
            try:
                _convert_pdf_to_images(
                    document_id, content, page_count, storage_config.dpi
                )
            except Exception as e:
                logger.error(f"Failed to convert PDF to images: {e}")

        # Trigger auto-labeling
        doc_repo.update_status(
            document_id=document_id,
            status="auto_labeling",
            auto_label_status="pending",
        )

        logger.info(f"Pre-label document {document_id} created with {len(expected_values)} expected fields")

        return PreLabelResponse(document_id=document_id)

    return router
