"""AEC 3-Way Matching API Router (Đối soát Hóa Đơn <-> Dự Án <-> Giá Sở Xây Dựng Hải Phòng).
Strict Zero-Tolerance Synthetic Data & Decimal(18,4) COMPLIANT.
"""

from __future__ import annotations

import logging
from typing import Any
from fastapi import APIRouter, Depends, HTTPException, Query
from pydantic import BaseModel, Field

from app.modules.auth.presentation.auth import get_current_user, require_role
from app.modules.invoices.application.aec_3way_matching_service import Aec3WayMatchingService

logger = logging.getLogger(__name__)

router = APIRouter(
    prefix="/v1/erp/invoices/3way-matching",
    tags=["ERP - AEC 3-Way Matching & SXD Price Benchmark"]
)


class ConfirmMatchRequest(BaseModel):
    project_id: str = Field(..., description="ID dự án cần khớp nối")
    wbs_id: str | None = Field(None, description="ID hạng mục WBS (tùy chọn)")


class BatchAutoMatchRequest(BaseModel):
    dry_run: bool = Field(True, description="Chế độ xem trước (True) hoặc áp dụng thật (False)")
    max_items: int = Field(500, ge=1, le=2000, description="Số lượng hóa đơn tối đa quét trong đợt này")


@router.get("/summary", summary="Lấy KPI Tổng Hợp 3-Way Matching & Kiểm Toán Giá Sở XD")
def get_3way_summary(
    current_user: dict[str, Any] = Depends(get_current_user),
) -> dict[str, Any]:
    """Tổng hợp 1.031 hóa đơn mua vào (50,3 tỷ), tỷ lệ khớp dự án và rủi ro đơn giá Sở Xây dựng."""
    try:
        service = Aec3WayMatchingService()
        return service.get_matching_summary()
    except Exception as exc:
        logger.error(f"Lỗi lấy summary 3-way matching: {exc}", exc_info=True)
        raise HTTPException(status_code=500, detail=str(exc))


@router.get("/list", summary="Danh Sách Hóa Đơn Mua Vào Phục Vụ Đối Soát")
def list_3way_invoices(
    status: str = Query("ALL", pattern="^(ALL|MATCHED|UNMATCHED)$", description="Trạng thái khớp nối"),
    project_id: str | None = Query(None, description="Lọc theo ID dự án"),
    search: str | None = Query(None, description="Tìm kiếm theo số HĐ, tên nhà cung cấp hoặc ghi chú"),
    limit: int = Query(50, ge=1, le=200),
    offset: int = Query(0, ge=0),
    current_user: dict[str, Any] = Depends(get_current_user),
) -> dict[str, Any]:
    """Truy xuất danh sách hóa đơn mua vào kèm nhãn cảnh báo đơn giá Sở Xây dựng và gợi ý AI."""
    try:
        service = Aec3WayMatchingService()
        return service.list_matching_invoices(
            status=status,
            project_id=project_id,
            search=search,
            limit=limit,
            offset=offset,
        )
    except Exception as exc:
        logger.error(f"Lỗi truy xuất danh sách 3-way matching: {exc}", exc_info=True)
        raise HTTPException(status_code=500, detail=str(exc))


@router.get("/{invoice_id}/audit-detail", summary="Chi Tiết Đối Soát 3 Chiều (Hóa Đơn vs WBS vs Giá Sở XD)")
def get_invoice_audit_detail(
    invoice_id: str,
    current_user: dict[str, Any] = Depends(get_current_user),
) -> dict[str, Any]:
    """Phân rã chi tiết từng dòng hàng: Đơn giá thực tế, Đơn giá Sở Xây dựng tương đương và Chênh lệch."""
    try:
        service = Aec3WayMatchingService()
        return service.get_invoice_audit_detail(invoice_id)
    except ValueError as exc:
        raise HTTPException(status_code=404, detail=str(exc))
    except Exception as exc:
        logger.error(f"Lỗi bóc tách chi tiết 3-way audit: {exc}", exc_info=True)
        raise HTTPException(status_code=500, detail=str(exc))


@router.post("/batch-auto-match", summary="Kích Hoạt Tự Động Khớp Nối AI Hàng Loạt (Dry-Run / Apply)")
def batch_auto_match(
    req: BatchAutoMatchRequest,
    current_user: dict[str, Any] = Depends(
        require_role(["superadmin", "director", "accountant", "pm"])
    ),
) -> dict[str, Any]:
    """Tự động phân bổ hàng loạt các hóa đơn mua vào chưa khớp vào Dự Án & Trụ Cột."""
    try:
        service = Aec3WayMatchingService()
        return service.batch_auto_match(dry_run=req.dry_run, max_items=req.max_items)
    except Exception as exc:
        logger.error(f"Lỗi batch auto match: {exc}", exc_info=True)
        raise HTTPException(status_code=500, detail=str(exc))


