"""
Fetch China - Partner API Routes
Partner-only endpoints for managing their clients and orders
"""

import json
from typing import Optional
from fastapi import APIRouter, Depends, HTTPException, status, Query
from pydantic import BaseModel, Field, HttpUrl
from sqlalchemy.orm import Session

from app.api import deps
from app.models.user import User, UserRole
from app.models.parcel import Parcel
from app.models.parcel_status import ParcelStatus
from app.services.audit_service import AuditService
from app.core.logging_config import get_logger

logger = get_logger(__name__)


router = APIRouter(prefix="/partner", tags=["partner"])


class RejectItemRequest(BaseModel):
    reason: str
    note: Optional[str] = None
    proposed_price_cny: Optional[float] = None


class WarehouseReceiveRequest(BaseModel):
    domestic_tracking_no: str = Field(..., min_length=1, max_length=100)
    internal_barcode: str = Field(..., min_length=1, max_length=50)
    qc_image_url: str  # 改为 str 类型，支持相对路径


def get_current_partner(
    current_user: User = Depends(deps.get_current_active_user),
) -> User:
    """Dependency to ensure user is partner"""
    if current_user.role != UserRole.PARTNER.value:
        raise HTTPException(
            status_code=status.HTTP_403_FORBIDDEN, detail="Partner access required"
        )
    return current_user


@router.get("/dashboard")
def get_partner_dashboard(
    current_user: User = Depends(get_current_partner),
    db: Session = Depends(deps.get_db),
):
    """获取合伙人仪表板数据"""
    from app.services.partner_service import PartnerService

    stats = PartnerService.get_partner_stats(db, current_user.id)
    return stats


@router.get("/clients")
def get_my_clients(
    current_user: User = Depends(get_current_partner),
    db: Session = Depends(deps.get_db),
):
    """获取我的客户列表"""
    from app.services.partner_service import PartnerService
    from app.models.order import Order

    clients = PartnerService.get_partner_clients(db, current_user.id)
    result = []
    for c in clients:
        order_count = db.query(Order).filter(Order.user_id == c.id).count()
        result.append(
            {
                "id": c.id,
                "email": c.email,
                "is_active": c.is_active,
                "partner_commission_rate": float(c.partner_commission_rate or 0) * 100,
                "total_orders": order_count,
                "created_at": c.created_at.isoformat() if c.created_at else None,
            }
        )
    return result


@router.get("/orders/summary")
def get_my_orders_summary(
    status: Optional[str] = None,
    skip: int = 0,
    limit: int = 50,
    current_user: User = Depends(get_current_partner),
    db: Session = Depends(deps.get_db),
):
    """获取我的订单列表（轻量级摘要版本，用于列表页）

    性能优化：
    - 只返回列表页需要的字段
    - 不加载QC图片等详细信息
    - 减少数据传输量
    """
    from app.services.partner_service import PartnerService

    # 使用优化后的查询，已预加载关联数据
    orders = PartnerService.get_partner_orders(db, current_user.id, status)
    orders = orders[skip : skip + limit]

    result = []
    for o in orders:
        # 使用预加载的用户信息
        client = o.user

        # 只统计商品数量，不返回详细信息
        items_count = len(o.items)

        result.append(
            {
                "id": o.id,
                "order_number": o.order_number,
                "status": o.status,
                "total_usd": float(o.total_usd),
                "service_fee_usd": float(o.service_fee_usd),
                "user_id": o.user_id,
                "client_email": client.email if client else "Unknown",
                "items_count": items_count,  # 只返回数量
                "created_at": o.created_at.isoformat() if o.created_at else None,
                "total_cny": float(o.total_cny),
                "exchange_rate": float(o.exchange_rate),
                "updated_at": o.updated_at.isoformat() if o.updated_at else None,
            }
        )
    return result


@router.get("/orders")
def get_my_orders(
    status: Optional[str] = None,
    skip: int = 0,
    limit: int = 50,
    current_user: User = Depends(get_current_partner),
    db: Session = Depends(deps.get_db),
):
    """获取我的订单列表（性能优化版本）"""
    from app.services.partner_service import PartnerService

    # 使用优化后的查询，已预加载关联数据
    orders = PartnerService.get_partner_orders(db, current_user.id, status)
    orders = orders[skip : skip + limit]

    result = []
    for o in orders:
        # 使用预加载的用户信息（避免额外查询）
        client = o.user  # 已通过joinedload预加载

        # 使用预加载的订单项（避免额外查询）
        items_data = []
        for item in o.items:  # 已通过joinedload预加载
            # 使用预加载的QC图片（避免额外查询）
            qc_images_data = [
                {
                    "image_url": img.image_url,
                    "uploaded_at": img.created_at.isoformat() if img.created_at else None
                }
                for img in item.qc_images  # 已通过joinedload预加载
            ]

            items_data.append(
                {
                    "id": str(item.id),
                    "item_id": str(item.id),
                    "product_name": item.product_name,
                    "product_url": item.product_url,
                    "specification": item.specification,
                    "quantity": item.quantity,
                    "unit_price_cny": float(item.unit_price_cny),
                    "unit_price_usd": float(item.unit_price_usd) if item.unit_price_usd else 0.0,
                    "domestic_shipping_cny": float(item.domestic_shipping_cny) if item.domestic_shipping_cny else 0.0,
                    "is_freight_collect": item.is_freight_collect,
                    "plan_b": item.plan_b,
                    "user_image_url": item.user_image_url,
                    "domestic_tracking_no": item.domestic_tracking_no,
                    "status": item.status,
                    "declared_name_en": item.declared_name_en,
                    "declared_value_usd": float(item.declared_value_usd) if item.declared_value_usd else None,
                    "is_sensitive": item.is_sensitive,
                    "qc_images": qc_images_data,
                    # 任务1.1: 新增商品级别字段
                    "freight_collect_frozen_cny": float(item.freight_collect_frozen_cny) if item.freight_collect_frozen_cny else 0.0,
                    "freight_collect_actual_cny": float(item.freight_collect_actual_cny) if item.freight_collect_actual_cny else None,
                    "actual_cost_cny": float(item.actual_cost_cny) if item.actual_cost_cny else None,
                    "internal_barcode": item.internal_barcode,
                    "warehouse_date": item.warehouse_date.isoformat() if item.warehouse_date else None,
                    "storage_fee_usd": float(item.storage_fee_usd) if item.storage_fee_usd else 0.0,
                    "return_tracking_no": item.return_tracking_no,
                    "return_shipping_fee_cny": float(item.return_shipping_fee_cny) if item.return_shipping_fee_cny else None,
                    "return_reason": item.return_reason,
                    "return_address": item.return_address,
                    "main_qc_image_url": item.main_qc_image_url,
                    "service_fee_usd": float(item.service_fee_usd) if item.service_fee_usd else 0.0,
                }
            )
        result.append(
            {
                "id": o.id,
                "order_number": o.order_number,
                "status": o.status,
                "total_usd": float(o.total_usd),
                "service_fee_usd": float(o.service_fee_usd),
                "user_id": o.user_id,
                "client_email": client.email if client else "Unknown",
                "items": items_data,
                "created_at": o.created_at.isoformat() if o.created_at else None,
                # 任务1.1: 新增订单级别字段
                "total_cny": float(o.total_cny),
                "exchange_rate": float(o.exchange_rate),
                "rejection_reason": o.rejection_reason,
                "rejection_note": o.rejection_note,
                "proposed_price_cny": float(o.proposed_price_cny) if o.proposed_price_cny else None,
                "updated_at": o.updated_at.isoformat() if o.updated_at else None,
            }
        )
    return result


