# app/api/v1/admin/inventory.py
"""
Admin inventory management endpoints.

Provides inventory management capabilities for administrators:
- View inventory across all vendors
- View vendor-specific inventory
- Set/adjust inventory on behalf of vendors
- Low stock alerts and reporting

Admin Context: Uses admin JWT authentication.
Vendor selection is passed as a request parameter.
"""

import logging

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

from app.api.deps import get_current_admin_api
from app.core.database import get_db
from app.services.inventory_service import inventory_service
from models.database.user import User
from models.schema.inventory import (
    AdminInventoryAdjust,
    AdminInventoryCreate,
    AdminInventoryListResponse,
    AdminInventoryLocationsResponse,
    AdminInventoryStats,
    AdminLowStockItem,
    AdminVendorsWithInventoryResponse,
    InventoryAdjust,
    InventoryCreate,
    InventoryMessageResponse,
    InventoryResponse,
    InventoryUpdate,
    ProductInventorySummary,
)

router = APIRouter(prefix="/inventory")
logger = logging.getLogger(__name__)


# ============================================================================
# List & Statistics Endpoints
# ============================================================================


@router.get("", response_model=AdminInventoryListResponse)
def get_all_inventory(
    skip: int = Query(0, ge=0),
    limit: int = Query(50, ge=1, le=500),
    vendor_id: int | None = Query(None, description="Filter by vendor"),
    location: str | None = Query(None, description="Filter by location"),
    low_stock: int | None = Query(None, ge=0, description="Filter items below threshold"),
    search: str | None = Query(None, description="Search by product title or SKU"),
    db: Session = Depends(get_db),
    current_admin: User = Depends(get_current_admin_api),
):
    """
    Get inventory across all vendors with filtering.

    Allows admins to view and filter inventory across the platform.
    """
    return inventory_service.get_all_inventory_admin(
        db=db,
        skip=skip,
        limit=limit,
        vendor_id=vendor_id,
        location=location,
        low_stock=low_stock,
        search=search,
    )


@router.get("/stats", response_model=AdminInventoryStats)
def get_inventory_stats(
    db: Session = Depends(get_db),
    current_admin: User = Depends(get_current_admin_api),
):
    """Get platform-wide inventory statistics."""
    return inventory_service.get_inventory_stats_admin(db)


@router.get("/low-stock", response_model=list[AdminLowStockItem])
def get_low_stock_items(
    threshold: int = Query(10, ge=0, description="Stock threshold"),
    vendor_id: int | None = Query(None, description="Filter by vendor"),
    limit: int = Query(50, ge=1, le=200),
    db: Session = Depends(get_db),
    current_admin: User = Depends(get_current_admin_api),
):
    """Get items with low stock levels."""
    return inventory_service.get_low_stock_items_admin(
        db=db,
        threshold=threshold,
        vendor_id=vendor_id,
        limit=limit,
    )


@router.get("/vendors", response_model=AdminVendorsWithInventoryResponse)
def get_vendors_with_inventory(
    db: Session = Depends(get_db),
    current_admin: User = Depends(get_current_admin_api),
):
    """Get list of vendors that have inventory entries."""
    return inventory_service.get_vendors_with_inventory_admin(db)


@router.get("/locations", response_model=AdminInventoryLocationsResponse)
def get_inventory_locations(
    vendor_id: int | None = Query(None, description="Filter by vendor"),
    db: Session = Depends(get_db),
    current_admin: User = Depends(get_current_admin_api),
):
    """Get list of unique inventory locations."""
    return inventory_service.get_inventory_locations_admin(db, vendor_id)


# ============================================================================
# Vendor-Specific Endpoints
# ============================================================================


@router.get("/vendors/{vendor_id}", response_model=AdminInventoryListResponse)
def get_vendor_inventory(
    vendor_id: int,
    skip: int = Query(0, ge=0),
    limit: int = Query(50, ge=1, le=500),
    location: str | None = Query(None, description="Filter by location"),
    low_stock: int | None = Query(None, ge=0, description="Filter items below threshold"),
    db: Session = Depends(get_db),
    current_admin: User = Depends(get_current_admin_api),
):
    """Get inventory for a specific vendor."""
    return inventory_service.get_vendor_inventory_admin(
        db=db,
        vendor_id=vendor_id,
        skip=skip,
        limit=limit,
        location=location,
        low_stock=low_stock,
    )


