from fastapi import APIRouter, Depends, File, Query, UploadFile
from app.utils.pdf_response import pdf_file_response
from sqlalchemy.orm import Session

from app.api.deps import require_super_admin
from app.db.session import get_db
from app.schemas.parser_lab import (
    ReExtractRequest,
    SaveParserCorrectionsRequest,
    ResolveBboxRequest,
    SavePatternRequest,
    SaveTrainingExampleRequest,
    SuggestPatternRequest,
    TestPatternRequest,
)
from app.schemas.user_context import CurrentUser
from app.services.parser_lab_service import ParserLabService
from app.services.parser_training_service import ParserTrainingService
from app.services.upload_service import UploadService

router = APIRouter()


@router.get("/fields")
def get_field_definitions(current_user: CurrentUser = Depends(require_super_admin)):
    from app.schemas.parser_lab import KEY_PARSER_FIELDS, PARSER_LAB_FIELD_DEFINITIONS

    return {
        "sections": PARSER_LAB_FIELD_DEFINITIONS,
        "key_fields": KEY_PARSER_FIELDS,
    }


@router.get("/parsers")
def list_registered_parsers(
    current_user: CurrentUser = Depends(require_super_admin),
    db: Session = Depends(get_db),
):
    return ParserLabService(db).list_parsers()


@router.get("/extractions")
def list_extractions(
    limit: int = Query(30, ge=1, le=100),
    current_user: CurrentUser = Depends(require_super_admin),
    db: Session = Depends(get_db),
):
    return ParserLabService(db).list_extractions(current_user.agency_id, limit=limit)


@router.post("/pdf")
async def upload_pdf_for_lab(
    file: UploadFile = File(...),
    current_user: CurrentUser = Depends(require_super_admin),
    db: Session = Depends(get_db),
):
    content = await file.read()
    return ParserLabService(db).extract_pdf(content, file.filename or "policy.pdf", current_user.id, current_user.agency_id)


@router.get("/extraction/{extraction_id}")
def get_extraction_detail(
    extraction_id: int,
    current_user: CurrentUser = Depends(require_super_admin),
    db: Session = Depends(get_db),
):
    return ParserLabService(db).get_extraction_detail(extraction_id, current_user.agency_id)


@router.get("/extraction/{extraction_id}/pdf")
def get_extraction_pdf(
    extraction_id: int,
    current_user: CurrentUser = Depends(require_super_admin),
    db: Session = Depends(get_db),
):
    path, filename = UploadService(db).get_extraction_pdf_path(extraction_id, current_user.agency_id)
    return pdf_file_response(path, filename)


@router.post("/extraction/{extraction_id}/re-extract")
def re_extract(
    extraction_id: int,
    payload: ReExtractRequest,
    current_user: CurrentUser = Depends(require_super_admin),
    db: Session = Depends(get_db),
):
    return ParserLabService(db).re_extract(extraction_id, payload, current_user.agency_id)


@router.post("/extraction/{extraction_id}/corrections")
def save_corrections(
    extraction_id: int,
    payload: SaveParserCorrectionsRequest,
    current_user: CurrentUser = Depends(require_super_admin),
    db: Session = Depends(get_db),
):
    return ParserLabService(db).save_corrections(
        extraction_id,
        current_user.agency_id,
        current_user.id,
        payload,
    )


@router.get("/extraction/{extraction_id}/pdf-meta")
def get_extraction_pdf_meta(
    extraction_id: int,
    current_user: CurrentUser = Depends(require_super_admin),
    db: Session = Depends(get_db),
):
    return {"pages": ParserTrainingService(db).get_pdf_page_meta(extraction_id, current_user.agency_id)}


@router.post("/extraction/{extraction_id}/resolve-bbox")
def resolve_bbox(
    extraction_id: int,
    payload: ResolveBboxRequest,
    current_user: CurrentUser = Depends(require_super_admin),
    db: Session = Depends(get_db),
):
    return ParserTrainingService(db).resolve_bbox(
        extraction_id,
        current_user.agency_id,
        page=payload.page,
        bbox=payload.bbox.model_dump(),
    )


@router.post("/extraction/{extraction_id}/training-examples")
def save_training_example(
    extraction_id: int,
    payload: SaveTrainingExampleRequest,
    current_user: CurrentUser = Depends(require_super_admin),
    db: Session = Depends(get_db),
):
    return ParserTrainingService(db).save_training_example(
        extraction_id,
        current_user.agency_id,
        current_user.id,
        field_name=payload.field_name,
        selection_start=payload.selection_start,
        selection_end=payload.selection_end,
        company_code=payload.company_code,
        page=payload.page,
        notes=payload.notes,
        bbox=payload.bbox.model_dump() if payload.bbox else None,
    )


