"""TEMPLATE – Mustervorlage für einen neuen Router (Modul mit Workflow-Status).

Abgeleitet vom aktuellsten sauberen Muster im Projekt: app/routers/hours_payouts.py.

Kern-Regeln (aus CLAUDE.md + gelernte Fallstricke):
- Company-Isolation: JEDE Query filtert auf company_id == current_user.company_id
  (zusätzlich zur DB-seitigen RLS – Python-Check ist die zweite Verteidigungslinie)
- **RLS-Bypass + mid-request commit Falle**: Response-Objekt (_build_out) IMMER
  VOR db.commit() bauen. db.refresh() nur nach db.flush() (noch in Transaktion).
  Nach commit() ist app.bypass_rls/app.company_id verfallen -> Post-Commit-Reads
  sehen ggf. keine Zeilen mehr.
- AuditLog bei JEDER schreibenden Aktion (create/approve/reject/cancel/delete)
- HTTPException mit sprechendem detail, kein Hard-Delete
- require_role() aus core.dependencies für Rollenprüfung

Anleitung:
1. Nach app/routers/<name>.py kopieren, XxxThing/xxx_things ersetzen
2. In app/main.py registrieren: app.include_router(xxx_things.router, prefix="/api/v1")
3. Model + Schema aus model_template.py / schema_template.py zuerst anlegen
4. Migration schreiben (Alembic) inkl. RLS-Policy + conftest.py nachziehen
5. Tests in backend/tests/test_xxx_things.py (siehe test_hours_payouts.py als Muster)
"""
from datetime import datetime
from uuid import UUID

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

from app.core.database import get_db
from app.core.dependencies import get_client_ip, require_role
from app.models.audit_log import AuditLog
from app.models.user import User, UserRole
from app.models.xxx_thing import XxxThing, XxxThingStatus  # TODO: Model anlegen
from app.schemas.xxx_thing import (  # TODO: Schemas anlegen
    XxxThingCreate,
    XxxThingListResponse,
    XxxThingOut,
    XxxThingReject,
)

router = APIRouter(tags=["Xxx-Thing"])

_hr_roles = (UserRole.HR, UserRole.COMPANY_ADMIN, UserRole.SUPER_ADMIN)
_all_roles = (UserRole.EMPLOYEE, UserRole.MANAGER, UserRole.HR, UserRole.COMPANY_ADMIN, UserRole.SUPER_ADMIN)


async def _build_out(item: XxxThing, db: AsyncSession) -> XxxThingOut:
    """Response-Objekt VOR commit() bauen – siehe RLS-Bypass-Falle oben."""
    out = XxxThingOut.model_validate(item)
    user = await db.get(User, item.user_id)
    out.user_name = f"{user.first_name} {user.last_name}" if user else str(item.user_id)
    return out


# ── GET /xxx-things ────────────────────────────────────────────────────────

@router.get("/xxx-things", response_model=XxxThingListResponse)
async def list_items(
    status: str | None = Query(None),
    current_user: User = require_role(*_all_roles),
    db: AsyncSession = Depends(get_db),
):
    """Liste der eigenen Firma. EMPLOYEE/MANAGER sehen nur eigene Einträge."""
    filters = [XxxThing.company_id == current_user.company_id]
    if current_user.role not in _hr_roles:
        filters.append(XxxThing.user_id == current_user.id)
    if status is not None:
        filters.append(XxxThing.status == status)

    total_count = await db.scalar(select(func.count()).select_from(XxxThing).where(*filters))
    rows = list(await db.scalars(
        select(XxxThing).where(*filters).order_by(XxxThing.created_at.desc())
    ))
    result = [await _build_out(row, db) for row in rows]
    return XxxThingListResponse(items=result, total_count=total_count or 0)


# ── POST /xxx-things ───────────────────────────────────────────────────────

@router.post("/xxx-things", response_model=XxxThingOut, status_code=201)
async def create_item(
    request: Request,
    data: XxxThingCreate,
    current_user: User = require_role(*_all_roles),
    db: AsyncSession = Depends(get_db),
):
    item = XxxThing(
        company_id=current_user.company_id,
        user_id=data.user_id,
        note=data.note,
        status=XxxThingStatus.REQUESTED.value,
        created_by=current_user.id,
    )
    db.add(item)
    await db.flush()
    await db.refresh(item)  # server_default created_at – noch in-Transaktion

    db.add(AuditLog(
        company_id=current_user.company_id, user_id=current_user.id,
        action="xxx_thing_created", entity_type="xxx_thing", entity_id=item.id,
        new_value={"note": data.note},
        ip=get_client_ip(request),
    ))
    out = await _build_out(item, db)
    await db.commit()
    return out


# ── POST /xxx-things/{id}/approve ──────────────────────────────────────────

@router.post("/xxx-things/{item_id}/approve", response_model=XxxThingOut)
async def approve_item(
    item_id: UUID,
    request: Request,
    current_user: User = require_role(*_hr_roles),
    db: AsyncSession = Depends(get_db),
):
    item = await db.get(XxxThing, item_id)
    if item is None or item.company_id != current_user.company_id:
        raise HTTPException(404, "Eintrag nicht gefunden")
    if item.status != XxxThingStatus.REQUESTED.value:
        raise HTTPException(409, "Nur offene Anträge können genehmigt werden.")

    item.status = XxxThingStatus.APPROVED.value
    item.decided_by = current_user.id
    item.decided_at = datetime.utcnow()

    db.add(AuditLog(
        company_id=current_user.company_id, user_id=current_user.id,
        action="xxx_thing_approved", entity_type="xxx_thing", entity_id=item.id,
        ip=get_client_ip(request),
    ))
    out = await _build_out(item, db)
    await db.commit()
    return out


# ── POST /xxx-things/{id}/reject ───────────────────────────────────────────

@router.post("/xxx-things/{item_id}/reject", response_model=XxxThingOut)
async def reject_item(
    item_id: UUID,
    request: Request,
    data: XxxThingReject,
    current_user: User = require_role(*_hr_roles),
    db: AsyncSession = Depends(get_db),
):
    item = await db.get(XxxThing, item_id)
    if item is None or item.company_id != current_user.company_id:
        raise HTTPException(404, "Eintrag nicht gefunden")
    if item.status != XxxThingStatus.REQUESTED.value:
        raise HTTPException(409, "Nur offene Anträge können abgelehnt werden.")

    item.status = XxxThingStatus.REJECTED.value
    item.rejection_reason = data.rejection_reason
    item.decided_by = current_user.id
    item.decided_at = datetime.utcnow()

    db.add(AuditLog(
        company_id=current_user.company_id, user_id=current_user.id,
        action="xxx_thing_rejected", entity_type="xxx_thing", entity_id=item.id,
        new_value={"rejection_reason": data.rejection_reason},
        ip=get_client_ip(request),
    ))
    out = await _build_out(item, db)
    await db.commit()
    return out
