"""前台退款退货 API — 顾客发起和查看退款申请

协议：
- 仅 paid / shipped / completed 状态订单可申请退款
- refund_amount ≤ order.grand_total
- 每个订单只能有一个 pending 状态的退款申请
"""
from datetime import datetime
from decimal import Decimal
from typing import Optional

from fastapi import APIRouter, Depends, HTTPException, Query  # Query kept for pagination params
from pydantic import BaseModel, Field
from sqlalchemy import select, func
from sqlalchemy.ext.asyncio import AsyncSession

from app.api.deps import get_db, get_current_customer, get_tenant_by_domain
from app.core.models.customer import Customer
from app.core.models.order import Order, OrderItem
from app.core.models.refund import RefundRequest
from app.core.services import inventory as inv_svc


router = APIRouter(prefix="/store/refund-requests", tags=["前台退款"])


# ── Schemas ────────────────────────────────────────────────────────────────

class RefundCreateIn(BaseModel):
    order_id: int
    type: str = Field(..., description="refund | return | exchange")
    reason: str
    refund_amount: Decimal = Field(..., ge=Decimal("0.01"))
    return_items: Optional[list[dict]] = None  # [{"variant_id":1,"qty":2}]
    images: Optional[list[str]] = None
    note: Optional[str] = None


class RefundItemOut(BaseModel):
    product_id: int
    product_name: str
    quantity: int
    unit_price: float
    total_price: float

    model_config = {"from_attributes": True}


class RefundOrderSnapshot(BaseModel):
    order_no: str
    status: str
    subtotal: float
    discount_total: float
    shipping_total: float
    grand_total: float
    created_at: Optional[str] = None
    paid_at: Optional[str] = None

    model_config = {"from_attributes": True}


class RefundRequestOut(BaseModel):
    id: int
    order_id: int
    order_no: str
    type: str
    status: str
    reason: str
    refund_amount: float
    return_items: Optional[list] = None
    images: Optional[list] = None
    admin_note: Optional[str] = None
    tracking_no: Optional[str] = None
    processed_at: Optional[str] = None
    completed_at: Optional[str] = None
    created_at: Optional[str] = None
    order: Optional[RefundOrderSnapshot] = None

    model_config = {"from_attributes": True}


class RefundListOut(BaseModel):
    id: int
    order_no: str
    type: str
    status: str
    refund_amount: float
    created_at: Optional[str] = None

    model_config = {"from_attributes": True}


# ── 顾客发起退款申请 ─────────────────────────────────────────────────────

@router.post("", summary="发起退款/退货申请", response_model=RefundRequestOut)
async def create_refund_request(
    body: RefundCreateIn,
    tid: int = Depends(get_tenant_by_domain),
    customer: Customer = Depends(get_current_customer),
    db: AsyncSession = Depends(get_db),
):
    tenant_id = tid

    # 校验订单
    r = await db.execute(
        select(Order).where(
            Order.id == body.order_id,
            Order.customer_id == customer.id,
            Order.tenant_id == tenant_id,
        )
    )
    order = r.scalar_one_or_none()
    if not order:
        raise HTTPException(status_code=404, detail="订单不存在")

    if order.status not in ("paid", "shipped", "completed"):
        raise HTTPException(
            status_code=400,
            detail=f"当前状态「{order.status}」不可申请退款，仅 paid/shipped/completed 订单可申请",
        )

    if body.refund_amount > order.grand_total:
        raise HTTPException(status_code=400, detail="退款金额不能超过订单实付金额")

    # 每订单只能有一个 pending 申请
    existing = await db.execute(
        select(RefundRequest).where(
            RefundRequest.order_id == order.id,
            RefundRequest.status == "pending",
        )
    )
    if existing.scalar_one_or_none():
        raise HTTPException(status_code=409, detail="该订单已有待处理的退款申请，请勿重复提交")

    # 累计退款金额校验（包含所有非 rejected 的申请）
    sum_r = await db.execute(
        select(func.coalesce(func.sum(RefundRequest.refund_amount), 0)).where(
            RefundRequest.order_id == order.id,
            RefundRequest.status.notin_(["rejected"]),
        )
    )
    existing_refund_total = sum_r.scalar() or 0
    if existing_refund_total + body.refund_amount > order.grand_total:
        remaining = float(order.grand_total) - float(existing_refund_total)
        raise HTTPException(
            status_code=400,
            detail=f"累计退款金额不能超过订单实付金额，当前可退余额：¥{remaining:.2f}",
        )

    rr = RefundRequest(
        tenant_id=tenant_id,
        order_id=order.id,
        order_no=order.order_no,
        customer_id=customer.id,
        type=body.type,
        reason=body.reason,
        refund_amount=body.refund_amount,
        return_items=body.return_items,
        images=body.images,
        admin_note=body.note,
        status="pending",
    )
    db.add(rr)
    await db.commit()
    await db.refresh(rr)

    return await _format_refund_full(rr, db)