@router.get("/training-examples")
def list_training_examples(
    extraction_id: int | None = None,
    company_code: str | None = None,
    limit: int = Query(100, ge=1, le=500),
    current_user: CurrentUser = Depends(require_super_admin),
    db: Session = Depends(get_db),
):
    return ParserTrainingService(db).list_training_examples(
        current_user.agency_id,
        extraction_id=extraction_id,
        company_code=company_code,
        limit=limit,
    )


@router.post("/patterns/suggest")
def suggest_pattern(
    payload: SuggestPatternRequest,
    current_user: CurrentUser = Depends(require_super_admin),
    db: Session = Depends(get_db),
):
    return ParserTrainingService(db).suggest_pattern(
        field_name=payload.field_name,
        value=payload.value,
        anchor_before=payload.anchor_before,
        anchor_after=payload.anchor_after,
        training_example_id=payload.training_example_id,
        agency_id=current_user.agency_id,
    )


@router.post("/patterns/test")
def test_pattern(
    payload: TestPatternRequest,
    current_user: CurrentUser = Depends(require_super_admin),
    db: Session = Depends(get_db),
):
    return ParserTrainingService(db).test_pattern(
        regex=payload.regex,
        company_code=payload.company_code,
        field_name=payload.field_name,
        extraction_id=payload.extraction_id,
        agency_id=current_user.agency_id,
    )


@router.post("/patterns")
def save_pattern(
    payload: SavePatternRequest,
    current_user: CurrentUser = Depends(require_super_admin),
    db: Session = Depends(get_db),
):
    return ParserTrainingService(db).save_pattern(
        current_user.agency_id,
        current_user.id,
        company_code=payload.company_code,
        field_name=payload.field_name,
        regex=payload.regex,
        page_hint=payload.page_hint,
        priority=payload.priority,
        source_training_example_id=payload.source_training_example_id,
        notes=payload.notes,
        require_sample_pass=payload.require_sample_pass,
    )


@router.get("/patterns")
def list_patterns(
    company_code: str | None = None,
    active_only: bool = True,
    limit: int = Query(100, ge=1, le=500),
    current_user: CurrentUser = Depends(require_super_admin),
    db: Session = Depends(get_db),
):
    return ParserTrainingService(db).list_patterns(
        current_user.agency_id,
        company_code=company_code,
        active_only=active_only,
        limit=limit,
    )


@router.get("/patterns/{pattern_id}/promote-preview")
def promote_pattern_preview(
    pattern_id: int,
    current_user: CurrentUser = Depends(require_super_admin),
    db: Session = Depends(get_db),
):
    return ParserTrainingService(db).promote_pattern_preview(pattern_id, current_user.agency_id)


@router.delete("/patterns/{pattern_id}")
def deactivate_pattern(
    pattern_id: int,
    current_user: CurrentUser = Depends(require_super_admin),
    db: Session = Depends(get_db),
):
    return ParserTrainingService(db).deactivate_pattern(pattern_id, current_user.agency_id)


@router.get("/training/export")
def export_training(
    company_code: str | None = None,
    current_user: CurrentUser = Depends(require_super_admin),
    db: Session = Depends(get_db),
):
    return ParserTrainingService(db).export_training(current_user.agency_id, company_code)


@router.get("/corrections/stats")
def correction_stats(
    company_code: str | None = None,
    current_user: CurrentUser = Depends(require_super_admin),
    db: Session = Depends(get_db),
):
    return ParserLabService(db).correction_stats(current_user.agency_id, company_code)


@router.get("/corrections")
def list_corrections(
    company_code: str | None = None,
    limit: int = Query(50, ge=1, le=200),
    current_user: CurrentUser = Depends(require_super_admin),
    db: Session = Depends(get_db),
):
    return ParserLabService(db).list_corrections(current_user.agency_id, company_code, limit)


@router.get("/corrections/export")
def export_corrections(
    company_code: str | None = None,
    current_user: CurrentUser = Depends(require_super_admin),
    db: Session = Depends(get_db),
):
    return {"items": ParserLabService(db).export_corrections(current_user.agency_id, company_code)}
