"""Verwaltung konfigurierbarer Kategorie-Optionen."""

from fastapi import APIRouter, Depends, Form, Request
from fastapi.responses import HTMLResponse, RedirectResponse
from fastapi.templating import Jinja2Templates
from sqlalchemy.orm import Session

from dependencies import get_current_user, get_db
from models.kategorie_option import KategorieOption
from services.kategorie_service import alle_gruppen, get_optionen, GRUPPEN_LABELS

router = APIRouter(prefix="/einstellungen/kategorien")
templates = Jinja2Templates(directory="templates")


@router.get("", response_class=HTMLResponse)
async def uebersicht(request: Request, user=Depends(get_current_user), db: Session = Depends(get_db)):
    gruppen = alle_gruppen(db)
    gruppen_info = []
    for g in gruppen:
        opts = get_optionen(db, g, nur_aktive=False)
        gruppen_info.append({
            "key": g,
            "label": GRUPPEN_LABELS.get(g, g),
            "anzahl": len(opts),
            "aktiv": sum(1 for o in opts if o.aktiv),
        })
    return templates.TemplateResponse("pages/einstellungen/kategorien.html", {
        "request": request,
        "user": user,
        "active_page": "einstellungen",
        "gruppen": gruppen_info,
    })


@router.get("/{gruppe}", response_class=HTMLResponse)
async def gruppe_detail(gruppe: str, request: Request, user=Depends(get_current_user), db: Session = Depends(get_db)):
    optionen = get_optionen(db, gruppe, nur_aktive=False)
    return templates.TemplateResponse("pages/einstellungen/kategorie_detail.html", {
        "request": request,
        "user": user,
        "active_page": "einstellungen",
        "gruppe": gruppe,
        "gruppe_label": GRUPPEN_LABELS.get(gruppe, gruppe),
        "optionen": optionen,
    })


@router.post("/{gruppe}/neu")
async def option_erstellen(
    gruppe: str,
    wert: str = Form(...),
    label: str = Form(...),
    icon: str = Form(""),
    farbe: str = Form(""),
    user=Depends(get_current_user),
    db: Session = Depends(get_db),
):
    wert = wert.strip()
    label = label.strip()
    if not wert or not label:
        return RedirectResponse(url=f"/einstellungen/kategorien/{gruppe}", status_code=303)

    existing = db.query(KategorieOption).filter(
        KategorieOption.gruppe == gruppe,
        KategorieOption.wert == wert,
    ).first()
    if not existing:
        max_pos = db.query(KategorieOption).filter(KategorieOption.gruppe == gruppe).count()
        db.add(KategorieOption(
            gruppe=gruppe,
            wert=wert,
            label=label,
            icon=icon.strip() or None,
            farbe=farbe.strip() or None,
            position=max_pos,
        ))
        db.commit()
        _refresh(db)
    return RedirectResponse(url=f"/einstellungen/kategorien/{gruppe}", status_code=303)


@router.post("/{gruppe}/{option_id}/bearbeiten")
async def option_bearbeiten(
    gruppe: str,
    option_id: int,
    label: str = Form(...),
    icon: str = Form(""),
    farbe: str = Form(""),
    user=Depends(get_current_user),
    db: Session = Depends(get_db),
):
    opt = db.query(KategorieOption).filter(KategorieOption.id == option_id).first()
    if opt:
        opt.label = label.strip()
        opt.icon = icon.strip() or None
        opt.farbe = farbe.strip() or None
        db.commit()
        _refresh(db)
    return RedirectResponse(url=f"/einstellungen/kategorien/{gruppe}", status_code=303)


@router.post("/{gruppe}/{option_id}/toggle")
async def option_toggle(
    gruppe: str,
    option_id: int,
    user=Depends(get_current_user),
    db: Session = Depends(get_db),
):
    opt = db.query(KategorieOption).filter(KategorieOption.id == option_id).first()
    if opt:
        opt.aktiv = not opt.aktiv
        db.commit()
        _refresh(db)
    return RedirectResponse(url=f"/einstellungen/kategorien/{gruppe}", status_code=303)


@router.post("/{gruppe}/{option_id}/loeschen")
async def option_loeschen(
    gruppe: str,
    option_id: int,
    user=Depends(get_current_user),
    db: Session = Depends(get_db),
):
    opt = db.query(KategorieOption).filter(KategorieOption.id == option_id).first()
    if opt:
        db.delete(opt)
        db.commit()
        _refresh(db)
    return RedirectResponse(url=f"/einstellungen/kategorien/{gruppe}", status_code=303)


@router.post("/{gruppe}/{option_id}/hoch")
async def option_hoch(
    gruppe: str,
    option_id: int,
    user=Depends(get_current_user),
    db: Session = Depends(get_db),
):
    optionen = db.query(KategorieOption).filter(
        KategorieOption.gruppe == gruppe
    ).order_by(KategorieOption.position, KategorieOption.label).all()
    for i, o in enumerate(optionen):
        o.position = i
    db.flush()

    opt = db.query(KategorieOption).filter(KategorieOption.id == option_id).first()
    if opt and opt.position > 0:
        other = db.query(KategorieOption).filter(
            KategorieOption.gruppe == gruppe,
            KategorieOption.position == opt.position - 1,
        ).first()
        if other:
            opt.position, other.position = other.position, opt.position
    db.commit()
    _refresh(db)
    return RedirectResponse(url=f"/einstellungen/kategorien/{gruppe}", status_code=303)


@router.post("/{gruppe}/{option_id}/runter")
async def option_runter(
    gruppe: str,
    option_id: int,
    user=Depends(get_current_user),
    db: Session = Depends(get_db),
):
    optionen = db.query(KategorieOption).filter(
        KategorieOption.gruppe == gruppe
    ).order_by(KategorieOption.position, KategorieOption.label).all()
    for i, o in enumerate(optionen):
        o.position = i
    db.flush()

    opt = db.query(KategorieOption).filter(KategorieOption.id == option_id).first()
    max_pos = len(optionen) - 1
    if opt and opt.position < max_pos:
        other = db.query(KategorieOption).filter(
            KategorieOption.gruppe == gruppe,
            KategorieOption.position == opt.position + 1,
        ).first()
        if other:
            opt.position, other.position = other.position, opt.position
    db.commit()
    _refresh(db)
    return RedirectResponse(url=f"/einstellungen/kategorien/{gruppe}", status_code=303)


def _refresh(db):
    """Model-Dicts nach Aenderung aktualisieren."""
    from main import refresh_model_dicts
    refresh_model_dicts(db)