@router.get("/orders/{order_id}")
def get_order_detail(
    order_id: str,
    current_user: User = Depends(get_current_partner),
    db: Session = Depends(deps.get_db),
):
    """获取订单详情（任务1.2）"""
    from app.models.order import Order, OrderItem
    from app.models.parcel import QCImage

    # 查询订单
    order = db.query(Order).filter(Order.id == order_id).first()
    if not order:
        raise HTTPException(
            status_code=status.HTTP_404_NOT_FOUND, detail="订单不存在"
        )

    # 验证订单属于当前合伙人的客户
    client = db.query(User).filter(User.id == order.user_id).first()
    if not client or client.partner_id != str(current_user.id):
        raise HTTPException(
            status_code=status.HTTP_403_FORBIDDEN,
            detail="无权访问此订单"
        )

    # 获取订单商品
    items = db.query(OrderItem).filter(OrderItem.order_id == order.id).all()
    items_data = []
    for item in items:
        # 获取质检图片
        qc_images = db.query(QCImage).filter(QCImage.order_item_id == item.id).all()
        qc_images_data = [
            {
                "image_url": img.image_url,
                "uploaded_at": img.created_at.isoformat() if img.created_at else None
            }
            for img in qc_images
        ]

        items_data.append(
            {
                "id": str(item.id),
                "item_id": str(item.id),
                "product_name": item.product_name,
                "product_url": item.product_url,
                "specification": item.specification,
                "quantity": item.quantity,
                "unit_price_cny": float(item.unit_price_cny),
                "unit_price_usd": float(item.unit_price_usd) if item.unit_price_usd else 0.0,
                "domestic_shipping_cny": float(item.domestic_shipping_cny) if item.domestic_shipping_cny else 0.0,
                "is_freight_collect": item.is_freight_collect,
                "plan_b": item.plan_b,
                "user_image_url": item.user_image_url,
                "domestic_tracking_no": item.domestic_tracking_no,
                "status": item.status,
                "declared_name_en": item.declared_name_en,
                "declared_value_usd": float(item.declared_value_usd) if item.declared_value_usd else None,
                "is_sensitive": item.is_sensitive,
                "qc_images": qc_images_data,
                # 任务1.1: 商品级别字段
                "freight_collect_frozen_cny": float(item.freight_collect_frozen_cny) if item.freight_collect_frozen_cny else 0.0,
                "freight_collect_actual_cny": float(item.freight_collect_actual_cny) if item.freight_collect_actual_cny else None,
                "actual_cost_cny": float(item.actual_cost_cny) if item.actual_cost_cny else None,
                "internal_barcode": item.internal_barcode,
                "warehouse_date": item.warehouse_date.isoformat() if item.warehouse_date else None,
                "storage_fee_usd": float(item.storage_fee_usd) if item.storage_fee_usd else 0.0,
                "return_tracking_no": item.return_tracking_no,
                "return_shipping_fee_cny": float(item.return_shipping_fee_cny) if item.return_shipping_fee_cny else None,
                "return_reason": item.return_reason,
                "return_address": item.return_address,
                "main_qc_image_url": item.main_qc_image_url,
                "service_fee_usd": float(item.service_fee_usd) if item.service_fee_usd else 0.0,
            }
        )

    # 获取包裹信息（如果有）
    from app.models.parcel import Parcel
    parcel_data = None
    if items:
        # 检查第一个商品的 parcel_id
        first_item = items[0]
        if first_item.parcel_id:
            parcel = db.query(Parcel).filter(Parcel.id == first_item.parcel_id).first()
            if parcel:
                parcel_data = {
                    "parcel_id": str(parcel.id),
                    "parcel_number": parcel.parcel_number,
                    "status": parcel.status,
                    "weight_kg": float(parcel.weight_kg) if parcel.weight_kg else None,
                    "length_cm": float(parcel.length_cm) if parcel.length_cm else None,
                    "width_cm": float(parcel.width_cm) if parcel.width_cm else None,
                    "height_cm": float(parcel.height_cm) if parcel.height_cm else None,
                }

    # 构建返回数据
    result = {
        "id": order.id,
        "order_number": order.order_number,
        "status": order.status,
        "total_usd": float(order.total_usd),
        "service_fee_usd": float(order.service_fee_usd),
        "user_id": order.user_id,
        "created_at": order.created_at.isoformat() if order.created_at else None,
        # 任务1.1: 订单级别字段
        "total_cny": float(order.total_cny),
        "exchange_rate": float(order.exchange_rate),
        "rejection_reason": order.rejection_reason,
        "rejection_note": order.rejection_note,
        "proposed_price_cny": float(order.proposed_price_cny) if order.proposed_price_cny else None,
        "updated_at": order.updated_at.isoformat() if order.updated_at else None,
        # 商品列表
        "items": items_data,
        # 客户基本信息
        "client": {
            "id": client.id,
            "email": client.email,
            "balance_usd": float(client.balance_usd) if client.balance_usd else 0.0,
        },
        # 包裹信息（如果有）
        "parcel": parcel_data
    }

    return result


