"""Settings router — cemetery profile and fee catalog."""
from uuid import UUID
from typing import Optional

from fastapi import APIRouter, Depends, Query
from sqlalchemy import select, func
from sqlalchemy.ext.asyncio import AsyncSession

from src.core.dependencies import require_min_role, require_tenant
from src.core.constants import UserRole
from src.core.schemas.response import success, paginated
from src.core.exceptions import NotFoundError
from src.database.session import get_db
from src.apps.auth.models.user import User
from src.apps.tenants.models.account import Account
from src.apps.settings.models.fee_item import FeeItem
from src.apps.settings.schemas.requests import (
    FeeItemCreateRequest,
    FeeItemUpdateRequest,
    CemeteryProfileUpdateRequest,
)
from src.apps.settings.schemas.responses import FeeItemResponse, CemeteryProfileResponse

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


# --- Cemetery profile ---

@router.get("/profile")
async def get_profile(
    current_user: User = Depends(require_min_role(UserRole.STAFF)),
    tenant_id: str = Depends(require_tenant),
    db: AsyncSession = Depends(get_db),
):
    result = await db.execute(select(Account).where(Account.id == tenant_id))
    account = result.scalar_one_or_none()
    if not account:
        raise NotFoundError("Cemetery profile not found")
    return success(CemeteryProfileResponse.model_validate(account))


@router.patch("/profile")
async def update_profile(
    body: CemeteryProfileUpdateRequest,
    current_user: User = Depends(require_min_role(UserRole.ADMINISTRATOR)),
    tenant_id: str = Depends(require_tenant),
    db: AsyncSession = Depends(get_db),
):
    result = await db.execute(select(Account).where(Account.id == tenant_id))
    account = result.scalar_one_or_none()
    if not account:
        raise NotFoundError("Cemetery profile not found")
    for field, value in body.model_dump(exclude_unset=True).items():
        setattr(account, field, value)
    await db.flush()
    await db.refresh(account)
    return success(CemeteryProfileResponse.model_validate(account))


# --- Fee catalog ---

@router.get("/fees")
async def list_fees(
    page: int = Query(1, ge=1),
    page_size: int = Query(50, ge=1, le=200),
    category: Optional[str] = Query(None),
    active_only: bool = Query(True),
    current_user: User = Depends(require_min_role(UserRole.STAFF)),
    tenant_id: str = Depends(require_tenant),
    db: AsyncSession = Depends(get_db),
):
    filters = [FeeItem.tenant_id == tenant_id]
    if category:
        filters.append(FeeItem.category == category)
    if active_only:
        filters.append(FeeItem.is_active.is_(True))

    total = (
        await db.execute(select(func.count()).select_from(FeeItem).where(*filters))
    ).scalar_one()
    offset = (page - 1) * page_size
    result = await db.execute(
        select(FeeItem).where(*filters)
        .order_by(FeeItem.sort_order, FeeItem.name)
        .offset(offset).limit(page_size)
    )
    items = [FeeItemResponse.model_validate(f) for f in result.scalars().all()]
    return paginated(items, total, page, page_size)


@router.post("/fees", status_code=201)
async def create_fee(
    body: FeeItemCreateRequest,
    current_user: User = Depends(require_min_role(UserRole.ADMINISTRATOR)),
    tenant_id: str = Depends(require_tenant),
    db: AsyncSession = Depends(get_db),
):
    fee = FeeItem(tenant_id=tenant_id, **body.model_dump())
    db.add(fee)
    await db.flush()
    await db.refresh(fee)
    return success(FeeItemResponse.model_validate(fee), "Fee item created")


@router.patch("/fees/{fee_id}")
async def update_fee(
    fee_id: UUID,
    body: FeeItemUpdateRequest,
    current_user: User = Depends(require_min_role(UserRole.ADMINISTRATOR)),
    tenant_id: str = Depends(require_tenant),
    db: AsyncSession = Depends(get_db),
):
    result = await db.execute(
        select(FeeItem).where(FeeItem.id == fee_id, FeeItem.tenant_id == tenant_id)
    )
    fee = result.scalar_one_or_none()
    if not fee:
        raise NotFoundError("Fee item not found")
    for field, value in body.model_dump(exclude_unset=True).items():
        setattr(fee, field, value)
    await db.flush()
    await db.refresh(fee)
    return success(FeeItemResponse.model_validate(fee))


@router.delete("/fees/{fee_id}", status_code=204)
async def delete_fee(
    fee_id: UUID,
    current_user: User = Depends(require_min_role(UserRole.ADMINISTRATOR)),
    tenant_id: str = Depends(require_tenant),
    db: AsyncSession = Depends(get_db),
):
    result = await db.execute(
        select(FeeItem).where(FeeItem.id == fee_id, FeeItem.tenant_id == tenant_id)
    )
    fee = result.scalar_one_or_none()
    if not fee:
        raise NotFoundError("Fee item not found")
    await db.delete(fee)
