from collections import defaultdict
from datetime import date, datetime, timedelta

from fastapi import APIRouter, Request, Depends, Form
from fastapi.responses import HTMLResponse, RedirectResponse, JSONResponse
from sqlalchemy.orm import Session

import models
from database import get_db
from security import (
    get_current_user, get_allowed_companies_list, apply_user_data_scope_filter,
    is_machine_allowed, is_company_allowed, require_modul,
    irasi_tiltas_oka, IRASI_TILTAS_UZENETEK
)
from msz_constants import compute_vizsgalati_esedekesseg
from msz_logic import get_vizsgalati_datum_kotelezo_mod
from templates_env import templates

router = APIRouter(dependencies=[Depends(require_modul("EMELOGEP"))])

# compute_vizsgalati_esedekesseg "tipus" mezője az IBF-nél "(EBSZ)" jelzéssel tér vissza - a
# SzakertoMegbizatas 3 boolean mezőjéhez és a TervezettVizsgalat.vizsgalat_tipusa (ami az
# Inspection.vizsgalat_tipusa-val egyező sima nevet használ) ide kötve egyértelműsítjük.
_TIPUS_ROVID = {
    "Szerkezeti vizsgálat": "szerkezeti",
    "Fővizsgálat": "fovizsgalat",
    "Időszakos biztonsági felülvizsgálat (EBSZ)": "ibf",
}

# KARBANTARTÁS (2026-10-03-i biztonsági audit, 4. fázis): a szakerto-tervez/-torles
# végpontok a vizsgalat_tipusa mezőt eddig validálatlanul fogadták - a kliens (JS) mindig a
# fenti _TIPUS_ROVID rövid kódjait küldi, de ez csak a felhasználói felület korlátozása volt,
# egy közvetlen POST kéréssel bármilyen szöveg bekerülhetett volna a TervezettVizsgalat
# táblába (adatintegritási probléma, nem jogosultsági rés - a végpont már eleve
# is_machine_allowed()-del védett).
ENGEDELYEZETT_VIZSGALAT_TIPUSOK = set(_TIPUS_ROVID.values())


def _szakerto_kapu(current_user) -> bool:
    return current_user.role == "Emelőgép szakértő"


def _parse_datum(ertek: str, alapertek: date) -> date:
    if not ertek:
        return alapertek
    try:
        return datetime.strptime(ertek, "%Y-%m-%d").date()
    except ValueError:
        return alapertek


