"""模型 → 接口返回字典。"""
import datetime as dt
import re
from collections import defaultdict

from sqlalchemy import select
from sqlalchemy.orm import Session

from flyway.domain.errors import BusinessError
from flyway.domain.units import parse_units
from flyway.models import AppUser, AuditLog, Client, PackingSlip, Product, ProductBatch, Supplier, Transfer, TransferItem
from flyway.models import TransferRelation

HEADER_FIELDS = ["ed_identification", "export_to", "transport_company", "vehicle_registration",
                 "condition_of_vehicle", "non_conforming_product", "container_number", "seal_number",
                 "can_number", "notes"]


def legacy_log_text(html: str | None) -> str:
    """旧 Logs 是拼接的 HTML；转成纯文本，前端不用 v-html。"""
    return re.sub(r"<[^>]+>", "", re.sub(r"<br\s*/?>", "\n", html or "")).strip()


def units_of(p: Product) -> list[int]:
    try:
        extra = parse_units(p.available_unit)
    except BusinessError:  # 旧数据里可能有不规范的单位文本
        extra = []
    return sorted(set(extra) | {p.default_unit})


def client_out(c: Client) -> dict:
    return {"id": c.id, "name": c.name, "email": c.email, "mobile_phone": c.mobile_phone,
            "phone": c.phone, "phone1": c.phone1}


def product_out(p: Product) -> dict:
    return {"id": p.id, "title": p.title, "default_unit": p.default_unit, "available_unit": p.available_unit,
            "units": units_of(p)}


def batch_out(bt: ProductBatch, stock: int | None = None) -> dict:
    return {"id": bt.id, "product_id": bt.product_id, "product_title": bt.product.title, "number": bt.number,
            "default_unit": bt.product.default_unit, "date": bt.date,
            "display_date": bt.display_date or dt.datetime.combine(bt.date, dt.time()),
            "used_by_date": bt.used_by_date, "stock": stock}


def supplier_out(s: Supplier) -> dict:
    return {"id": s.id, "name": s.name, "rmp_number": s.rmp_number}


def user_out(u: AppUser) -> dict:
    return {"id": u.id, "username": u.username, "first_name": u.first_name, "last_name": u.last_name,
            "full_name": u.full_name, "email": u.email, "mobile": u.mobile, "is_admin": u.is_admin,
            "is_active": u.is_active, "is_locked_out": u.is_locked_out, "created_at": u.created_at,
            "last_login_at": u.last_login_at, "last_activity_at": u.last_activity_at, "has_password": u.password_hash is not None}


def transfer_row(t: Transfer) -> dict:
    row = {"id": t.id, "code": t.code, "date": t.date, "is_draft": t.is_draft, "is_load_out": t.is_load_out,
           "is_local": t.is_local, "client_id": t.client_id, "client_name": t.client.name,
           # 旧页面客户显示为 "名称 (E:邮箱,M:手机)"
           "client_email": t.client.email, "client_mobile": t.client.mobile_phone,
           "from_location": t.from_location, "from_rmp": t.from_rmp, "to_location": t.to_location,
           "to_rmp": t.to_rmp, "operator": t.operator, "awb_number": t.awb_number,
           "packing_slip_id": t.packing_slip_id,
           "packing_slip_reference": t.packing_slip.reference if t.packing_slip else None}
    if t.is_local and t.transfer_tos:
        row["to_client_id"] = t.transfer_tos[0].client_id
        row["to_client_name"] = t.transfer_tos[0].client.name
        row["to_client_email"] = t.transfer_tos[0].client.email
        row["to_client_mobile"] = t.transfer_tos[0].client.mobile_phone
    return row


def item_out(i: TransferItem) -> dict:
    main = i.main_item
    product = i.batch.product
    return {"id": i.id, "product_id": product.id, "product_title": product.title, "units": units_of(product),
            "batch_id": i.batch_id, "batch_number": i.batch.number, "used_by_date": i.batch.used_by_date,
            "quantity": i.quantity, "unit": i.unit, "reference": i.reference, "remaining_stock": i.remaining_stock,
            "source_item_id": i.related_transfer_item_id,
            "source_code": main.transfer.code if main else None,
            "source_remaining": main.remaining_stock if main else None}


def audit_out(db: Session, entity_id) -> list[dict]:
    rows = db.scalars(select(AuditLog).where(AuditLog.entity_id == str(entity_id))
                      .order_by(AuditLog.at.desc()).limit(50)).all()
    return [{"at": a.at, "username": a.username, "action": a.action, "detail": a.detail} for a in rows]


def transfer_detail(db: Session, t: Transfer) -> dict:
    links = db.scalars(select(TransferRelation).where(TransferRelation.rel_transfer_id == t.id)).all()
    return {**transfer_row(t), **{f: getattr(t, f) for f in HEADER_FIELDS},
            "items": [item_out(i) for i in sorted(t.items, key=lambda i: i.batch.product.title.casefold())],
            "load_ins": [{"id": r.transfer_id, "code": r.load_in.code} for r in links],
            "logs": legacy_log_text(t.logs), "audit": audit_out(db, t.id)}


def slip_row(s: PackingSlip) -> dict:
    return {"id": s.id, "reference": s.reference, "date": s.date, "from_location": s.from_location,
            "from_rmp": s.from_rmp, "to_location": s.to_location, "to_rmp": s.to_rmp,
            "awb_number": s.awb_number, "completed": s.completed, "operator": s.operator,
            "load_out_count": len(s.transfers)}


def slip_detail(db: Session, s: PackingSlip) -> dict:
    totals: dict[tuple, int] = defaultdict(int)
    for t in s.transfers:
        for i in t.items:
            totals[(i.batch.product.title, i.batch.number)] += i.quantity * i.unit
    products = [{"product_title": p, "batch_number": n, "quantity": q} for (p, n), q in sorted(totals.items())]
    # 旧关联集合按 SQL Server uniqueidentifier 主键顺序读取。
    def record_order(t: Transfer) -> bytes:
        raw = t.id.bytes_le
        return raw[10:] + raw[8:10] + raw[6:8] + raw[4:6] + raw[:4]

    return {**slip_row(s), "load_outs": [transfer_row(t) for t in sorted(s.transfers, key=record_order)],
            "products": products, "total_cases": sum(i.quantity for t in s.transfers for i in t.items),
            "logs": legacy_log_text(s.logs), "audit": audit_out(db, s.id)}
