"""物流/发货单管理 API — Admin
支持一张订单对应多个快递包裹（shipments）。
数据存储在 Order.extra_attributes["shipments"] 数组中，无需额外建表。
"""
import uuid
from datetime import date, timedelta, datetime
from typing import Optional
from fastapi import APIRouter, Depends, HTTPException
from pydantic import BaseModel, Field
from sqlalchemy import select
from sqlalchemy.ext.asyncio import AsyncSession

from app.api.deps import get_db, require_permission
from app.core.models.user import User
from app.core.models.order import Order

router = APIRouter(prefix="/orders", tags=["物流管理"])


# ── Schemas ────────────────────────────────────────────────────────────────

class AddShipmentIn(BaseModel):
    carrier: str = Field(..., min_length=1, max_length=100, description="快递公司名称")
    tracking_no: str = Field(..., min_length=1, max_length=100, description="运单号")
    estimated_delivery: Optional[str] = Field(None, description="预计送达 YYYY-MM-DD")
    note: Optional[str] = Field(None, max_length=200, description="备注，如：第一批货")


# ── 内部：往订单写入一条发货记录 ────────────────────────────────────────────

async def _add_shipment(order_id: int, body: AddShipmentIn, db: AsyncSession, current_user: User):
    r = await db.execute(
        select(Order).where(
            Order.id == order_id,
            Order.tenant_id == current_user.tenant_id,
        )
    )
    order = r.scalar_one_or_none()
    if not order:
        raise HTTPException(status_code=404, detail="订单不存在")
    if order.status == "cancelled":
        raise HTTPException(status_code=400, detail="已取消订单无法添加发货信息")

    extra = dict(order.extra_attributes or {})
    shipments = list(extra.get("shipments") or [])

    new_shipment = {
        "id": str(uuid.uuid4()),
        "carrier": body.carrier,
        "tracking_no": body.tracking_no,
        "estimated_delivery": body.estimated_delivery or "",
        "note": body.note or "",
        "added_at": datetime.now().isoformat(timespec="seconds"),
    }
    shipments.append(new_shipment)
    extra["shipments"] = shipments
    order.extra_attributes = extra

    # 同步到 Order 字段（始终保持最新一条，供查询/打印用）
    order.carrier = body.carrier
    order.tracking_no = body.tracking_no
    if body.estimated_delivery:
        try:
            order.estimated_delivery = date.fromisoformat(body.estimated_delivery)
        except ValueError:
            pass
    elif not order.estimated_delivery and order.status in ("pending", "paid"):
        order.estimated_delivery = date.today() + timedelta(days=3)

    # paid / pending → shipped
    if order.status in ("pending", "paid"):
        order.status = "shipped"

    await db.commit()
    return {
        "ok": True,
        "shipment": new_shipment,
        "order_status": order.status,
        "shipments": shipments,
    }


# ── PUT /orders/{id}/logistics  （旧接口保持兼容） ─────────────────────────

@router.put("/{order_id}/logistics", summary="添加发货信息（兼容旧接口）")
async def set_logistics(
    order_id: int,
    body: AddShipmentIn,
    db: AsyncSession = Depends(get_db),
    current_user: User = Depends(require_permission("orders.ship")),
):
    return await _add_shipment(order_id, body, db, current_user)


# ── POST /orders/{id}/shipments ────────────────────────────────────────────

@router.post("/{order_id}/shipments", summary="新增发货包裹")
async def add_shipment(
    order_id: int,
    body: AddShipmentIn,
    db: AsyncSession = Depends(get_db),
    current_user: User = Depends(require_permission("orders.ship")),
):
    return await _add_shipment(order_id, body, db, current_user)


# ── DELETE /orders/{id}/shipments/{shipment_id} ────────────────────────────

@router.delete("/{order_id}/shipments/{shipment_id}", summary="删除发货包裹")
async def delete_shipment(
    order_id: int,
    shipment_id: str,
    db: AsyncSession = Depends(get_db),
    current_user: User = Depends(require_permission("orders.tracking.update")),
):
    r = await db.execute(
        select(Order).where(
            Order.id == order_id,
            Order.tenant_id == current_user.tenant_id,
        )
    )
    order = r.scalar_one_or_none()
    if not order:
        raise HTTPException(status_code=404, detail="订单不存在")

    extra = dict(order.extra_attributes or {})
    shipments = [s for s in (extra.get("shipments") or []) if s.get("id") != shipment_id]
    extra["shipments"] = shipments
    order.extra_attributes = extra

    # 同步 carrier/tracking_no 为最后一条，若全删完则清空
    if shipments:
        last = shipments[-1]
        order.carrier = last["carrier"]
        order.tracking_no = last["tracking_no"]
        if last.get("estimated_delivery"):
            try:
                order.estimated_delivery = date.fromisoformat(last["estimated_delivery"])
            except ValueError:
                pass
    else:
        order.carrier = None
        order.tracking_no = None
        order.estimated_delivery = None

    await db.commit()
    return {"ok": True, "shipments": shipments}


# ── GET /orders/{id}/logistics ─────────────────────────────────────────────

@router.get("/{order_id}/logistics", summary="查看订单物流信息")
async def get_logistics_info(
    order_id: int,
    db: AsyncSession = Depends(get_db),
    current_user: User = Depends(require_permission("orders.detail.view")),
):
    r = await db.execute(
        select(Order).where(
            Order.id == order_id,
            Order.tenant_id == current_user.tenant_id,
        )
    )
    order = r.scalar_one_or_none()
    if not order:
        raise HTTPException(status_code=404, detail="订单不存在")

    extra = order.extra_attributes or {}
    return {
        "order_id": order.id,
        "order_no": order.order_no,
        "status": order.status,
        "carrier": order.carrier,
        "tracking_no": order.tracking_no,
        "estimated_delivery": str(order.estimated_delivery) if order.estimated_delivery else None,
        "shipments": extra.get("shipments") or [],
    }