@router.post("/items/{item_id}/reject")
def reject_item(
    item_id: str,
    request: RejectItemRequest,
    current_user: User = Depends(get_current_partner),
    db: Session = Depends(deps.get_db),
):
    """
    [Partner] Mark an item as cannot be purchased with a reason.
    Reasons: out_of_stock, price_mismatch, prohibited, fake_goods, other

    For price_mismatch, proposed_price_cny is required.
    This will notify the user and allow them to accept the new price or cancel.
    """
    from app.services.order_service import OrderService

    try:
        OrderService.reject_item_cannot_purchase(
            db=db,
            item_id=item_id,
            partner_id=str(current_user.id),
            reason=request.reason,
            note=request.note,
            proposed_price_cny=request.proposed_price_cny,
        )
        return {"success": True, "item_id": item_id, "reason": request.reason}
    except ValueError as e:
        raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail=str(e))
    except Exception as e:
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, detail=str(e)
        )


@router.get("/revenue")
def get_my_revenue(
    days: int = 30,
    current_user: User = Depends(get_current_partner),
    db: Session = Depends(deps.get_db),
):
    """获取我的收入统计"""
    from app.services.partner_service import PartnerService

    return PartnerService.get_partner_revenue(db, current_user.id, days)


# ========== 仓库操作路由（原 staff.py）==========

@router.get("/warehouse/stats")
def get_warehouse_stats(
    current_user: User = Depends(get_current_partner),
    db: Session = Depends(deps.get_db),
):
    """Get warehouse dashboard statistics"""
    from app.services.partner_service import PartnerService
    return PartnerService.get_warehouse_stats(db)


@router.get("/warehouse/receiving")
def get_pending_items(
    status: str = Query("processing", description="Filter by status"),
    current_user: User = Depends(get_current_partner),
    db: Session = Depends(deps.get_db),
):
    """Get items pending to be received at warehouse"""
    from app.services.partner_service import PartnerService
    items = PartnerService.get_pending_items(db, status=status)
    return {"items": items, "total": len(items)}


@router.get("/warehouse/search")
def search_item(
    q: str = Query(..., description="Tracking number or internal barcode"),
    current_user: User = Depends(get_current_partner),
    db: Session = Depends(deps.get_db),
):
    """Find an item for rapid processing"""
    from app.services.partner_service import PartnerService
    item = PartnerService.find_item_by_tracking(db, q)
    if not item:
        raise HTTPException(status_code=404, detail="Item not found")
    return item


@router.post("/warehouse/bind")
def bind_barcode(
    item_id: str = Query(...),
    barcode: str = Query(...),
    current_user: User = Depends(get_current_partner),
    db: Session = Depends(deps.get_db),
):
    """Rapidly bind barcode and check-in item"""
    from app.services.partner_service import PartnerService
    try:
        item = PartnerService.bind_barcode(db, item_id, barcode, str(current_user.id))
        return {"status": "success", "item_id": item.id, "new_status": item.status}
    except ValueError as e:
        raise HTTPException(status_code=400, detail=str(e))


@router.post("/warehouse/receiving/{item_id}")
def receive_item(
    item_id: str,
    tracking_no: Optional[str] = None,
    current_user: User = Depends(get_current_partner),
    db: Session = Depends(deps.get_db),
):
    """Mark an item as received at warehouse"""
    from app.services.partner_service import PartnerService
    try:
        item = PartnerService.receive_item(
            db, item_id=item_id, tracking_no=tracking_no, partner_id=str(current_user.id)
        )
        return {
            "success": True,
            "item_id": item.id,
            "status": item.status,
            "warehouse_date": item.warehouse_date.isoformat()
            if item.warehouse_date
            else None,
        }
    except ValueError as e:
        raise HTTPException(status_code=400, detail=str(e))


@router.get("/warehouse/qc")
def get_items_for_qc(
    item_id: Optional[str] = Query(
        None, description="Optional: fetch specific item by ID"
    ),
    current_user: User = Depends(get_current_partner),
    db: Session = Depends(deps.get_db),
):
    """Get items needing QC photos, or specific item by ID"""
    from app.services.partner_service import PartnerService
    items = PartnerService.get_items_for_qc(db, item_id=item_id)
    return {"items": items, "total": len(items)}


@router.post("/warehouse/qc/{item_id}")
def upload_qc_image(
    item_id: str,
    image_url: str,
    current_user: User = Depends(get_current_partner),
    db: Session = Depends(deps.get_db),
):
    """Upload QC image for an item"""
    from app.services.partner_service import PartnerService
    try:
        item = PartnerService.upload_qc_image(
            db, item_id, image_url, partner_id=str(current_user.id)
        )
        return {
            "success": True,
            "item_id": item.id,
            "image_url": item.main_qc_image_url,
        }
    except ValueError as e:
        raise HTTPException(status_code=400, detail=str(e))


from pydantic import BaseModel
from typing import List


class MultipleImagesRequest(BaseModel):
    images: List[str]


class QCFailRequest(BaseModel):
    reason: str


class ShipReturnRequest(BaseModel):
    tracking_no: str
    fee_cny: float


