"""Products router — endpoints for the global product catalogue and price history."""

from fastapi import APIRouter, Depends, HTTPException, status
from sqlalchemy.ext.asyncio import AsyncSession

from app.core.database import get_db
from app.dependencies import get_current_user
from app.models.user import User
from app.schemas.product import ProdukCreate, ProdukHargaCreate, ProdukHargaResponse, ProdukResponse, ProdukUpdate
from app.services import product_service


def _service_error(e: ValueError | PermissionError) -> HTTPException:
    """Convert service-layer ValueError → 404 and PermissionError → 403."""
    if isinstance(e, PermissionError):
        return HTTPException(status_code=status.HTTP_403_FORBIDDEN, detail=str(e))
    return HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail=str(e))


router = APIRouter()


@router.get("", response_model=dict)
async def list_products(
    skip: int = 0,
    limit: int = 50,
    db: AsyncSession = Depends(get_db),
    current_user: User = Depends(get_current_user),
) -> dict:
    """Return a paginated list of all products with their current prices."""
    products, total = await product_service.list_products(db, skip, limit)
    return {
        "data": products,
        "meta": {"total": total, "page": skip // limit + 1, "per_page": limit},
    }


@router.post("", response_model=dict, status_code=status.HTTP_201_CREATED)
async def create_product(
    data: ProdukCreate,
    db: AsyncSession = Depends(get_db),
    current_user: User = Depends(get_current_user),
) -> dict:
    """Create a new product in the global catalogue, optionally with an initial price."""
    produk = await product_service.create_product(db, data)
    return {"data": {"id": produk.id, "nama": produk.nama, "kode": produk.kode}, "message": "Produk berhasil dibuat"}


@router.get("/{produk_id}", response_model=dict)
async def get_product(
    produk_id: int,
    db: AsyncSession = Depends(get_db),
    current_user: User = Depends(get_current_user),
) -> dict:
    """Return details for a single product including its full price history."""
    try:
        produk = await product_service.get_product(db, produk_id)
    except ValueError as e:
        raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail=str(e))
    return {"data": ProdukResponse.model_validate(produk)}


@router.patch("/{produk_id}", response_model=dict)
async def update_product(
    produk_id: int,
    data: ProdukUpdate,
    db: AsyncSession = Depends(get_db),
    current_user: User = Depends(get_current_user),
) -> dict:
    """Update scalar fields on a product."""
    try:
        produk = await product_service.update_product(db, produk_id, data)
    except ValueError as e:
        raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail=str(e))
    return {"data": ProdukResponse.model_validate(produk), "message": "Produk berhasil diupdate"}


@router.get("/{produk_id}/harga", response_model=dict)
async def get_harga_history(
    produk_id: int,
    db: AsyncSession = Depends(get_db),
    current_user: User = Depends(get_current_user),
) -> dict:
    """Return the full price history for a product, newest first."""
    try:
        history = await product_service.get_harga_history(db, produk_id)
    except ValueError as e:
        raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail=str(e))
    return {"data": [ProdukHargaResponse.model_validate(h) for h in history]}


@router.post("/{produk_id}/harga", response_model=dict, status_code=status.HTTP_201_CREATED)
async def add_harga(
    produk_id: int,
    data: ProdukHargaCreate,
    db: AsyncSession = Depends(get_db),
    current_user: User = Depends(get_current_user),
) -> dict:
    """Add a new price entry for a product, automatically closing the previous active price."""
    try:
        harga = await product_service.add_harga(db, produk_id, data)
    except ValueError as e:
        raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail=str(e))
    return {"data": ProdukHargaResponse.model_validate(harga), "message": "Harga berhasil ditambahkan"}