@router.get("/szakerto-dashboard", response_class=HTMLResponse)
def szakerto_dashboard(
    request: Request,
    tol: str = "",
    ig: str = "",
    db: Session = Depends(get_db),
    current_user: models.User = Depends(get_current_user)
):
    """Emelőgép szakértőnek szóló áttekintő: ügyfelei (cégei) szerinti bontásban megmutatja a
    telephelyenkénti gépszámot/vizsgálati módokat, és a kiválasztott időszakra eső (vagy már
    lejárt) vizsgálati teendőket - a cégenként önként beállított "megbízatás" (l.
    [[project_szakerto_dashboard_2026_10_02]]) csak azt szűri, mely vizsgálat-típusok jelenjenek
    meg itt, a tényleges vizsgálat-rögzítést NEM korlátozza."""
    if not _szakerto_kapu(current_user):
        return RedirectResponse(url="/lista", status_code=303)

    mai_nap = date.today()
    tol_datum = _parse_datum(tol, mai_nap)
    ig_datum = _parse_datum(ig, mai_nap + timedelta(days=30))

    cegek = get_allowed_companies_list(current_user, db, "EMELOGEP")

    megbizatas_map = {
        m.company_id: m for m in db.query(models.SzakertoMegbizatas).filter(
            models.SzakertoMegbizatas.user_id == current_user.id
        ).all()
    }

    cegek_adatai = []
    for ceg in cegek:
        megbizatas = megbizatas_map.get(ceg.id)
        engedelyezett = {
            "szerkezeti": megbizatas.szerkezeti if megbizatas else True,
            "fovizsgalat": megbizatas.fovizsgalat if megbizatas else True,
            "ibf": megbizatas.ibf if megbizatas else True,
        }

        query = db.query(models.Machine).filter(
            models.Machine.company_id == ceg.id,
            models.Machine.statusz == "Aktív"
        )
        query = apply_user_data_scope_filter(query, current_user)
        gepek = query.all()

        configs_by_geptipus = {
            c.geptipus: c for c in
            db.query(models.MachineTypeConfig).filter(models.MachineTypeConfig.company_id == ceg.id).all()
        }
        datum_kotelezo_mod = get_vizsgalati_datum_kotelezo_mod(ceg.id, db)

        tervezett_map = {
            (t.machine_id, t.vizsgalat_tipusa): t for t in
            db.query(models.TervezettVizsgalat).join(models.Machine).filter(
                models.Machine.company_id == ceg.id
            ).all()
        }

        telephely_osszesito = defaultdict(lambda: {"gepszam": 0, "tipusok": defaultdict(int)})
        teendok_telephelyenkent = defaultdict(list)

        for gep in gepek:
            telephely_nev = gep.telephely.nev if gep.telephely else "Nincs telephely"
            telephely_osszesito[telephely_nev]["gepszam"] += 1

            config = configs_by_geptipus.get(gep.geptipus)
            for e in compute_vizsgalati_esedekesseg(gep, mai_nap, config, datum_kotelezo_mod):
                rovid = _TIPUS_ROVID.get(e["tipus"])
                if rovid and not engedelyezett.get(rovid, True):
                    continue

                tipus_teljes = e["tipus"].replace(" (EBSZ)", "")
                telephely_osszesito[telephely_nev]["tipusok"][tipus_teljes] += 1

                # Teendő = már lejárt/hiányzó (időszaktól függetlenül mindig releváns), vagy a
                # kiválasztott időszakba eső esedékesség.
                teendo_e = e["allapot"] in ("lejart", "hianyzik")
                if not teendo_e and e["esedekes"]:
                    esedekes_datum = datetime.strptime(e["esedekes"], "%Y-%m-%d").date()
                    teendo_e = tol_datum <= esedekes_datum <= ig_datum

                if not teendo_e:
                    continue

                tervezett = tervezett_map.get((gep.id, tipus_teljes))
                teendok_telephelyenkent[telephely_nev].append({
                    "gep": gep,
                    "tipus": tipus_teljes,
                    "allapot": e["allapot"],
                    "esedekes": e["esedekes"],
                    "tervezett": tervezett,
                })

        for lista in teendok_telephelyenkent.values():
            lista.sort(key=lambda t: t["esedekes"] or "0000-00-00")

        cegek_adatai.append({
            "ceg": ceg,
            "megbizatas": engedelyezett,
            "gepszam": len(gepek),
            "telephely_osszesito": dict(telephely_osszesito),
            "teendok_telephelyenkent": dict(teendok_telephelyenkent),
            "teendo_szama": sum(len(v) for v in teendok_telephelyenkent.values()),
        })

    return templates.TemplateResponse(
        request=request,
        name="szakerto_dashboard.html",
        context={
            "user": current_user,
            "cegek_adatai": cegek_adatai,
            "tol": tol_datum.strftime("%Y-%m-%d"),
            "ig": ig_datum.strftime("%Y-%m-%d"),
        }
    )


@router.post("/szakerto-megbizatas")
def szakerto_megbizatas_mentese(
    company_id: int = Form(...),
    szerkezeti: bool = Form(False),
    fovizsgalat: bool = Form(False),
    ibf: bool = Form(False),
    db: Session = Depends(get_db),
    current_user: models.User = Depends(get_current_user)
):
    if not _szakerto_kapu(current_user):
        return JSONResponse(status_code=403, content={"message": "Csak Emelőgép szakértő állíthatja be a megbízatását!"})

    if not is_company_allowed(current_user, company_id):
        return JSONResponse(status_code=403, content={"message": "Nincs jogosultságod ehhez a céghez!"})

    # J-09 (v65): inaktív cégbe / csak_olvasas fiókkal nem írunk
    tiltas = irasi_tiltas_oka(current_user, company_id, db)
    if tiltas:
        return JSONResponse(status_code=403, content={"message": IRASI_TILTAS_UZENETEK[tiltas]})

    megbizatas = db.query(models.SzakertoMegbizatas).filter(
        models.SzakertoMegbizatas.user_id == current_user.id,
        models.SzakertoMegbizatas.company_id == company_id
    ).first()
    if not megbizatas:
        megbizatas = models.SzakertoMegbizatas(user_id=current_user.id, company_id=company_id)
        db.add(megbizatas)

    megbizatas.szerkezeti = szerkezeti
    megbizatas.fovizsgalat = fovizsgalat
    megbizatas.ibf = ibf
    db.commit()

    return JSONResponse(status_code=200, content={"message": "Megbízatás elmentve!"})