@router.post("/warehouse/qc/{item_id}/multiple")
def upload_qc_images(
    item_id: str,
    request: MultipleImagesRequest,
    current_user: User = Depends(get_current_partner),
    db: Session = Depends(deps.get_db),
):
    """Upload multiple QC images for an item"""
    if not request.images or len(request.images) < 1:
        raise HTTPException(status_code=400, detail="At least 1 image required")
    if len(request.images) > 5:
        raise HTTPException(status_code=400, detail="Maximum 5 images allowed")

    from app.services.partner_service import PartnerService
    try:
        item = PartnerService.upload_qc_images(
            db, item_id, request.images, str(current_user.id)
        )
        return {"success": True, "item_id": item.id, "image_count": len(request.images)}
    except ValueError as e:
        raise HTTPException(status_code=400, detail=str(e))


@router.post("/warehouse/qc/{item_id}/fail")
def fail_qc(
    item_id: str,
    request: QCFailRequest,
    current_user: User = Depends(get_current_partner),
    db: Session = Depends(deps.get_db),
):
    """Mark an item as QC failed with a reason"""
    from app.services.partner_service import PartnerService
    try:
        item = PartnerService.mark_qc_failed(
            db, item_id, request.reason, str(current_user.id)
        )
        return {
            "success": True,
            "item_id": item.id,
            "new_status": item.status,
            "reason": request.reason,
        }
    except ValueError as e:
        raise HTTPException(status_code=400, detail=str(e))


@router.post("/warehouse/qc/{item_id}/ship-return")
def ship_return(
    item_id: str,
    request: ShipReturnRequest,
    current_user: User = Depends(get_current_partner),
    db: Session = Depends(deps.get_db),
):
    """Mark item as returning and deduct return shipping fee"""
    from app.services.partner_service import PartnerService
    try:
        item = PartnerService.ship_return(
            db, item_id, request.tracking_no, request.fee_cny, str(current_user.id)
        )
        return {
            "success": True,
            "item_id": item.id,
            "status": item.status,
            "return_tracking_no": item.return_tracking_no,
        }
    except ValueError as e:
        raise HTTPException(status_code=400, detail=str(e))


class CompleteReturnRequest(BaseModel):
    return_success: bool = True
    notes: Optional[str] = None


@router.post("/orders/{order_id}/complete-return")
def complete_return(
    order_id: str,
    request: CompleteReturnRequest,
    current_user: User = Depends(get_current_partner),
    db: Session = Depends(deps.get_db),
):
    """
    [Partner] Complete return process for an order
    - Changes order status to 'cancelled'
    - Refunds the customer
    - Updates all order items to 'cancelled'
    """
    from app.services.partner_service import PartnerService
    try:
        order = PartnerService.complete_return(
            db=db,
            order_id=order_id,
            partner_id=str(current_user.id),
            return_success=request.return_success,
            notes=request.notes
        )
        return {
            "success": True,
            "order_id": order.id,
            "order_number": order.order_number,
            "status": order.status,
            "message": "Return completed and refund issued"
        }
    except ValueError as e:
        raise HTTPException(status_code=400, detail=str(e))


# ========== 新增：工作流程优化API ==========

@router.post("/orders/{order_id}/start-purchasing")
def start_purchasing(
    order_id: str,
    current_user: User = Depends(get_current_partner),
    db: Session = Depends(deps.get_db),
):
    """
    [Partner] 开始采购订单
    """
    from app.services.partner_service import PartnerService

    try:
        order = PartnerService.start_purchasing(
            db=db,
            order_id=order_id,
            partner_id=str(current_user.id)
        )
        return {
            "success": True,
            "order_id": order.id,
            "status": order.status,
            "purchasing_started_at": order.purchasing_started_at.isoformat() if order.purchasing_started_at else None
        }
    except ValueError as e:
        raise HTTPException(status_code=400, detail=str(e))


class MarkPurchasedRequest(BaseModel):
    tracking_no: Optional[str] = None
    actual_cost_cny: Optional[float] = None
    image_url: Optional[str] = None


@router.post("/orders/{order_id}/mark-awaiting-warehouse")
def mark_awaiting_warehouse(
    order_id: str,
    request: MarkPurchasedRequest,
    current_user: User = Depends(get_current_partner),
    db: Session = Depends(deps.get_db),
):
    """
    [Partner] 标记订单待入库
    """
    from app.services.partner_service import PartnerService

    try:
        order = PartnerService.mark_awaiting_warehouse(
            db=db,
            order_id=order_id,
            partner_id=str(current_user.id),
            tracking_no=request.tracking_no,
            actual_cost_cny=request.actual_cost_cny,
            image_url=request.image_url
        )
        return {
            "success": True,
            "order_id": order.id,
            "status": order.status,
            "awaiting_warehouse_at": order.awaiting_warehouse_at.isoformat() if order.awaiting_warehouse_at else None
        }
    except ValueError as e:
        raise HTTPException(status_code=400, detail=str(e))


@router.get("/parcels/pending-shipment")
def get_pending_shipment_parcels(
    current_user: User = Depends(get_current_partner),
    db: Session = Depends(deps.get_db),
):
    """
    [Partner] 获取待出库的包裹列表（需要填写重量体积）
    """
    from app.models.parcel import Parcel
    from app.models.order import OrderItem

    # 查找该合伙人客户的待出库包裹
    parcels = db.query(Parcel).join(
        User, Parcel.user_id == User.id
    ).filter(
        User.partner_id == str(current_user.id),
        Parcel.parcel_status == "packing_requested"
    ).all()

    result = []
    for parcel in parcels:
        user = db.query(User).filter(User.id == parcel.user_id).first()
        items = db.query(OrderItem).filter(OrderItem.parcel_id == parcel.id).all()
        
        result.append({
            "parcel_id": str(parcel.id),
            "parcel_number": parcel.parcel_number,
            "user_email": user.email if user else None,
            "status": parcel.status,
            "item_count": len(items),
            "items": [{
                "id": str(item.id),
                "product_name": item.product_name,
                "quantity": item.quantity,
                "main_qc_image_url": item.main_qc_image_url
            } for item in items],
            "created_at": parcel.created_at.isoformat() if parcel.created_at else None
        })
    
    return {"parcels": result, "total": len(result)}


