import logging
from sqlalchemy.ext.asyncio import AsyncSession
from sqlalchemy import select

from .parser import identify_supplier
from .azure_extractor import process_invoice_with_azure
from services.duplicate_detector import detect_document_type
from services.pdf_rotation import rotate_pdf_pages

logger = logging.getLogger(__name__)


async def process_invoice_image(
    image_path: str,
    kitchen_id: int,
    db: AsyncSession
) -> dict:
    """
    Process an invoice image through Azure OCR and extract relevant fields.

    Args:
        image_path: Path to the invoice image
        kitchen_id: ID of the kitchen for supplier matching
        db: Database session for supplier lookup

    Returns:
        dict with extracted fields:
            - invoice_number: str or None
            - invoice_date: date or None
            - total: Decimal or None
            - supplier_id: int or None
            - supplier_match_type: str ("exact", "fuzzy") or None
            - vendor_name: str or None
            - order_number: str or None
            - document_type: str ("invoice" or "delivery_note")
            - line_items: list
            - raw_text: str
            - raw_json: dict (serialized Azure response)
            - confidence: float
    """
    # Check kitchen settings for Azure credentials
    from models.settings import KitchenSettings
    settings_result = await db.execute(
        select(KitchenSettings).where(KitchenSettings.kitchen_id == kitchen_id)
    )
    settings = settings_result.scalar_one_or_none()

    # Require Azure configuration
    if not settings or not settings.azure_endpoint or not settings.azure_key:
        logger.error("Azure credentials not configured for kitchen")
        return {
            "invoice_number": None,
            "invoice_date": None,
            "total": None,
            "net_total": None,
            "supplier_id": None,
            "supplier_match_type": None,
            "vendor_name": None,
            "order_number": None,
            "document_type": "invoice",
            "line_items": [],
            "raw_text": "Error: Azure credentials not configured. Please configure in Settings.",
            "raw_json": None,
            "confidence": 0.0
        }

    logger.info("Using Azure Document Intelligence for OCR")

    try:
        result = await process_invoice_with_azure(
            image_path,
            settings.azure_endpoint,
            settings.azure_key,
            clean_product_codes=settings.ocr_clean_product_codes,
            filter_subtotal_rows=settings.ocr_filter_subtotal_rows,
            use_weight_as_quantity=settings.ocr_use_weight_as_quantity
        )

        # FIRST post-processing step: Rotate PDF pages with non-zero angles
        # This must happen BEFORE any other processing extracts data from raw_json
        # because coordinates need to be transformed to match the corrected orientation
        if image_path.lower().endswith('.pdf') and result.get('raw_json'):
            try:
                modified, updated_json = rotate_pdf_pages(image_path, result['raw_json'])
                if modified:
                    result['raw_json'] = updated_json
                    logger.info(f"PDF pages rotated and coordinates transformed for {image_path}")
            except Exception as e:
                logger.warning(f"PDF rotation failed (non-fatal): {e}")

        # Try to identify/match supplier from vendor name
        supplier_id = None
        supplier_match_type = None
        if result.get("vendor_name"):
            supplier_id, supplier_match_type = await identify_supplier(result["vendor_name"], kitchen_id, db)
        if not supplier_id and result.get("raw_text"):
            supplier_id, supplier_match_type = await identify_supplier(result["raw_text"], kitchen_id, db)

        # Use document_type from azure_extractor (already detected there)
        # Fall back to detect_document_type only if not provided
        document_type = result.get("document_type")
        if not document_type:
            document_type = detect_document_type(
                result.get("raw_text", ""),
                result
            )

        # LLM FEATURE — see LLM-MANIFEST.md for removal instructions
        # Feature E: LLM fallback when Azure returns null for header fields
        invoice_number = result.get("invoice_number")
        invoice_date = result.get("invoice_date")
        total = result.get("total")
        any_null = invoice_number is None or invoice_date is None or total is None

        if any_null and result.get("raw_text"):
            try:
                from services.llm_service import extract_invoice_fields_llm
                llm_result = await extract_invoice_fields_llm(
                    db=db,
                    kitchen_id=kitchen_id,
                    raw_text=result["raw_text"],
                )
                if llm_result["status"] in ("success", "cached") and llm_result.get("fields"):
                    fields = llm_result["fields"]
                    if invoice_number is None and fields.get("invoice_number"):
                        invoice_number = fields["invoice_number"]
                        logger.info(f"LLM extracted invoice_number: {invoice_number}")
                    if invoice_date is None and fields.get("invoice_date"):
                        invoice_date = fields["invoice_date"]
                        logger.info(f"LLM extracted invoice_date: {invoice_date}")
                    if total is None and fields.get("total"):
                        total = fields["total"]
                        logger.info(f"LLM extracted total: {total}")
            except Exception as llm_err:
                logger.warning(f"LLM field extraction fallback failed (non-fatal): {llm_err}")

        logger.info(f"Processed invoice: number={invoice_number}, "
                    f"type={document_type}, supplier_id={supplier_id}, match_type={supplier_match_type}")

        return {
            "invoice_number": invoice_number,
            "invoice_date": invoice_date,
            "total": total,
            "net_total": result.get("net_total"),
            "supplier_id": supplier_id,
            "supplier_match_type": supplier_match_type,
            "vendor_name": result.get("vendor_name"),
            "order_number": result.get("order_number"),
            "document_type": document_type,
            "line_items": result.get("line_items", []),
            "raw_text": result.get("raw_text", ""),
            "raw_json": result.get("raw_json"),
            "confidence": result.get("confidence", 0.0)
        }

    except Exception as e:
        logger.error(f"Azure OCR failed: {e}")
        return {
            "invoice_number": None,
            "invoice_date": None,
            "total": None,
            "net_total": None,
            "supplier_id": None,
            "supplier_match_type": None,
            "vendor_name": None,
            "order_number": None,
            "document_type": "invoice",
            "line_items": [],
            "raw_text": f"Error: Azure OCR failed - {str(e)}",
            "raw_json": None,
            "confidence": 0.0
        }