@router.post("/szakerto-tervez")
def szakerto_tervez_mentese(
    machine_id: int = Form(...),
    vizsgalat_tipusa: str = Form(...),
    tervezett_datum: str = Form(...),
    megjegyzes: str = Form(""),
    db: Session = Depends(get_db),
    current_user: models.User = Depends(get_current_user)
):
    if not _szakerto_kapu(current_user):
        return JSONResponse(status_code=403, content={"message": "Csak Emelőgép szakértő ütemezhet!"})

    if vizsgalat_tipusa not in ENGEDELYEZETT_VIZSGALAT_TIPUSOK:
        return JSONResponse(status_code=400, content={"message": "Érvénytelen vizsgálat-típus!"})

    gep = db.query(models.Machine).filter(models.Machine.id == machine_id).first()
    if not gep or not is_machine_allowed(gep, current_user):
        return JSONResponse(status_code=404, content={"message": "Hiba történt vagy nincs jogosultság!"})

    # J-09 (v65): a gép cégének állapota számít (a szakértő több cégben is dolgozhat)
    tiltas = irasi_tiltas_oka(current_user, gep.company_id, db)
    if tiltas:
        return JSONResponse(status_code=403, content={"message": IRASI_TILTAS_UZENETEK[tiltas]})

    try:
        tervezett_datum_obj = datetime.strptime(tervezett_datum, "%Y-%m-%d").date()
    except ValueError:
        return JSONResponse(status_code=400, content={"message": "Érvénytelen dátum formátum!"})

    tervezett = db.query(models.TervezettVizsgalat).filter(
        models.TervezettVizsgalat.machine_id == machine_id,
        models.TervezettVizsgalat.vizsgalat_tipusa == vizsgalat_tipusa
    ).first()
    if not tervezett:
        tervezett = models.TervezettVizsgalat(machine_id=machine_id, vizsgalat_tipusa=vizsgalat_tipusa)
        db.add(tervezett)

    tervezett.user_id = current_user.id
    tervezett.tervezett_datum = tervezett_datum_obj
    tervezett.megjegyzes = megjegyzes.strip() or None
    db.commit()

    return JSONResponse(status_code=200, content={"message": "Ütemezve!", "tervezett_datum": tervezett_datum})


@router.post("/szakerto-tervez-torles")
def szakerto_tervez_torlese(
    machine_id: int = Form(...),
    vizsgalat_tipusa: str = Form(...),
    db: Session = Depends(get_db),
    current_user: models.User = Depends(get_current_user)
):
    if not _szakerto_kapu(current_user):
        return JSONResponse(status_code=403, content={"message": "Csak Emelőgép szakértő ütemezhet!"})

    if vizsgalat_tipusa not in ENGEDELYEZETT_VIZSGALAT_TIPUSOK:
        return JSONResponse(status_code=400, content={"message": "Érvénytelen vizsgálat-típus!"})

    gep = db.query(models.Machine).filter(models.Machine.id == machine_id).first()
    if not gep or not is_machine_allowed(gep, current_user):
        return JSONResponse(status_code=404, content={"message": "Hiba történt vagy nincs jogosultság!"})

    # J-09 (v65): a gép cégének állapota számít (a szakértő több cégben is dolgozhat)
    tiltas = irasi_tiltas_oka(current_user, gep.company_id, db)
    if tiltas:
        return JSONResponse(status_code=403, content={"message": IRASI_TILTAS_UZENETEK[tiltas]})

    db.query(models.TervezettVizsgalat).filter(
        models.TervezettVizsgalat.machine_id == machine_id,
        models.TervezettVizsgalat.vizsgalat_tipusa == vizsgalat_tipusa
    ).delete(synchronize_session=False)
    db.commit()

    return JSONResponse(status_code=200, content={"message": "Ütemezés törölve!"})