@router.get("/parcels/{parcel_id}")
def get_parcel_detail(
    parcel_id: str,
    current_user: User = Depends(get_current_partner),
    db: Session = Depends(deps.get_db),
):
    """
    [Partner] 获取包裹详情
    
    返回包裹完整信息，包括：
    - 包裹基本信息（重量、尺寸、状态）
    - 商品列表（含敏感品标记）
    - 收货地址
    - 用户信息
    """
    from app.models.parcel import Parcel, Address
    from app.models.order import OrderItem

    # 查询包裹
    parcel = db.query(Parcel).filter(Parcel.id == parcel_id).first()
    if not parcel:
        raise HTTPException(status_code=404, detail="包裹不存在")

    # 验证权限：包裹属于该合伙人的客户
    user = db.query(User).filter(User.id == parcel.user_id).first()
    if not user or user.partner_id != str(current_user.id):
        raise HTTPException(status_code=403, detail="无权访问此包裹")

    # 获取包裹中的商品
    items = db.query(OrderItem).filter(OrderItem.parcel_id == parcel_id).all()

    # 获取地址信息
    address = db.query(Address).filter(Address.id == parcel.address_id).first()

    # 构建商品列表
    items_data = []
    has_sensitive = False
    for item in items:
        if item.is_sensitive:
            has_sensitive = True
        
        items_data.append({
            "item_id": str(item.id),
            "product_name": item.product_name,
            "specification": item.specification,
            "quantity": item.quantity,
            "is_sensitive": item.is_sensitive,
            "internal_barcode": item.internal_barcode,
            "main_qc_image_url": item.main_qc_image_url,
            "warehouse_date": item.warehouse_date.isoformat() if item.warehouse_date else None
        })

    # 构建地址信息
    address_info = None
    if address:
        address_info = {
            "recipient_name": address.recipient_name,
            "phone": address.phone,
            "address_line1": address.address_line1,
            "address_line2": address.address_line2,
            "city": address.city,
            "state_province": address.state_province,
            "country": address.country,
            "postal_code": address.postal_code
        }

    return {
        "parcel_id": str(parcel.id),
        "parcel_number": parcel.parcel_number,
        "parcel_status": parcel.parcel_status,
        "user_id": str(parcel.user_id),
        "user_email": user.email if user else None,
        "weight_kg": float(parcel.weight_kg) if parcel.weight_kg else None,
        "length_cm": float(parcel.length_cm) if parcel.length_cm else None,
        "width_cm": float(parcel.width_cm) if parcel.width_cm else None,
        "height_cm": float(parcel.height_cm) if parcel.height_cm else None,
        "shipping_quote_usd": float(parcel.shipping_quote_usd) if parcel.shipping_quote_usd else None,
        "storage_fee_usd": float(parcel.storage_fee_usd) if parcel.storage_fee_usd else 0.0,
        "internal_tracking_no": parcel.internal_tracking_no,
        "international_tracking_no": parcel.international_tracking_no,
        "packing_note": parcel.packing_note,
        "has_sensitive_items": has_sensitive,
        "items": items_data,
        "address": address_info,
        "created_at": parcel.created_at.isoformat() if parcel.created_at else None,
        "packed_at": parcel.packed_at.isoformat() if hasattr(parcel, 'packed_at') and parcel.packed_at else None,
        "awaiting_shipment_at": parcel.awaiting_shipment_at.isoformat() if parcel.awaiting_shipment_at else None,
        "shipped_at": parcel.shipped_at.isoformat() if parcel.shipped_at else None
    }


@router.get("/orders/{order_id}/parcel")
def get_order_parcel(
    order_id: str,
    current_user: User = Depends(get_current_partner),
    db: Session = Depends(deps.get_db),
):
    """获取订单的包裹信息"""
    from app.models.order import Order, OrderItem
    from app.models.parcel import Parcel

    # 查询订单
    order = db.query(Order).filter(Order.id == order_id).first()
    if not order:
        raise HTTPException(status_code=404, detail="订单不存在")

    # 验证权限
    client = db.query(User).filter(User.id == order.user_id).first()
    if not client or client.partner_id != str(current_user.id):
        raise HTTPException(status_code=403, detail="无权访问此订单")

    # 查找包裹
    items = db.query(OrderItem).filter(OrderItem.order_id == order.id).all()
    if not items:
        raise HTTPException(status_code=404, detail="订单无商品")

    parcel_id = items[0].parcel_id
    if not parcel_id:
        raise HTTPException(status_code=404, detail="订单未关联包裹")

    parcel = db.query(Parcel).filter(Parcel.id == parcel_id).first()
    if not parcel:
        raise HTTPException(status_code=404, detail="包裹不存在")

    return {
        "parcel_id": str(parcel.id),
        "parcel_number": parcel.parcel_number,
        "status": parcel.parcel_status
    }


class SetParcelDimensionsRequest(BaseModel):
    parcel_id: str
    weight_kg: float
    length_cm: Optional[float] = None
    width_cm: Optional[float] = None
    height_cm: Optional[float] = None


class SubmitPackingRequest(BaseModel):
    """用于 /parcels/{parcel_id}/submit-packing 端点的请求模型（不含 parcel_id）"""
    weight_kg: float
    length_cm: Optional[float] = None
    width_cm: Optional[float] = None
    height_cm: Optional[float] = None