# ── 顾客查看自己的退款列表 ───────────────────────────────────────────────

@router.get("", summary="我的退款申请列表")
async def list_my_refund_requests(
    tid: int = Depends(get_tenant_by_domain),
    status: Optional[str] = Query(None),
    page: int = Query(1, ge=1),
    page_size: int = Query(10, ge=1, le=50),
    customer: Customer = Depends(get_current_customer),
    db: AsyncSession = Depends(get_db),
):
    tenant_id = tid

    q = select(RefundRequest).where(
        RefundRequest.customer_id == customer.id,
        RefundRequest.tenant_id == tenant_id,
    )
    if status:
        q = q.where(RefundRequest.status == status)

    q = q.order_by(RefundRequest.created_at.desc())

    # 总数
    count_q = select(func.count()).select_from(q.subquery())
    total_r = await db.execute(count_q)
    total = total_r.scalar() or 0

    # 分页
    q = q.offset((page - 1) * page_size).limit(page_size)
    rows_r = await db.execute(q)
    rows = rows_r.scalars().all()

    return {
        "total": total,
        "page": page,
        "page_size": page_size,
        "items": [_format_refund_list(r) for r in rows],
    }


# ── 顾客查看退款详情 ─────────────────────────────────────────────────────

@router.get("/{refund_id}", summary="退款详情", response_model=RefundRequestOut)
async def get_refund_request(
    refund_id: int,
    tid: int = Depends(get_tenant_by_domain),
    customer: Customer = Depends(get_current_customer),
    db: AsyncSession = Depends(get_db),
):
    tenant_id = tid

    r = await db.execute(
        select(RefundRequest).where(
            RefundRequest.id == refund_id,
            RefundRequest.customer_id == customer.id,
            RefundRequest.tenant_id == tenant_id,
        )
    )
    rr = r.scalar_one_or_none()
    if not rr:
        raise HTTPException(status_code=404, detail="退款申请不存在")

    return await _format_refund_full(rr, db)


# ── 工具函数 ──────────────────────────────────────────────────────────────

def _format_refund_list(r: RefundRequest) -> dict:
    return RefundListOut(
        id=r.id,
        order_no=r.order_no,
        type=r.type,
        status=r.status,
        refund_amount=float(r.refund_amount),
        created_at=r.created_at.isoformat() if r.created_at else None,
    ).model_dump()


async def _format_refund_full(r: RefundRequest, db: AsyncSession) -> dict:
    out = RefundRequestOut(
        id=r.id,
        order_id=r.order_id,
        order_no=r.order_no,
        type=r.type,
        status=r.status,
        reason=r.reason,
        refund_amount=float(r.refund_amount),
        return_items=r.return_items,
        images=r.images,
        admin_note=r.admin_note,
        tracking_no=r.tracking_no,
        processed_at=r.processed_at.isoformat() if r.processed_at else None,
        completed_at=r.completed_at.isoformat() if r.completed_at else None,
        created_at=r.created_at.isoformat() if r.created_at else None,
    ).model_dump()

    # 附加订单快照
    order_r = await db.execute(select(Order).where(Order.id == r.order_id))
    order = order_r.scalar_one_or_none()
    if order:
        out["order"] = RefundOrderSnapshot(
            order_no=order.order_no,
            status=order.status,
            subtotal=float(order.subtotal),
            discount_total=float(order.discount_total),
            shipping_total=float(order.shipping_total),
            grand_total=float(order.grand_total),
            created_at=order.created_at.isoformat() if order.created_at else None,
            paid_at=order.paid_at.isoformat() if order.paid_at else None,
        ).model_dump()

    return out
