"""Pricing tiers router — CRUD for category × quality-level price configuration."""
from datetime import datetime
from decimal import Decimal
from typing import Optional
import uuid

from fastapi import APIRouter, Depends, HTTPException, status
from pydantic import BaseModel
from sqlalchemy import select, update as sql_update
from sqlalchemy.exc import IntegrityError
from sqlalchemy.ext.asyncio import AsyncSession

from app.database import get_db
from app.models.pricing_tier import PricingTier
from app.models.user import User
from app.utils.auth import require_admin_or_pm, get_current_user

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


# ── Schemas ────────────────────────────────────────────────────────────────────

class PricingTierOut(BaseModel):
    id: int
    category_key: str
    quality_level: str
    price_per_item: float
    description: Optional[str]
    is_active: bool
    created_at: datetime
    updated_at: datetime

    model_config = {"from_attributes": True}


class PricingTierCreate(BaseModel):
    category_key: str
    quality_level: str = "Normal"
    price_per_item: Decimal
    description: Optional[str] = None
    is_active: bool = True


class PricingTierPatch(BaseModel):
    category_key: Optional[str] = None
    quality_level: Optional[str] = None
    price_per_item: Optional[Decimal] = None
    description: Optional[str] = None
    is_active: Optional[bool] = None


# ── Endpoints ──────────────────────────────────────────────────────────────────

@router.get("", response_model=list[PricingTierOut])
async def list_pricing_tiers(
    _user: User = Depends(require_admin_or_pm),
    db: AsyncSession = Depends(get_db),
) -> list[PricingTierOut]:
    result = await db.execute(
        select(PricingTier).order_by(PricingTier.category_key, PricingTier.quality_level)
    )
    return result.scalars().all()


@router.post("", response_model=PricingTierOut, status_code=status.HTTP_201_CREATED)
async def create_pricing_tier(
    body: PricingTierCreate,
    _user: User = Depends(require_admin_or_pm),
    db: AsyncSession = Depends(get_db),
) -> PricingTierOut:
    tier = PricingTier(
        category_key=body.category_key,
        quality_level=body.quality_level,
        price_per_item=body.price_per_item,
        description=body.description,
        is_active=body.is_active,
    )
    db.add(tier)
    try:
        await db.commit()
        await db.refresh(tier)
    except IntegrityError:
        await db.rollback()
        raise HTTPException(
            status_code=409,
            detail=f"Pricing tier for '{body.category_key}' / '{body.quality_level}' already exists",
        )
    return tier


@router.patch("/{tier_id}", response_model=PricingTierOut)
async def update_pricing_tier(
    tier_id: int,
    body: PricingTierPatch,
    _user: User = Depends(require_admin_or_pm),
    db: AsyncSession = Depends(get_db),
) -> PricingTierOut:
    result = await db.execute(select(PricingTier).where(PricingTier.id == tier_id))
    tier = result.scalar_one_or_none()
    if tier is None:
        raise HTTPException(status_code=404, detail="Pricing tier not found")

    patch = body.model_dump(exclude_unset=True)
    if patch:
        patch["updated_at"] = datetime.utcnow()
        await db.execute(
            sql_update(PricingTier).where(PricingTier.id == tier_id).values(**patch)
        )
        await db.commit()
        result = await db.execute(select(PricingTier).where(PricingTier.id == tier_id))
        tier = result.scalar_one()
    return tier


@router.delete("/{tier_id}", status_code=status.HTTP_204_NO_CONTENT)
async def delete_pricing_tier(
    tier_id: int,
    _user: User = Depends(require_admin_or_pm),
    db: AsyncSession = Depends(get_db),
) -> None:
    result = await db.execute(select(PricingTier).where(PricingTier.id == tier_id))
    tier = result.scalar_one_or_none()
    if tier is None:
        raise HTTPException(status_code=404, detail="Pricing tier not found")
    await db.delete(tier)
    await db.commit()


# ── Price Estimation ──────────────────────────────────────────────────────────

class EstimateLineInput(BaseModel):
    product_id: uuid.UUID
    output_type_id: uuid.UUID | None = None


class EstimateRequest(BaseModel):
    lines: list[EstimateLineInput]


@router.post("/estimate")
async def estimate_price(
    body: EstimateRequest,
    _user: User = Depends(get_current_user),
    db: AsyncSession = Depends(get_db),
):
    """Estimate the total price for a set of prospective order lines.

    Open to all authenticated users (read-only, needed by wizard).
    """
    from app.services.pricing_service import estimate_order_price
    lines_dicts = [{"product_id": str(l.product_id), "output_type_id": str(l.output_type_id) if l.output_type_id else None} for l in body.lines]
    return await estimate_order_price(db, lines_dicts)