@router.post("/parcels/set-dimensions")
def set_parcel_dimensions(
    request: SetParcelDimensionsRequest,
    current_user: User = Depends(get_current_partner),
    db: Session = Depends(deps.get_db),
):
    """
    [Partner] 设置包裹重量体积（出库前必填）
    """
    from app.services.shipping_service import ShippingService
    from app.models.parcel import Parcel

    try:
        # 验证包裹属于该合伙人的客户
        parcel = db.query(Parcel).filter(Parcel.id == request.parcel_id).first()
        if not parcel:
            raise ValueError("Parcel not found")

        # 验证用户是该合伙人的客户
        from app.models.user import User
        user = db.query(User).filter(User.id == parcel.user_id).first()
        if not user or user.partner_id != str(current_user.id):
            raise ValueError("This parcel does not belong to your client")

        # 设置包裹尺寸
        parcel = ShippingService.set_parcel_dimensions(
            db=db,
            parcel_id=request.parcel_id,
            weight_kg=request.weight_kg,
            length_cm=request.length_cm,
            width_cm=request.width_cm,
            height_cm=request.height_cm
        )

        return {
            "success": True,
            "parcel_id": parcel.id,
            "parcel_number": parcel.parcel_number,
            "status": parcel.status,
            "weight_kg": float(parcel.weight_kg) if parcel.weight_kg else None,
            "message": "包裹尺寸已设置，等待报价"
        }
    except ValueError as e:
        raise HTTPException(status_code=400, detail=str(e))


@router.post("/orders/{order_id}/warehouse-receive")
def warehouse_receive(
    order_id: str,
    request: WarehouseReceiveRequest,
    current_user: User = Depends(get_current_partner),
    db: Session = Depends(deps.get_db),
):
    """
    仓库收货入库

    合伙人扫描包裹信息并上传质检图片，完成入库操作。
    订单状态从 awaiting_warehouse 变为 in_warehouse。
    """
    from app.services.partner_service import PartnerService

    try:
        order = PartnerService.warehouse_receive(
            db=db,
            order_id=order_id,
            domestic_tracking_no=request.domestic_tracking_no,
            internal_barcode=request.internal_barcode,
            qc_image_url=request.qc_image_url if request.qc_image_url else None,
            partner_id=str(current_user.id)
        )

        logger.info(
            f"Warehouse receive completed: order_id={order.id}, "
            f"partner_id={current_user.id}, "
            f"internal_barcode={request.internal_barcode}"
        )

        return {
            "success": True,
            "order_id": order.id,
            "message": "入库成功"
        }
    except ValueError as e:
        raise HTTPException(
            status_code=status.HTTP_400_BAD_REQUEST,
            detail=str(e)
        )


# ============================================================
# 新增：合伙人包裹视角 API
# ============================================================

@router.get("/parcels")
def get_partner_parcels(
    status: Optional[str] = Query(None, description="筛选包裹状态: packing_requested, awaiting_shipment, paid, shipped_waiting"),
    current_user: User = Depends(get_current_partner),
    db: Session = Depends(deps.get_db),
):
    """
    [Partner] 获取需要合伙人处理的包裹列表

    支持状态筛选：
    - packing_requested: 待打包（需要填写重量尺寸）
    - awaiting_shipment: 待发货（等待管理员报价）
    - paid: 已支付运费（等待发货）
    - shipped_waiting: 已发货等待国际单号

    如果不指定status参数，返回所有需要处理的包裹
    """
    from app.models.parcel import Parcel, Address
    from app.models.order import OrderItem
    from sqlalchemy.orm import joinedload

    # 定义合伙人需要处理的包裹状态
    partner_relevant_statuses = [
        ParcelStatus.PACKING_REQUESTED.value,
        ParcelStatus.AWAITING_SHIPMENT.value,
        ParcelStatus.SHIPPED_WAITING.value
    ]

    # 构建查询，使用 joinedload 预加载关联数据避免 N+1 查询
    query = db.query(Parcel).join(
        User, Parcel.user_id == User.id
    ).options(
        joinedload(Parcel.user),
        joinedload(Parcel.items),
        joinedload(Parcel.address)
    ).filter(
        User.partner_id == str(current_user.id)
    )

    # 如果指定了status参数，筛选该状态
    if status:
        # 验证状态是否有效
        valid_statuses = ['packing_requested', 'awaiting_shipment', 'paid', 'shipped_waiting']
        if status not in valid_statuses:
            raise HTTPException(
                status_code=status.HTTP_400_BAD_REQUEST,
                detail=f"无效的状态参数。有效值: {', '.join(valid_statuses)}"
            )

        # paid 状态在数据库中实际是 shipped_waiting（已支付，等待发货）
        if status == 'paid':
            status = ParcelStatus.SHIPPED_WAITING.value

        query = query.filter(Parcel.parcel_status == status)
    else:
        # 不指定status时，返回所有需要合伙人处理的包裹
        query = query.filter(Parcel.parcel_status.in_(partner_relevant_statuses))

    parcels = query.all()

    result = []
    for parcel in parcels:
        # 使用预加载的关联对象，避免额外查询
        user = parcel.user  # 已预加载
        items = parcel.items  # 已预加载
        address = parcel.address  # 已预加载

        result.append({
            "parcel_id": str(parcel.id),
            "parcel_number": parcel.parcel_number,
            "parcel_status": parcel.parcel_status,
            "item_count": len(items),
            "weight_kg": float(parcel.weight_kg) if parcel.weight_kg else None,
            "length_cm": float(parcel.length_cm) if parcel.length_cm else None,
            "width_cm": float(parcel.width_cm) if parcel.width_cm else None,
            "height_cm": float(parcel.height_cm) if parcel.height_cm else None,
            "tracking_number": parcel.international_tracking_no,
            "internal_tracking_no": parcel.internal_tracking_no,
            "shipping_quote_usd": float(parcel.shipping_quote_usd) if parcel.shipping_quote_usd else None,
            "user_email": user.email if user else None,
            "shipping_address": {
                "recipient_name": address.recipient_name if address else None,
                "full_address": f"{address.address_line1}, {address.city}, {address.state_province}, {address.country}" if address else None
            } if address else None,
            "items": [{
                "item_id": str(item.id),
                "product_name": item.product_name,
                "quantity": item.quantity,
                "internal_barcode": item.internal_barcode
            } for item in items],
            "created_at": parcel.created_at.isoformat() if parcel.created_at else None
        })

    return {"parcels": result, "total": len(result)}


