from __future__ import annotations

import logging
import os
import shutil
from pathlib import Path
from typing import Any

from fastapi import (
    APIRouter,
    BackgroundTasks,
    Depends,
    File,
    Form,
    HTTPException,
    UploadFile,
    status,
)

from app.modules.auth.presentation.auth import require_role
from app.modules.takeoff.application.drawing_takeoff_service import get_drawing_takeoff_service

from .schemas import STORAGE_VAULT

logger = logging.getLogger("dscons.api.takeoff.upload_batch")
router = APIRouter()


def is_hsmt_file(filename: str) -> bool:
    """Kiểm tra xem file có phải là Hồ sơ mời thầu / Biểu giá / Tiên lượng dự toán hay không."""
    fn_lower = filename.lower()
    ext = Path(filename).suffix.lower()
    if ext in [".xlsx", ".xls", ".doc", ".docx", ".csv"]:
        return True
    if ext == ".pdf":
        hsmt_keywords = [
            "tiên lượng",
            "tien luong",
            "dự toán",
            "du toan",
            "hsmt",
            "mời thầu",
            "moi thau",
            "biểu giá",
            "bieu gia",
            "báo cáo ktkt",
            "bao cao ktkt",
            "thuyết minh",
            "thuyet minh",
            "bctm",
            "tổng hợp",
            "tong hop",
            "dutoan",
            "bang gia",
            "bảng giá",
        ]
        return any(kw in fn_lower for kw in hsmt_keywords)
    return False


