"""
财务票据域路由 —— /api/finance
薄路由层：参数解析 + 调用 Service + 包装响应
"""
from __future__ import annotations
import uuid
import os
import time
import base64
from fastapi import APIRouter, Depends, Query, Body, File, UploadFile, Form
from sqlalchemy.ext.asyncio import AsyncSession
from app.api.deps import get_current_user
from app.db.database import get_db
from app.schemas.auth import CurrentUserPayload
from app.schemas.finance import ExpenseCreate, ExpenseStatusUpdate, InvoiceCreate
from app.schemas.response import ok
from app.core.exceptions import BizException
from app.services import finance_service as svc

router = APIRouter(prefix="/finance", tags=["财务票据"])


@router.post("/ocr", summary="上传票据图片并做 AI 发票/名片 OCR 识别")
async def ocr_recognize(
    file: UploadFile = File(...),
    scene: str = Form("invoice"),
    current_user: CurrentUserPayload = Depends(get_current_user),
) -> dict:
    from app.services.ocr_service import ocr_image
    
    # 读取并在本地保存原始文件
    file_bytes = await file.read()
    
    upload_dir = "uploads/finance"
    os.makedirs(upload_dir, exist_ok=True)
    ext = os.path.splitext(file.filename or "")[1].lower() or ".png"
    ts = int(time.time())
    safe_filename = f"{ts}_{current_user.user_id}{ext}"
    file_path = os.path.join(upload_dir, safe_filename)
    
    with open(file_path, "wb") as f:
        f.write(file_bytes)
        
    file_url = f"/uploads/finance/{safe_filename}"
    
    # 仅支持图片（png/jpg/jpeg）和 PDF，不再支持 MD/TXT
    supported = {".png", ".jpg", ".jpeg", ".pdf"}
    if ext not in supported:
        raise BizException(message=f"不支持的文件格式 {ext}，仅支持: {', '.join(supported)}")
    
    # 如果是 PDF，转成 PNG 再做 OCR
    ocr_bytes = file_bytes
    if ext == ".pdf":
        try:
            import fitz  # PyMuPDF
            doc = fitz.open(stream=file_bytes, filetype="pdf")
            page = doc[0]  # 取第一页
            # 中等分辨率渲染（150 DPI，平衡质量与大小）
            pix = page.get_pixmap(dpi=150)
            ocr_bytes = pix.tobytes("png")
            doc.close()
            print(f"[OCR] PDF 转 PNG 成功: {len(ocr_bytes)} bytes")
        except Exception as e:
            print(f"[OCR] PDF 转换失败: {e}")
            return ok(data={"ocr_data": {}, "file_url": file_url}, message=f"PDF 转换失败: {e}")
    
    # 转换为纯 base64 传给 OCR
    image_base64 = base64.b64encode(ocr_bytes).decode("utf-8")
    result = await ocr_image(image_base64, scene)

    if result.get("success"):
        return ok(data={"ocr_data": result["data"], "file_url": file_url}, message="AI OCR 识别成功")
    return ok(data={"ocr_data": result.get("data", {}), "file_url": file_url}, message=result.get("error", "OCR 识别失败"))


@router.post("/invoices", summary="上传票据入池（含 AI/OCR JSONB 数据）")
async def create_invoice(
    body: InvoiceCreate,
    db: AsyncSession = Depends(get_db),
    current_user: CurrentUserPayload = Depends(get_current_user),
) -> dict:
    result = await svc.create_invoice(db, current_user, body)
    return ok(data=result.model_dump(mode="json"), message="票据入池成功")


@router.get("/invoices", summary="票据池列表（数据权限隔离）")
async def list_invoices(
    page: int = Query(1, ge=1),
    size: int = Query(20, ge=1, le=100),
    type: str | None = Query(None, alias="category", pattern=r"^(expense|customer)$"),
    is_used: bool | None = Query(None),
    db: AsyncSession = Depends(get_db),
    current_user: CurrentUserPayload = Depends(get_current_user),
) -> dict:
    result = await svc.list_invoices(db, current_user, page, size, type, is_used)
    return ok(data=result.model_dump(mode="json"))


@router.delete("/invoices/{invoice_id}", summary="作废票据（软删除）")
async def void_invoice(
    invoice_id: uuid.UUID,
    db: AsyncSession = Depends(get_db),
    current_user: CurrentUserPayload = Depends(get_current_user),
) -> dict:
    await svc.void_invoice(db, current_user, invoice_id)
    return ok(message="票据已作废")


@router.post("/expenses", summary="生成报销单（防重锁定 + 强事务）")
async def create_expense(
    body: ExpenseCreate,
    db: AsyncSession = Depends(get_db),
    current_user: CurrentUserPayload = Depends(get_current_user),
) -> dict:
    result = await svc.create_expense(db, current_user, body)
    return ok(data=result.model_dump(mode="json"), message=f"报销单 {result.system_no} 提交成功")


@router.get("/expenses", summary="报销单大盘（多角色数据权限）")
async def list_expenses(
    page: int = Query(1, ge=1),
    size: int = Query(20, ge=1, le=100),
    status: str | None = Query(None, pattern=r"^(submitted|approved|rejected|voided)$"),
    applicant_id: uuid.UUID | None = Query(None, description="按申请人过滤（管理员用）"),
    db: AsyncSession = Depends(get_db),
    current_user: CurrentUserPayload = Depends(get_current_user),
) -> dict:
    result = await svc.list_expenses(db, current_user, page, size, status, applicant_id)
    return ok(data=result.model_dump(mode="json"))


@router.get("/expenses/{expense_id}", summary="报销单详情（含明细行）")
async def get_expense(
    expense_id: uuid.UUID,
    db: AsyncSession = Depends(get_db),
    current_user: CurrentUserPayload = Depends(get_current_user),
) -> dict:
    result = await svc.get_expense(db, current_user, expense_id)
    return ok(data=result.model_dump(mode="json"))


@router.put("/expenses/{expense_id}/status", summary="审批/撤回报销单（含发票释放）")
async def update_expense_status(
    expense_id: uuid.UUID,
    body: ExpenseStatusUpdate,
    db: AsyncSession = Depends(get_db),
    current_user: CurrentUserPayload = Depends(get_current_user),
) -> dict:
    msg = await svc.update_expense_status(db, current_user, expense_id, body)
    return ok(message=msg)
