from __future__ import annotations

import logging
import shutil
from pathlib import Path
from typing import Any

from fastapi import (
    APIRouter,
    Depends,
    File,
    Form,
    HTTPException,
    Query,
    Response,
    UploadFile,
)

from app.modules.auth.presentation.auth import require_role
from app.core.postgres.erp_client import ErpDatabaseClient
from app.modules.takeoff.application.drawing_takeoff_service import get_drawing_takeoff_service

from .schemas import STORAGE_VAULT

logger = logging.getLogger("dscons.api.takeoff.export")
router = APIRouter()


@router.get(
    "/{takeoff_id}/export-excel",
    summary="Xuất Toàn Bộ Bảng Bóc Tách Dự Toán BoQ (Phụ Lục 03a) ra File Excel (.xlsx)",
)
def export_takeoff_boq_excel(
    takeoff_id: str,
    current_user: dict[str, Any] = Depends(
        require_role(
            ["superadmin", "director", "manager", "engineer", "staff"]
        )
    ),
) -> Response:
    """Tạo và tải về file Excel (.xlsx) chuẩn dự toán AEC bao gồm bảng BoQ và bảng giá vật liệu thị trường 2026."""
    client = ErpDatabaseClient()
    takeoff = client.get_drawing_takeoff(takeoff_id)
    if not takeoff:
        raise HTTPException(status_code=404, detail="Không tìm thấy hồ sơ bản vẽ")

    try:
        service = get_drawing_takeoff_service()
        excel_bytes = service.export_takeoff_to_excel(takeoff_id)
        safe_code = (
            str(takeoff.get("drawing_code") or "Du_Toan_BoQ")
            .replace(" ", "_")
            .replace(".", "_")
        )
        filename = f"Du_Toan_BoQ_{safe_code}_2026.xlsx"

        return Response(
            content=excel_bytes,
            media_type="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
            headers={
                "Content-Disposition": f'attachment; filename="{filename}"',
            },
        )
    except Exception as e:
        logger.error("[TAKEOFF] Export Excel failed: %s", e)
        raise HTTPException(
            status_code=500, detail=f"Lỗi khi xuất file Excel dự toán: {e!s}"
        )


@router.get(
    "/{takeoff_id}/export-a3-pdf",
    summary="Xuất Bản vẽ Kỹ thuật sang file PDF Khổ A3 Độ Phân Giải Cao (300 DPI)",
)
def export_takeoff_drawing_to_a3_pdf(
    takeoff_id: str,
    orientation: str = Query(
        "landscape", description="Khổ giấy in: landscape hoặc portrait"
    ),
    color_scheme: str = Query(
        "print_ready", description="Chế độ màu: print_ready hoặc dark"
    ),
    dpi: int = Query(300, ge=100, le=600, description="Độ phân giải trang in A3 (DPI)"),
    current_user: dict[str, Any] = Depends(
        require_role(
            ["superadmin", "director", "manager", "engineer", "staff"]
        )
    ),
) -> Response:
    """Tạo và tải về file PDF Khổ A3 chuẩn in ấn thi công (420mm x 297mm)."""
    client = ErpDatabaseClient()
    takeoff = client.get_drawing_takeoff(takeoff_id)
    if not takeoff:
        raise HTTPException(status_code=404, detail="Không tìm thấy hồ sơ bản vẽ")

    file_path_str = takeoff.get("file_path") or ""
    file_url = takeoff.get("file_url") or ""

    file_path: Path | None = None
    if file_path_str and Path(file_path_str).exists():
        file_path = Path(file_path_str)
    elif file_url:
        cand1 = Path(file_url.lstrip("/"))
        cand2 = STORAGE_VAULT / Path(file_url).name
        if cand1.exists():
            file_path = cand1
        elif cand2.exists():
            file_path = cand2

    if not file_path or not file_path.exists():
        raise HTTPException(
            status_code=404, detail="File bản vẽ gốc không tồn tại trên hệ thống"
        )

    try:
        service = get_drawing_takeoff_service()
        pdf_bytes = service.export_drawing_to_a3_pdf(
            file_path=file_path,
            orientation=orientation,
            color_scheme=color_scheme,
            dpi=dpi,
        )
        safe_code = str(takeoff.get("drawing_code") or "BAN_VE").replace(" ", "_")
        filename = f"{safe_code}_Size_A3_{orientation}.pdf"

        return Response(
            content=pdf_bytes,
            media_type="application/pdf",
            headers={
                "Content-Disposition": f'attachment; filename="{filename}"',
                "X-Paper-Size": "A3",
                "X-Dimensions-MM": "420x297"
                if orientation == "landscape"
                else "297x420",
            },
        )
    except Exception as e:
        logger.error("[TAKEOFF] Export A3 PDF failed: %s", e)
        raise HTTPException(status_code=500, detail=f"Lỗi khi xuất PDF A3: {e!s}")


@router.post(
    "/convert-to-a3-pdf",
    summary="Chuyển đổi Trực tiếp File CAD / DWG / DXF sang PDF Khổ A3 (300 DPI)",
)
async def direct_convert_cad_to_a3_pdf(
    file: UploadFile = File(..., description="File CAD DWG, DXF, PDF, PNG"),
    orientation: str = Form("landscape", description="landscape hoặc portrait"),
    color_scheme: str = Form("print_ready", description="print_ready hoặc dark"),
    dpi: int = Form(300, description="DPI"),
    current_user: dict[str, Any] = Depends(
        require_role(
            ["superadmin", "director", "manager", "engineer", "staff"]
        )
    ),
) -> Response:
    """Upload trực tiếp một file CAD và nhận ngay file PDF khổ A3 chuẩn in ấn."""
    if not file.filename:
        raise HTTPException(status_code=400, detail="Tên file không hợp lệ")

    allowed_exts = [".dwg", ".dxf", ".pdf", ".png", ".jpg", ".jpeg", ".webp"]
    file_ext = Path(file.filename).suffix.lower()
    if file_ext not in allowed_exts:
        raise HTTPException(status_code=400, detail="Định dạng file không được hỗ trợ")

    temp_path = STORAGE_VAULT / f"temp_{file.filename}"
    try:
        with open(temp_path, "wb") as buffer:
            shutil.copyfileobj(file.file, buffer)

        service = get_drawing_takeoff_service()
        pdf_bytes = service.export_drawing_to_a3_pdf(
            file_path=temp_path,
            orientation=orientation,
            color_scheme=color_scheme,
            dpi=dpi,
        )
        base_name = Path(file.filename).stem
        out_filename = f"{base_name}_A3_{orientation}.pdf"

        return Response(
            content=pdf_bytes,
            media_type="application/pdf",
            headers={
                "Content-Disposition": f'attachment; filename="{out_filename}"',
                "X-Paper-Size": "A3",
            },
        )
    finally:
        if temp_path.exists():
            try:
                temp_path.unlink()
            except Exception:
                pass