@router.post(
    "/upload-batch",
    summary="Tải lên Nhiều Bản Vẽ Kỹ Thuật & Hồ Sơ Mời Thầu Cùng Lúc (Batch Upload) & Ghép Cặp Khớp Nối Kép",
    status_code=status.HTTP_201_CREATED,
)
async def upload_batch_drawings(
    background_tasks: BackgroundTasks,
    files: list[UploadFile] = File(
        ...,
        description="Danh sách các file bản vẽ CAD/PDF và file HSMT/Dự toán Excel/Word",
    ),
    project_id: str | None = Form(None, description="Mã UUID Dự án (tùy chọn)"),
    document_id: str | None = Form(
        None, description="Mã UUID Văn bản liên kết (tùy chọn)"
    ),
    drawing_hint: str = Form("", description="Ghi chú cấu kiện / loại móng chung"),
    auto_analyze: bool = Form(
        True, description="Tự động chạy tiến trình AI bóc tách ngầm"
    ),
    current_user: dict[str, Any] = Depends(
        require_role(
            ["superadmin", "director", "manager", "engineer", "staff"]
        )
    ),
) -> dict[str, Any]:
    """Tải lên đồng thời nhiều file, tự động phân loại Bản vẽ vs HSMT/Dự toán và kích hoạt quy trình khớp nối kép 100%."""
    if not files or len(files) == 0:
        raise HTTPException(status_code=400, detail="Không có file nào được chọn")

    logger.info(
        "[TAKEOFF] upload_batch_drawings received %d files: %s",
        len(files),
        [(getattr(f, "filename", None), getattr(f, "size", None)) for f in files],
    )

    allowed_exts = [
        ".dwg",
        ".dxf",
        ".pdf",
        ".png",
        ".jpg",
        ".jpeg",
        ".webp",
        ".xlsx",
        ".xls",
        ".doc",
        ".docx",
        ".csv",
    ]
    service = get_drawing_takeoff_service()

    # 1. Save all uploaded files to secure storage first and classify content
    saved_files: list[dict[str, Any]] = []
    errors: list[dict[str, str]] = []

    for f in files:
        if not f.filename:
            continue
        file_ext = Path(f.filename).suffix.lower()
        if file_ext not in allowed_exts:
            errors.append(
                {
                    "filename": f.filename,
                    "error": f"Định dạng '{file_ext}' không được hỗ trợ",
                }
            )
            continue

        safe_name = f"{Path(f.filename).stem}_{os.urandom(4).hex()}{file_ext}"
        dest_path = STORAGE_VAULT / safe_name
        try:
            import asyncio

            def save_file():
                with open(dest_path, "wb") as buffer:
                    shutil.copyfileobj(f.file, buffer)

            await asyncio.to_thread(save_file)

            saved_files.append(
                {
                    "path": dest_path,
                    "filename": f.filename,
                    "ext": file_ext,
                }
            )
        except Exception as e:
            logger.error("[TAKEOFF] Lỗi lưu file '%s': %s", f.filename, e)
            errors.append({"filename": f.filename, "error": str(e)})

    # 2. Classify saved files using extension + Deep PDF Content Inspection
    drawing_files: list[dict[str, Any]] = []
    hsmt_files: list[dict[str, Any]] = []

    for sf in saved_files:
        ext = sf["ext"]
        if ext in [".xlsx", ".xls", ".doc", ".docx", ".csv"]:
            hsmt_files.append(sf)
        elif ext in [".dwg", ".dxf", ".png", ".jpg", ".jpeg", ".webp"]:
            drawing_files.append(sf)
        elif ext == ".pdf":
            # Deep inspection of PDF internal structure (A3 Landscape vector drawing vs A4 Portrait text/table)
            import asyncio

            pdf_class = await asyncio.to_thread(
                service.classify_pdf_content_type, sf["path"]
            )
            if pdf_class.get("is_hsmt", False):
                sf["classification_reason"] = pdf_class.get("summary_reason", "")
                hsmt_files.append(sf)
            else:
                drawing_files.append(sf)

    # Edge case: If all uploaded files are classified as HSMT (0 drawings)
    if not drawing_files and hsmt_files:
        raise HTTPException(
            status_code=400,
            detail="Vui lòng tải lên ít nhất một file Bản vẽ kỹ thuật (CAD/PDF) kèm theo Hồ sơ mời thầu để AI Quỳnh tiến hành bóc tách.",
        )

    # 3. Process Drawing files and pair with matching HSMT
    created_takeoffs: list[dict[str, Any]] = []
    for df in drawing_files:
        # Smart pairing: prioritize files with BoQ / Biểu mẫu / Dự toán keywords over administrative decisions
        matched_hsmt = None
        if len(hsmt_files) >= 1:
            boq_keywords = [
                "biểu mẫu", "bieu_mau", "bieu mau", "dự toán", "du_toan", "du toan",
                "tiên lượng", "tien_luong", "tien luong", "boq", "khối lượng", "khoi_luong",
                "phụ lục", "phu_luc", "phu luc", "mẫu số 01", "mau so 01"
            ]
            non_boq_prefixes = ["qd", "quyet dinh", "bảo lãnh", "bao lanh", "thư thu xếp", "thu thu xep", "tờ trình", "to trinh"]
            df_stem = Path(df["filename"]).stem.lower()

            # 1. Match BoQ keywords
            for h in hsmt_files:
                fname = Path(h["filename"]).stem.lower()
                if any(kw in fname for kw in boq_keywords):
                    matched_hsmt = h
                    break

            # 2. Match drawing stem keywords
            if not matched_hsmt and df_stem:
                for h in hsmt_files:
                    h_stem = Path(h["filename"]).stem.lower()
                    if any(w in df_stem for w in h_stem.split() if len(w) > 3):
                        matched_hsmt = h
                        break

            # 3. Filter out administrative documents
            if not matched_hsmt:
                for h in hsmt_files:
                    fname = Path(h["filename"]).stem.lower()
                    if not any(pref in fname for pref in non_boq_prefixes):
                        matched_hsmt = h
                        break

            # 4. Fallback to first file
            if not matched_hsmt:
                matched_hsmt = hsmt_files[0]

        created = service.create_pending_takeoff(
            file_path=df["path"],
            filename=df["filename"],
            project_id=project_id,
            document_id=document_id,
            drawing_hint=drawing_hint,
        )
        takeoff_id = str(created["id"])

        if matched_hsmt:
            created["attached_hsmt_file"] = matched_hsmt["filename"]

        # Robust boolean parsing for form data
        if isinstance(auto_analyze, str):
            is_auto_analyze = auto_analyze.strip().lower() not in (
                "false",
                "0",
                "no",
                "f",
                "off",
            )
        else:
            is_auto_analyze = bool(auto_analyze)

        if is_auto_analyze:
            background_tasks.add_task(
                service.run_takeoff_pipeline,
                takeoff_id=takeoff_id,
                drawing_hint=drawing_hint,
                attached_hsmt_path=str(matched_hsmt["path"]) if matched_hsmt else None,
                attached_hsmt_filename=matched_hsmt["filename"]
                if matched_hsmt
                else None,
            )

        created_takeoffs.append(created)

    msg = f"Đã tiếp nhận {len(created_takeoffs)} bản vẽ kỹ thuật thành công."
    if hsmt_files:
        msg = f"Đã tự động phân loại {len(created_takeoffs)} Bản vẽ và {len(hsmt_files)} Hồ sơ mời thầu/Dự toán kèm theo để khớp nối kép 100%!"

    return {
        "status": "success",
        "message": msg,
        "count": len(created_takeoffs),
        "drawings_count": len(created_takeoffs),
        "hsmts_count": len(hsmt_files),
        "takeoffs": created_takeoffs,
        "errors": errors,
        "is_async": is_auto_analyze,
    }