@router.post("/{invoice_id}/confirm", summary="Phê Duyệt Khớp Nối Hóa Đơn Vào Dự Án & WBS")
def confirm_invoice_matching(
    invoice_id: str,
    req: ConfirmMatchRequest,
    current_user: dict[str, Any] = Depends(
        require_role(["superadmin", "director", "accountant", "pm"])
    ),
) -> dict[str, Any]:
    """Phê duyệt khớp nối chính thức 1 hóa đơn vào 1 dự án cụ thể."""
    try:
        service = Aec3WayMatchingService()
        user_name = current_user.get("full_name") or current_user.get("email") or "Kế Toán Viên"
        return service.confirm_matching(
            invoice_id=invoice_id,
            project_id=req.project_id,
            wbs_id=req.wbs_id,
            user_name=user_name,
        )
    except ValueError as exc:
        raise HTTPException(status_code=404, detail=str(exc))
    except Exception as exc:
        logger.error(f"Lỗi xác nhận khớp nối hóa đơn: {exc}", exc_info=True)
        raise HTTPException(status_code=500, detail=str(exc))


@router.get("/{invoice_id}/suggestions", summary="Lấy Gợi Ý Top Dự Án Phù Hợp Cho Hóa Đơn")
def get_invoice_project_suggestions(
    invoice_id: str,
    current_user: dict[str, Any] = Depends(get_current_user),
) -> dict[str, Any]:
    """Tính toán và xếp hạng top dự án thông minh phù hợp cho hóa đơn dựa trên vật tư và vị trí."""
    try:
        service = Aec3WayMatchingService()
        return service.get_smart_project_suggestions(invoice_id=invoice_id)
    except ValueError as exc:
        raise HTTPException(status_code=404, detail=str(exc))
    except Exception as exc:
        logger.error(f"Lỗi gợi ý dự án: {exc}", exc_info=True)
        raise HTTPException(status_code=500, detail=str(exc))


class ItemAllocationItem(BaseModel):
    invoice_item_id: str | None = None
    project_id: str = Field(..., description="ID dự án nhận phân bổ")
    allocated_quantity: float = Field(0.0, ge=0)
    allocated_total_amount_vnd: float = Field(..., gt=0, description="Số tiền thanh toán phân bổ cho dự án")
    notes: str | None = None


class MultiAllocationRequest(BaseModel):
    allocations: list[ItemAllocationItem] = Field(..., min_length=1)


@router.get("/{invoice_id}/allocations", summary="Lấy Danh Sách Phân Bổ Đa Dự Án Của Hóa Đơn")
def get_invoice_allocations_endpoint(
    invoice_id: str,
    current_user: dict[str, Any] = Depends(get_current_user),
) -> dict[str, Any]:
    """Truy vấn bảng phân bổ chi phí đa dự án cho hóa đơn này."""
    try:
        service = Aec3WayMatchingService()
        return service.get_invoice_allocations(invoice_id=invoice_id)
    except ValueError as exc:
        raise HTTPException(status_code=404, detail=str(exc))
    except Exception as exc:
        logger.error(f"Lỗi truy vấn phân bổ đa dự án: {exc}", exc_info=True)
        raise HTTPException(status_code=500, detail=str(exc))


@router.post("/{invoice_id}/allocations", summary="Lưu Bảng Phân Bổ Đa Dự Án Cho Hóa Đơn")
def save_invoice_allocations_endpoint(
    invoice_id: str,
    req: MultiAllocationRequest,
    current_user: dict[str, Any] = Depends(
        require_role(["superadmin", "director", "accountant", "pm"])
    ),
) -> dict[str, Any]:
    """Phân bổ hóa đơn đầu vào cho nhiều dự án / nhiều công trình khác nhau."""
    try:
        service = Aec3WayMatchingService()
        user_name = current_user.get("full_name") or current_user.get("email") or "Kế Toán Viên"
        alloc_dicts = [a.model_dump() for a in req.allocations]
        return service.save_invoice_multi_allocations(
            invoice_id=invoice_id,
            allocations=alloc_dicts,
            user_name=user_name,
        )
    except ValueError as exc:
        raise HTTPException(status_code=400, detail=str(exc))
    except Exception as exc:
        logger.error(f"Lỗi lưu phân bổ đa dự án: {exc}", exc_info=True)
        raise HTTPException(status_code=500, detail=str(exc))


