"""Information fields management API."""
from __future__ import annotations

from typing import List, Optional, Literal
from uuid import UUID

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

from normbase.db.connection import get_db
from normbase.models.norm import Field as InfoField
from normbase.models.schemas import FieldCreate, FieldResponse, FieldUpdate


router = APIRouter(tags=["fields"])


@router.get("/fields", response_model=List[FieldResponse])
async def list_fields(
    status: Optional[Literal["active", "inactive", "archived"]] = Query(
        default=None,
        description="Filter by field status",
    ),
    db: AsyncSession = Depends(get_db),
):
    stmt = select(InfoField).order_by(InfoField.created_at.desc())
    if status is not None:
        stmt = stmt.where(InfoField.status == status)
    rows = (await db.execute(stmt)).scalars().all()
    return [FieldResponse.model_validate(row) for row in rows]


@router.post("/fields", response_model=FieldResponse, status_code=status.HTTP_201_CREATED)
async def create_field(payload: FieldCreate, db: AsyncSession = Depends(get_db)):
    name = (payload.name or "").strip()
    if not name:
        raise HTTPException(status_code=400, detail="Field name cannot be empty.")

    existing_stmt = select(InfoField).where(InfoField.name == name)
    existing = (await db.execute(existing_stmt)).scalar_one_or_none()
    if existing:
        raise HTTPException(status_code=409, detail=f"Field '{name}' already exists.")

    item = InfoField(
        name=name,
        description=(payload.description or None),
        org_id=payload.org_id,
        status=payload.status,
    )
    db.add(item)
    await db.commit()
    await db.refresh(item)
    return FieldResponse.model_validate(item)


@router.patch("/fields/{field_id}", response_model=FieldResponse)
async def update_field(field_id: UUID, payload: FieldUpdate, db: AsyncSession = Depends(get_db)):
    item = (
        await db.execute(select(InfoField).where(InfoField.id == field_id))
    ).scalar_one_or_none()
    if item is None:
        raise HTTPException(status_code=404, detail="Field not found.")

    if payload.name is not None:
        name = payload.name.strip()
        if not name:
            raise HTTPException(status_code=400, detail="Field name cannot be empty.")
        existing_stmt = select(InfoField).where(
            InfoField.name == name,
            InfoField.id != field_id,
        )
        existing = (await db.execute(existing_stmt)).scalar_one_or_none()
        if existing:
            raise HTTPException(status_code=409, detail=f"Field '{name}' already exists.")
        item.name = name

    if payload.description is not None:
        item.description = payload.description
    if payload.org_id is not None:
        item.org_id = payload.org_id
    if payload.status is not None:
        item.status = payload.status

    await db.commit()
    await db.refresh(item)
    return FieldResponse.model_validate(item)


@router.delete("/fields/{field_id}", response_model=FieldResponse)
async def soft_delete_field(field_id: UUID, db: AsyncSession = Depends(get_db)):
    item = (
        await db.execute(select(InfoField).where(InfoField.id == field_id))
    ).scalar_one_or_none()
    if item is None:
        raise HTTPException(status_code=404, detail="Field not found.")

    item.status = "archived"
    await db.commit()
    await db.refresh(item)
    return FieldResponse.model_validate(item)