@router.post("/parcels/{parcel_id}/submit-packing")
def submit_parcel_packing(
    parcel_id: str,
    request: SubmitPackingRequest,
    current_user: User = Depends(get_current_partner),
    db: Session = Depends(deps.get_db),
):
    """
    [Partner] 提交包裹打包信息

    合伙人填写包裹重量尺寸后提交，包裹状态从 packing_requested 变为 awaiting_shipment。
    同时设置 packed_at 和商品的 outbound_at 时间戳。
    """
    from app.services.shipping_service import ShippingService
    from app.models.parcel import Parcel
    from app.models.order import OrderItem
    from datetime import datetime

    try:
        # 验证包裹属于该合伙人的客户
        parcel = db.query(Parcel).filter(Parcel.id == parcel_id).first()
        if not parcel:
            raise ValueError("Parcel not found")

        # 验证用户是该合伙人的客户
        user = db.query(User).filter(User.id == parcel.user_id).first()
        if not user or user.partner_id != str(current_user.id):
            raise ValueError("This parcel does not belong to your client")

        # 调用现有的 set_parcel_dimensions 方法
        parcel = ShippingService.set_parcel_dimensions(
            db=db,
            parcel_id=parcel_id,
            weight_kg=request.weight_kg,
            length_cm=request.length_cm,
            width_cm=request.width_cm,
            height_cm=request.height_cm
        )

        # 设置新增的时间戳字段
        parcel.packed_at = datetime.utcnow()

        db.commit()
        db.refresh(parcel)

        logger.info(
            f"Parcel packing submitted: parcel_id={parcel_id}, "
            f"partner_id={current_user.id}, "
            f"weight_kg={request.weight_kg}"
        )

        return {
            "success": True,
            "parcel_id": str(parcel.id),
            "parcel_number": parcel.parcel_number,
            "parcel_status": parcel.parcel_status,
            "packed_at": parcel.packed_at.isoformat() if parcel.packed_at else None
        }
    except ValueError as e:
        raise HTTPException(status_code=400, detail=str(e))


@router.get("/orders/{order_number}/items")
def get_order_items_by_number(
    order_number: str,
    current_user: User = Depends(get_current_partner),
    db: Session = Depends(deps.get_db),
):
    """
    [Partner] 通过订单号查询商品（客户投诉场景）

    返回订单的商品信息，包括内部条码和出库包裹号。
    """
    from app.models.order import Order, OrderItem
    from app.models.parcel import Parcel

    # 查询订单
    order = db.query(Order).filter(Order.order_number == order_number).first()
    if not order:
        raise HTTPException(status_code=404, detail="订单不存在")

    # 验证权限
    client = db.query(User).filter(User.id == order.user_id).first()
    if not client or client.partner_id != str(current_user.id):
        raise HTTPException(status_code=403, detail="无权访问此订单")

    # 查询商品（一订单一商品）
    item = db.query(OrderItem).filter(OrderItem.order_id == order.id).first()
    if not item:
        raise HTTPException(status_code=404, detail="订单无商品")

    # 查询包裹号
    parcel_number = None
    if item.parcel_id:
        parcel = db.query(Parcel).filter(Parcel.id == item.parcel_id).first()
        if parcel:
            parcel_number = parcel.parcel_number

    return {
        "order_number": order_number,
        "item": {
            "item_id": str(item.id),
            "product_name": item.product_name,
            "quantity": item.quantity,
            "internal_barcode": item.internal_barcode,
            "item_status": item.item_status,
            "parcel_number": parcel_number
        }
    }


@router.get("/items/{item_id}/tracking-history")
def get_item_tracking_history(
    item_id: str,
    current_user: User = Depends(get_current_partner),
    db: Session = Depends(deps.get_db),
):
    """
    [Partner] 获取商品追踪历史

    返回商品的完整流转时间线。
    """
    from app.models.order import Order, OrderItem
    from app.models.parcel import Parcel

    # 查询商品
    item = db.query(OrderItem).filter(OrderItem.id == item_id).first()
    if not item:
        raise HTTPException(status_code=404, detail="商品不存在")

    # 验证权限
    order = db.query(Order).filter(Order.id == item.order_id).first()
    if not order:
        raise HTTPException(status_code=404, detail="订单不存在")

    client = db.query(User).filter(User.id == order.user_id).first()
    if not client or client.partner_id != str(current_user.id):
        raise HTTPException(status_code=403, detail="无权访问此商品")

    # 构建时间线
    timeline = []

    # 1. 购买下单
    if item.created_at:
        timeline.append({
            "event": "purchased",
            "timestamp": item.created_at.isoformat(),
            "order_number": order.order_number
        })

    # 2. 仓库签收
    if item.qc_started_at:
        timeline.append({
            "event": "warehouse_checkin",
            "timestamp": item.qc_started_at.isoformat(),
            "barcode": item.internal_barcode
        })

    # 3. 质检完成
    if item.qc_completed_at:
        timeline.append({
            "event": "qc_completed",
            "timestamp": item.qc_completed_at.isoformat()
        })

    # 4. 出库
    if item.outbound_at:
        parcel_number = None
        if item.parcel_id:
            parcel = db.query(Parcel).filter(Parcel.id == item.parcel_id).first()
            if parcel:
                parcel_number = parcel.parcel_number

        timeline.append({
            "event": "outbound",
            "timestamp": item.outbound_at.isoformat(),
            "parcel_number": parcel_number
        })

    return {
        "item_id": str(item.id),
        "product_name": item.product_name,
        "internal_barcode": item.internal_barcode,
        "timeline": timeline
    }


class ShipParcelRequest(BaseModel):
    internal_tracking_no: str = Field(..., min_length=1, max_length=100)


