from __future__ import annotations

from typing import Annotated

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

from app.api.deps import get_current_user
from app.core.i18n import Language, get_language, localized_value
from app.db.session import get_db
from app.models.master_data import BudgetHead, OFESEstablishment
from app.models.procurement import ItemDatabase
from app.schemas.master_data import BudgetHeadRead, ItemMasterRead, OFESEstablishmentRead

router = APIRouter(dependencies=[Depends(get_current_user)])


def localized_dict(record, language: Language, fields: tuple[str, ...]) -> dict:
    data = record.__dict__.copy()
    data.pop("_sa_instance_state", None)
    for field in fields:
        data[field] = localized_value(record, field, language)
    return data


@router.get("/budget-heads", response_model=list[BudgetHeadRead])
def list_budget_heads(
    db: Annotated[Session, Depends(get_db)],
    language: Annotated[Language, Depends(get_language)],
    active_only: bool = True,
    search: str | None = Query(default=None),
):
    query = db.query(BudgetHead)
    if active_only:
        query = query.filter(BudgetHead.is_active.is_(True))
    if search:
        term = f"%{search}%"
        query = query.filter(
            or_(
                BudgetHead.display_name.like(term),
                BudgetHead.category_name.like(term),
                BudgetHead.fund_source.like(term),
                BudgetHead.expenditure_head.like(term),
                BudgetHead.item_component.like(term),
            )
        )
    rows = query.order_by(BudgetHead.display_name.asc()).all()
    return [
        localized_dict(row, language, ("display_name", "category_name", "expenditure_head", "item_component"))
        for row in rows
    ]


@router.get("/establishments", response_model=list[OFESEstablishmentRead])
def list_establishments(
    db: Annotated[Session, Depends(get_db)],
    language: Annotated[Language, Depends(get_language)],
    active_only: bool = True,
    search: str | None = Query(default=None),
    limit: int = Query(default=1000, ge=1, le=1000),
):
    query = db.query(OFESEstablishment)
    if active_only:
        query = query.filter(OFESEstablishment.is_active.is_(True))
    if search:
        term = f"%{search}%"
        query = query.filter(
            or_(
                OFESEstablishment.display_name.like(term),
                OFESEstablishment.name.like(term),
                OFESEstablishment.district.like(term),
                OFESEstablishment.range_name.like(term),
            )
        )
    rows = query.order_by(OFESEstablishment.display_name.asc()).limit(limit).all()
    return [
        localized_dict(row, language, ("name", "district", "range_name", "display_name"))
        for row in rows
    ]


@router.get("/items", response_model=list[ItemMasterRead])
def list_items(
    db: Annotated[Session, Depends(get_db)],
    language: Annotated[Language, Depends(get_language)],
    active_only: bool = True,
    search: str | None = Query(default=None),
    item_type: str | None = Query(default=None),
    limit: int = Query(default=500, ge=1, le=1000),
):
    query = db.query(ItemDatabase)
    if active_only:
        query = query.filter(ItemDatabase.is_active.is_(True))
    if item_type:
        query = query.filter(ItemDatabase.item_type == item_type)
    if search:
        term = f"%{search}%"
        query = query.filter(
            or_(
                ItemDatabase.name.like(term),
                ItemDatabase.item_type.like(term),
            )
        )
    rows = query.order_by(ItemDatabase.item_type.asc(), ItemDatabase.name.asc()).limit(limit).all()
    return [localized_dict(row, language, ("name", "item_type")) for row in rows]


@router.get("/item-types", response_model=list[str])
def list_item_types(
    db: Annotated[Session, Depends(get_db)],
    language: Annotated[Language, Depends(get_language)],
    active_only: bool = True,
):
    query = db.query(ItemDatabase.item_type)
    if active_only:
        query = query.filter(ItemDatabase.is_active.is_(True))
    rows = query.distinct().order_by(ItemDatabase.item_type.asc()).all()
    values = []
    for row in rows:
        if not row[0]:
            continue
        item = db.query(ItemDatabase).filter(ItemDatabase.item_type == row[0]).first()
        values.append(localized_value(item, "item_type", language) if item else row[0])
    return [value for value in values if value]
