# app/modules/orders/routes/api/store_exceptions.py
"""
Store API endpoints for order item exception management.

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

import logging

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

from app.api.deps import get_current_store_api, require_module_access
from app.core.database import get_db
from app.modules.enums import FrontendType
from app.modules.orders.schemas import (
    BulkResolveRequest,
    BulkResolveResponse,
    IgnoreExceptionRequest,
    OrderItemExceptionListResponse,
    OrderItemExceptionResponse,
    OrderItemExceptionStats,
    ResolveExceptionRequest,
)
from app.modules.orders.services.order_item_exception_service import (
    order_item_exception_service,
)
from app.modules.tenancy.schemas.auth import UserContext

logger = logging.getLogger(__name__)

store_exceptions_router = APIRouter(
    prefix="/order-exceptions",
    tags=["Store Order Item Exceptions"],
    dependencies=[Depends(require_module_access("orders", FrontendType.STORE))],
)


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


@store_exceptions_router.get("", response_model=OrderItemExceptionListResponse)
def list_store_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: UserContext = Depends(get_current_store_api),
    db: Session = Depends(get_db),
):
    """
    List order item exceptions for the authenticated store.

    Returns exceptions for unmatched products during marketplace order imports.
    """
    store_id = current_user.token_store_id

    exceptions, total = order_item_exception_service.get_pending_exceptions(
        db=db,
        store_id=store_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,
    )


@store_exceptions_router.get("/stats", response_model=OrderItemExceptionStats)
def get_store_exception_stats(
    current_user: UserContext = Depends(get_current_store_api),
    db: Session = Depends(get_db),
):
    """
    Get exception statistics for the authenticated store.

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


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


@store_exceptions_router.get("/{exception_id}", response_model=OrderItemExceptionResponse)
def get_store_exception(
    exception_id: int = Path(..., description="Exception ID"),
    current_user: UserContext = Depends(get_current_store_api),
    db: Session = Depends(get_db),
):
    """
    Get details of a single exception (store-scoped).
    """
    store_id = current_user.token_store_id

    # Pass store_id for scoped access
    exception = order_item_exception_service.get_exception_by_id(
        db, exception_id, store_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
# ============================================================================


@store_exceptions_router.post("/{exception_id}/resolve", response_model=OrderItemExceptionResponse)
def resolve_store_exception(
    exception_id: int = Path(..., description="Exception ID"),
    request: ResolveExceptionRequest = ...,
    current_user: UserContext = Depends(get_current_store_api),
    db: Session = Depends(get_db),
):
    """
    Resolve an exception by assigning a product (store-scoped).

    This updates the order item's product_id and marks the exception as resolved.
    """
    store_id = current_user.token_store_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,
        store_id=store_id,  # Store-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"Store user {current_user.id} resolved exception {exception_id} "
        f"with product {request.product_id}"
    )

    return response


@store_exceptions_router.post("/{exception_id}/ignore", response_model=OrderItemExceptionResponse)
def ignore_store_exception(
    exception_id: int = Path(..., description="Exception ID"),
    request: IgnoreExceptionRequest = ...,
    current_user: UserContext = Depends(get_current_store_api),
    db: Session = Depends(get_db),
):
    """
    Mark an exception as ignored (store-scoped).

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

    exception = order_item_exception_service.ignore_exception(
        db=db,
        exception_id=exception_id,
        resolved_by=current_user.id,
        notes=request.notes,
        store_id=store_id,  # Store-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"Store user {current_user.id} ignored exception {exception_id}: {request.notes}"
    )

    return response


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


@store_exceptions_router.post("/bulk-resolve", response_model=BulkResolveResponse)
def bulk_resolve_store_exceptions(
    request: BulkResolveRequest,
    current_user: UserContext = Depends(get_current_store_api),
    db: Session = Depends(get_db),
):
    """
    Bulk resolve all pending exceptions for a GTIN (store-scoped).

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

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

    logger.info(
        f"Store 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,
    )