@router.get("/products/{product_id}", response_model=ProductInventorySummary)
def get_product_inventory(
    product_id: int,
    db: Session = Depends(get_db),
    current_admin: User = Depends(get_current_admin_api),
):
    """Get inventory summary for a specific product across all locations."""
    return inventory_service.get_product_inventory_admin(db, product_id)


# ============================================================================
# Inventory Modification Endpoints
# ============================================================================


@router.post("/set", response_model=InventoryResponse)
def set_inventory(
    inventory_data: AdminInventoryCreate,
    db: Session = Depends(get_db),
    current_admin: User = Depends(get_current_admin_api),
):
    """
    Set exact inventory quantity for a product at a location.

    Admin version - requires explicit vendor_id in request body.
    """
    # Verify vendor exists
    inventory_service.verify_vendor_exists(db, inventory_data.vendor_id)

    # Convert to standard schema for service
    service_data = InventoryCreate(
        product_id=inventory_data.product_id,
        location=inventory_data.location,
        quantity=inventory_data.quantity,
    )

    result = inventory_service.set_inventory(
        db=db,
        vendor_id=inventory_data.vendor_id,
        inventory_data=service_data,
    )

    logger.info(
        f"Admin {current_admin.email} set inventory for product {inventory_data.product_id} "
        f"at {inventory_data.location}: {inventory_data.quantity} units"
    )

    db.commit()
    return result


@router.post("/adjust", response_model=InventoryResponse)
def adjust_inventory(
    adjustment: AdminInventoryAdjust,
    db: Session = Depends(get_db),
    current_admin: User = Depends(get_current_admin_api),
):
    """
    Adjust inventory by adding or removing quantity.

    Positive quantity = add stock, negative = remove stock.
    Admin version - requires explicit vendor_id in request body.
    """
    # Verify vendor exists
    inventory_service.verify_vendor_exists(db, adjustment.vendor_id)

    # Convert to standard schema for service
    service_data = InventoryAdjust(
        product_id=adjustment.product_id,
        location=adjustment.location,
        quantity=adjustment.quantity,
    )

    result = inventory_service.adjust_inventory(
        db=db,
        vendor_id=adjustment.vendor_id,
        inventory_data=service_data,
    )

    sign = "+" if adjustment.quantity >= 0 else ""
    logger.info(
        f"Admin {current_admin.email} adjusted inventory for product {adjustment.product_id} "
        f"at {adjustment.location}: {sign}{adjustment.quantity} units"
        f"{f' (reason: {adjustment.reason})' if adjustment.reason else ''}"
    )

    db.commit()
    return result


@router.put("/{inventory_id}", response_model=InventoryResponse)
def update_inventory(
    inventory_id: int,
    inventory_update: InventoryUpdate,
    db: Session = Depends(get_db),
    current_admin: User = Depends(get_current_admin_api),
):
    """Update inventory entry fields."""
    # Get inventory to find vendor_id
    inventory = inventory_service.get_inventory_by_id_admin(db, inventory_id)

    result = inventory_service.update_inventory(
        db=db,
        vendor_id=inventory.vendor_id,
        inventory_id=inventory_id,
        inventory_update=inventory_update,
    )

    logger.info(f"Admin {current_admin.email} updated inventory {inventory_id}")

    db.commit()
    return result


@router.delete("/{inventory_id}", response_model=InventoryMessageResponse)
def delete_inventory(
    inventory_id: int,
    db: Session = Depends(get_db),
    current_admin: User = Depends(get_current_admin_api),
):
    """Delete inventory entry."""
    # Get inventory to find vendor_id and log details
    inventory = inventory_service.get_inventory_by_id_admin(db, inventory_id)
    vendor_id = inventory.vendor_id
    product_id = inventory.product_id
    location = inventory.location

    inventory_service.delete_inventory(
        db=db,
        vendor_id=vendor_id,
        inventory_id=inventory_id,
    )

    logger.info(
        f"Admin {current_admin.email} deleted inventory {inventory_id} "
        f"(product {product_id} at {location})"
    )

    db.commit()
    return InventoryMessageResponse(message="Inventory deleted successfully")
