from typing import Annotated, List, Optional
from fastapi import APIRouter, File, Form, UploadFile, Depends, HTTPException
import structlog

from .models.dto import MenuExtractionResponse
from .service import ImageDocument
from ...shared.middleware.auth import verify_menu_extraction_auth
from ...shared.exceptions.base import ValidationException, MenuExtractionException, RateLimitException

router = APIRouter(prefix="/menu", tags=["menu"])
logger = structlog.get_logger("menu_extraction.routes")

# Service instance will be set by main.py
menu_extraction_service = None


def set_menu_extraction_service(service):
    """Set the menu extraction service instance"""
    global menu_extraction_service
    menu_extraction_service = service


@router.post(
    "/extract",
    response_model=MenuExtractionResponse,
    response_model_exclude_none=True,
    summary="Extract structured menu data from images",
    dependencies=[Depends(verify_menu_extraction_auth)]
)
async def extract_menu(
    files: Annotated[List[UploadFile], File(..., description="One or more menu images.")],
    source_language: Annotated[str, Form()] = "bg",
    target_language: Annotated[str, Form()] = "bg",
    city: Annotated[Optional[str], Form()] = None,
    zavedenia_id: Annotated[Optional[int], Form()] = None,
    openai_api_key: Annotated[Optional[str], Form(description="Optional API key override")] = None,
) -> MenuExtractionResponse:
    """
    Extract structured menu data from images

    BACKWARD COMPATIBLE - Maintains exact same input/output format
    """
    logger.info(
        "menu_extraction_request",
        files_count=len(files),
        source_language=source_language,
        target_language=target_language,
        city=city,
        zavedenia_id=zavedenia_id,
        has_api_key_override=bool(openai_api_key)
    )

    try:
        image_documents: List[ImageDocument] = []
        for upload in files:
            contents = await upload.read()
            image_documents.append(
                ImageDocument(
                    content=contents,
                    mime_type=upload.content_type or "image/jpeg",
                    filename=upload.filename,
                )
            )

        result = await menu_extraction_service.extract_menu(
            images=image_documents,
            source_language=source_language,
            target_language=target_language,
            api_key_override=openai_api_key,
            analytics_context={
                "city": city,
                "zavedenia_id": zavedenia_id,
                "data_input": {
                    "source_language": source_language,
                    "target_language": target_language,
                }
            }
        )

        logger.info(
            "menu_extraction_success",
            files_count=len(files),
            categories_count=len(result.menu.categories),
            model=result.model
        )

        return result

    except ValidationException as e:
        logger.error("menu_extraction_validation_error", error=str(e), files_count=len(files))
        raise HTTPException(status_code=400, detail=str(e.message))
    except RateLimitException as e:
        logger.warning(
            "menu_extraction_rate_limited",
            error=str(e),
            files_count=len(files),
            retry_after=e.details.get("retry_after")
        )
        headers = {}
        retry_after = e.details.get("retry_after")
        if retry_after:
            headers["Retry-After"] = str(retry_after)
        raise HTTPException(status_code=e.status_code, detail=e.message, headers=headers or None)
    except MenuExtractionException as e:
        logger.error("menu_extraction_error", error=str(e), files_count=len(files))
        raise HTTPException(status_code=500, detail=str(e.message))
    except Exception as e:
        logger.error("menu_extraction_unexpected_error", error=str(e), files_count=len(files))
        raise HTTPException(status_code=500, detail=f"Menu extraction failed: {str(e)}")
