# app/api/v1/vendor/order_item_exceptions.py
"""
Vendor API endpoints for order item exception management.

Provides vendor-level management of:
- Listing vendor's own exceptions
- Resolving exceptions by assigning products
- Exception statistics for vendor dashboard
"""

import logging

from fastapi import APIRouter, Depends, Path, Query
from sqlalchemy.orm import Session

from app.api.deps import get_current_vendor_api
from app.core.database import get_db
from app.services.order_item_exception_service import order_item_exception_service
from models.database.user import User
from models.schema.order_item_exception import (
    BulkResolveRequest,
    BulkResolveResponse,
    IgnoreExceptionRequest,
    OrderItemExceptionListResponse,
    OrderItemExceptionResponse,
    OrderItemExceptionStats,
    ResolveExceptionRequest,
)

logger = logging.getLogger(__name__)

router = APIRouter(prefix="/order-exceptions", tags=["Vendor Order Item Exceptions"])


# ============================================================================
# Exception Listing and Stats
# ============================================================================


@router.get("", response_model=OrderItemExceptionListResponse)
def list_vendor_exceptions(
    status: str | None = Query(
        None,
        pattern="^(pending|resolved|ignored)$",
        description="Filter by status"
    ),
    search: str | None = Query(
        None,
        description="Search in GTIN, product name, SKU, or order number"
    ),
    skip: int = Query(0, ge=0),
    limit: int = Query(50, ge=1, le=200),
    current_user: User = Depends(get_current_vendor_api),
    db: Session = Depends(get_db),
):
    """
    List order item exceptions for the authenticated vendor.

    Returns exceptions for unmatched products during marketplace order imports.
    """
    vendor_id = current_user.token_vendor_id

    exceptions, total = order_item_exception_service.get_pending_exceptions(
        db=db,
        vendor_id=vendor_id,
        status=status,
        search=search,
        skip=skip,
        limit=limit,
    )

    # Enrich with order info
    response_items = []
    for exc in exceptions:
        item = OrderItemExceptionResponse.model_validate(exc)
        if exc.order_item and exc.order_item.order:
            order = exc.order_item.order
            item.order_number = order.order_number
            item.order_id = order.id
            item.order_date = order.order_date
            item.order_status = order.status
        response_items.append(item)

    return OrderItemExceptionListResponse(
        exceptions=response_items,
        total=total,
        skip=skip,
        limit=limit,
    )


@router.get("/stats", response_model=OrderItemExceptionStats)
def get_vendor_exception_stats(
    current_user: User = Depends(get_current_vendor_api),
    db: Session = Depends(get_db),
):
    """
    Get exception statistics for the authenticated vendor.

    Returns counts of pending, resolved, and ignored exceptions.
    """
    vendor_id = current_user.token_vendor_id
    stats = order_item_exception_service.get_exception_stats(db, vendor_id)
    return OrderItemExceptionStats(**stats)


# ============================================================================
# Exception Details
# ============================================================================


@router.get("/{exception_id}", response_model=OrderItemExceptionResponse)
def get_vendor_exception(
    exception_id: int = Path(..., description="Exception ID"),
    current_user: User = Depends(get_current_vendor_api),
    db: Session = Depends(get_db),
):
    """
    Get details of a single exception (vendor-scoped).
    """
    vendor_id = current_user.token_vendor_id

    # Pass vendor_id for scoped access
    exception = order_item_exception_service.get_exception_by_id(
        db, exception_id, vendor_id
    )

    response = OrderItemExceptionResponse.model_validate(exception)
    if exception.order_item and exception.order_item.order:
        order = exception.order_item.order
        response.order_number = order.order_number
        response.order_id = order.id
        response.order_date = order.order_date
        response.order_status = order.status

    return response


# ============================================================================
# Exception Resolution
# ============================================================================


@router.post("/{exception_id}/resolve", response_model=OrderItemExceptionResponse)
def resolve_vendor_exception(
    exception_id: int = Path(..., description="Exception ID"),
    request: ResolveExceptionRequest = ...,
    current_user: User = Depends(get_current_vendor_api),
    db: Session = Depends(get_db),
):
    """
    Resolve an exception by assigning a product (vendor-scoped).

    This updates the order item's product_id and marks the exception as resolved.
    """
    vendor_id = current_user.token_vendor_id

    exception = order_item_exception_service.resolve_exception(
        db=db,
        exception_id=exception_id,
        product_id=request.product_id,
        resolved_by=current_user.id,
        notes=request.notes,
        vendor_id=vendor_id,  # Vendor-scoped access
    )
    db.commit()

    response = OrderItemExceptionResponse.model_validate(exception)
    if exception.order_item and exception.order_item.order:
        order = exception.order_item.order
        response.order_number = order.order_number
        response.order_id = order.id
        response.order_date = order.order_date
        response.order_status = order.status

    logger.info(
        f"Vendor user {current_user.id} resolved exception {exception_id} "
        f"with product {request.product_id}"
    )

    return response


@router.post("/{exception_id}/ignore", response_model=OrderItemExceptionResponse)
def ignore_vendor_exception(
    exception_id: int = Path(..., description="Exception ID"),
    request: IgnoreExceptionRequest = ...,
    current_user: User = Depends(get_current_vendor_api),
    db: Session = Depends(get_db),
):
    """
    Mark an exception as ignored (vendor-scoped).

    Note: Ignored exceptions still block order confirmation.
    Use this when a product will never be matched (e.g., discontinued).
    """
    vendor_id = current_user.token_vendor_id

    exception = order_item_exception_service.ignore_exception(
        db=db,
        exception_id=exception_id,
        resolved_by=current_user.id,
        notes=request.notes,
        vendor_id=vendor_id,  # Vendor-scoped access
    )
    db.commit()

    response = OrderItemExceptionResponse.model_validate(exception)
    if exception.order_item and exception.order_item.order:
        order = exception.order_item.order
        response.order_number = order.order_number
        response.order_id = order.id
        response.order_date = order.order_date
        response.order_status = order.status

    logger.info(
        f"Vendor user {current_user.id} ignored exception {exception_id}: {request.notes}"
    )

    return response


# ============================================================================
# Bulk Operations
# ============================================================================


@router.post("/bulk-resolve", response_model=BulkResolveResponse)
def bulk_resolve_vendor_exceptions(
    request: BulkResolveRequest,
    current_user: User = Depends(get_current_vendor_api),
    db: Session = Depends(get_db),
):
    """
    Bulk resolve all pending exceptions for a GTIN (vendor-scoped).

    Useful when a new product is imported and multiple orders have
    items with the same unmatched GTIN.
    """
    vendor_id = current_user.token_vendor_id

    resolved_count = order_item_exception_service.bulk_resolve_by_gtin(
        db=db,
        vendor_id=vendor_id,
        gtin=request.gtin,
        product_id=request.product_id,
        resolved_by=current_user.id,
        notes=request.notes,
    )
    db.commit()

    logger.info(
        f"Vendor user {current_user.id} bulk resolved {resolved_count} exceptions "
        f"for GTIN {request.gtin} with product {request.product_id}"
    )

    return BulkResolveResponse(
        resolved_count=resolved_count,
        gtin=request.gtin,
        product_id=request.product_id,
    )
