"""Customer + connection lookups.

Customers are born from installed applications, so there is no create endpoint here.
Equipment hand-outs and complaints both need to find a customer and one of their
connections, which is all this router does.
"""
from fastapi import APIRouter, Depends, HTTPException, Query, status
from sqlalchemy import func, or_, select
from sqlalchemy.orm import Session, joinedload, selectinload

from app.api.deps import get_current_user
from app.db.session import get_db
from app.models.customer import Connection, Customer
from app.models.enums import ConnectionStatus
from app.models.reference import Area
from app.models.user import User
from app.schemas.common import Page
from app.schemas.customer import ConnectionBrief, ConnectionOut, CustomerDetail, CustomerListItem

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

_AREA_LOAD = joinedload(Customer.area).joinedload(Area.zone)


@router.get("", response_model=Page[CustomerListItem])
def list_customers(
    db: Session = Depends(get_db),
    _: User = Depends(get_current_user),
    search: str | None = Query(None, description="Name, phone, customer code, or NID"),
    area_id: int | None = None,
    page: int = Query(1, ge=1),
    page_size: int = Query(25, ge=1, le=200),
) -> Page[CustomerListItem]:
    stmt = select(Customer).where(Customer.is_deleted.is_(False))
    if search:
        pattern = f"%{search.strip()}%"
        stmt = stmt.where(
            or_(
                Customer.full_name.ilike(pattern),
                Customer.phone.ilike(pattern),
                Customer.customer_code.ilike(pattern),
                Customer.nid.ilike(pattern),
            )
        )
    if area_id is not None:
        stmt = stmt.where(Customer.area_id == area_id)

    total = db.scalar(select(func.count()).select_from(stmt.subquery())) or 0
    rows = db.scalars(
        stmt.options(_AREA_LOAD)
        .order_by(Customer.full_name, Customer.id)
        .offset((page - 1) * page_size)
        .limit(page_size)
    ).unique().all()
    return Page.build([CustomerListItem.model_validate(r) for r in rows], total, page, page_size)


@router.get("/{customer_id}", response_model=CustomerDetail)
def get_customer(
    customer_id: int,
    db: Session = Depends(get_db),
    _: User = Depends(get_current_user),
) -> CustomerDetail:
    customer = db.scalar(
        select(Customer)
        .where(Customer.id == customer_id, Customer.is_deleted.is_(False))
        .options(_AREA_LOAD, selectinload(Customer.connections))
    )
    if customer is None:
        raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="Customer not found")

    out = CustomerDetail.model_validate(customer)
    # Soft-deleted connections stay on the row for audit but must not be selectable.
    out.connections = [
        ConnectionBrief.model_validate(c) for c in customer.connections if not c.is_deleted
    ]
    return out


@router.get("/{customer_id}/connections", response_model=list[ConnectionOut])
def list_customer_connections(
    customer_id: int,
    db: Session = Depends(get_db),
    _: User = Depends(get_current_user),
    active_only: bool = False,
) -> list[ConnectionOut]:
    stmt = select(Connection).where(
        Connection.customer_id == customer_id, Connection.is_deleted.is_(False)
    )
    if active_only:
        stmt = stmt.where(Connection.status == ConnectionStatus.ACTIVE)
    rows = db.scalars(stmt.order_by(Connection.id.desc())).unique().all()
    return [ConnectionOut.model_validate(r) for r in rows]