@router.post("/parcels/{parcel_id}/ship")
def ship_parcel(
    parcel_id: str,
    request: ShipParcelRequest,
    current_user: User = Depends(get_current_partner),
    db: Session = Depends(deps.get_db),
):
    """
    [Partner] 合伙人发货 - 填写中间物流单号

    合伙人将包裹发往国际物流前，填写中间物流单号。
    包裹状态必须是 shipped_waiting（已支付运费，等待发货）。
    """
    # 查询包裹
    parcel = db.query(Parcel).filter(Parcel.id == parcel_id).first()
    if not parcel:
        raise HTTPException(
            status_code=status.HTTP_404_NOT_FOUND,
            detail="包裹不存在"
        )

    # 验证包裹属于该合伙人的客户
    user = db.query(User).filter(User.id == parcel.user_id).first()
    if not user or user.partner_id != str(current_user.id):
        raise HTTPException(
            status_code=status.HTTP_403_FORBIDDEN,
            detail="无权操作此包裹"
        )

    # 验证包裹状态必须是 shipped_waiting
    if parcel.parcel_status != ParcelStatus.SHIPPED_WAITING.value:
        raise HTTPException(
            status_code=status.HTTP_400_BAD_REQUEST,
            detail=f"包裹状态错误：当前状态为 {parcel.parcel_status}，必须是 shipped_waiting"
        )

    # 更新中间物流单号（添加事务错误处理）
    old_tracking = parcel.internal_tracking_no
    try:
        parcel.internal_tracking_no = request.internal_tracking_no
        db.add(parcel)
        db.commit()
        db.refresh(parcel)
    except Exception as e:
        db.rollback()
        logger.error(f"Failed to update parcel {parcel_id}: {e}", exc_info=True)
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail="更新包裹失败"
        )

    # 记录操作日志
    try:
        AuditService.log_action(
            db=db,
            admin_id=str(current_user.id),
            action_type="ship_parcel",
            target_type="parcel",
            target_id=str(parcel.id),
            description=f"合伙人填写中间物流单号: {request.internal_tracking_no}",
            extra_data=json.dumps({
                "old_tracking": old_tracking,
                "new_tracking": request.internal_tracking_no,
                "parcel_number": parcel.parcel_number
            })
        )
    except Exception as e:
        logger.warning(f"Failed to log audit for parcel {parcel_id}: {e}")

    logger.info(
        f"Partner {current_user.id} shipped parcel {parcel_id}, "
        f"internal_tracking_no: {request.internal_tracking_no}"
    )

    return {
        "success": True,
        "parcel_id": str(parcel.id),
        "status": parcel.parcel_status
    }


class ParcelScanRequest(BaseModel):
    barcode: str = Field(..., min_length=1, max_length=50, description="扫描的条形码")


@router.post("/parcels/scan")
def scan_parcel_by_barcode(
    request: ParcelScanRequest,
    current_user: User = Depends(get_current_partner),
    db: Session = Depends(deps.get_db),
):
    """
    通过条形码扫描查询包裹详情
    
    返回：
    - 包裹详情（parcel_number, parcel_barcode, weight, dimensions, status）
    - 包裹内所有商品列表（商品名称、规格、internal_barcode、入库时间）
    - 客户信息（姓名、联系方式）
    - 订单号
    - 收货地址
    """
    from app.models.order import OrderItem
    
    # 查询包裹
    parcel = db.query(Parcel).filter(
        Parcel.parcel_barcode == request.barcode
    ).first()
    
    if not parcel:
        raise HTTPException(
            status_code=status.HTTP_404_NOT_FOUND,
            detail="未找到该条形码对应的包裹"
        )
    
    # 获取包裹内的所有商品
    items = db.query(OrderItem).filter(
        OrderItem.parcel_id == parcel.id
    ).all()
    
    # 获取客户信息
    user = db.query(User).filter(User.id == parcel.user_id).first()
    
    # 构建商品列表
    items_list = []
    for item in items:
        items_list.append({
            "id": str(item.id),
            "product_name": item.product_name,
            "product_specs": item.specification,
            "internal_barcode": item.internal_barcode,
            "quantity": item.quantity,
            "price_cny": float(item.unit_price_cny) if item.unit_price_cny else None,
            "received_at": item.warehouse_date.isoformat() if item.warehouse_date else None,
            "status": item.status,
        })
    
    # 构建地址信息（使用快照地址）
    address_info = {
        "recipient_name": parcel.snapshot_recipient_name,
        "phone": parcel.snapshot_phone,
        "address_line1": parcel.snapshot_address_line1,
        "address_line2": parcel.snapshot_address_line2,
        "city": parcel.snapshot_city,
        "state_province": parcel.snapshot_state_province,
        "country": parcel.snapshot_country,
        "postal_code": parcel.snapshot_postal_code,
    }
    
    # 构建响应
    result = {
        "parcel": {
            "id": str(parcel.id),
            "parcel_number": parcel.parcel_number,
            "parcel_barcode": parcel.parcel_barcode,
            "status": parcel.parcel_status,
            "weight_kg": float(parcel.weight_kg) if parcel.weight_kg else None,
            "length_cm": float(parcel.length_cm) if parcel.length_cm else None,
            "width_cm": float(parcel.width_cm) if parcel.width_cm else None,
            "height_cm": float(parcel.height_cm) if parcel.height_cm else None,
            "shipping_quote_usd": float(parcel.shipping_quote_usd) if parcel.shipping_quote_usd else None,
            "internal_tracking_no": parcel.internal_tracking_no,
            "international_tracking_no": parcel.international_tracking_no,
            "created_at": parcel.created_at.isoformat() if parcel.created_at else None,
        },
        "items": items_list,
        "customer": {
            "id": str(user.id),
            "email": user.email,
            "phone": user.phone if hasattr(user, 'phone') else None,
        },
        "address": address_info,
    }
    
    # 记录扫描操作
    try:
        AuditService.log_action(
            db=db,
            admin_id=str(current_user.id),
            action_type="scan_parcel",
            target_type="parcel",
            target_id=str(parcel.id),
            description=f"合伙人扫描包裹条形码: {request.barcode}",
            extra_data=json.dumps({
                "barcode": request.barcode,
                "parcel_number": parcel.parcel_number
            })
        )
    except Exception as e:
        logger.warning(f"Failed to log scan audit: {e}")
    
    return result
