"""MSZ 16226 (Gépi hajtású targonca üzemviteli dokumentuma) segédfüggvényei.

Fázis 0: csak a váz. A dokumentum-checklist katalógusa, a telephely-történet
összeállítása és a javítási napló szűrése a következő fázisokban kerül ide.
"""

from datetime import date

from templates_env import helyi_ido, helyi_datetime

import models
from sqlalchemy.orm import Session, joinedload


def gep_van_e_msz16226_szukseg(gep, db: Session) -> bool:
    """Igaz, ha a gép géptípusához a cégnél be van kapcsolva az MSZ 16226 üzemviteli
    dokumentum szükségessége (MachineTypeConfig.msz16226_szukseges)."""
    if not gep.geptipus:
        return False

    konfig = db.query(models.MachineTypeConfig).filter(
        models.MachineTypeConfig.company_id == gep.company_id,
        models.MachineTypeConfig.geptipus == gep.geptipus
    ).first()

    return bool(konfig and konfig.msz16226_szukseges)


def alkalmaz_muszaki_elotoltes(gep, muszaki: dict, mukodtetoenergia: str):
    """A géptörzsadatokban már meglévő, átfedő mezőket (teherbírás, emelési magasság,
    meghajtás) használja alapértékként ott, ahol a dokumentum saját (adatok_json-beli)
    mezője még üres - hogy ugyanazt az adatot ne kelljen kétszer bevinni. CSAK
    megjelenítéskor (form előtöltés + PDF) alkalmazzuk, nem íródik vissza automatikusan
    az adatok_json-ba, amíg a user ténylegesen el nem menti az űrlapot."""
    emelomu = dict(muszaki.get("emelomu", {}))
    if not emelomu.get("nevleges_teherbiras") and gep.teherbiras:
        emelomu["nevleges_teherbiras"] = gep.teherbiras
    if not emelomu.get("nevleges_emelesi_magassag") and gep.emelesi_magassag:
        emelomu["nevleges_emelesi_magassag"] = gep.emelesi_magassag

    muszaki = dict(muszaki)
    muszaki["emelomu"] = emelomu

    if not mukodtetoenergia and gep.meghajtas:
        mukodtetoenergia = gep.meghajtas

    return muszaki, mukodtetoenergia


# A 3.2 szakasz szabad szöveges mezői - ezeknek nincs otthonuk a Machine/Company modellben,
# ezért egy lapos dict-ben (adatok_json["szemelyek_szervezetek"]) tároljuk őket.
SZEMELYEK_SZERVEZETEK_MEZOK = [
    "szerzodes_kelte", "szerzodes_azonositoja",
    "berbeado_alairo_nev", "berbeado_alairo_szervezeti_egyseg",
    "berbeado_alairo_beosztas", "berbeado_alairo_elerhetoseg",
    "berbevevo_alairo_nev", "berbevevo_alairo_szervezeti_egyseg",
    "berbevevo_alairo_beosztas", "berbevevo_alairo_elerhetoseg",
    "uzemeltetesert_felelos_nev", "uzemeltetesert_felelos_beosztas",
    "karbantartasert_felelos_nev", "karbantartasert_felelos_beosztas",
    "emelogep_ugyintezo_nev", "emelogep_ugyintezo_beosztasi_hely", "emelogep_ugyintezo_elerhetoseg",
]


KEZELES_MODJA_OPCIOK = ["Vezetőüléses", "Vezetőállásos", "Gyalogkíséretű"]

# 3.3 - "A targonca fő jellemzői" tábla. Tisztán kézzel kitöltendő, változatos mezők -
# egy generikus (kód, cím, mértékegység) lista csoportonként, hogy a sablon egy Jinja
# ciklussal renderelhesse, ne kelljen ~50 input mezőt kézzel felsorolni.
MUSZAKI_CSOPORTOK = [
    {
        "kod": "emelomu",
        "cim": "Emelőmű",
        "mezok": [
            # Nincs kötött mértékegység-felirat: ezt a két mezőt a gép törzsadatai
            # (teherbírás/emelési magasság) automatikusan előtölthetik, azok pedig
            # szabad szöveges mezők, amikben a mértékegység gyakran már benne van
            # (pl. "1500 kg") - egy rákényszerített "t"/"mm" felirat duplikált vagy
            # akár hibás (kg helyett t) mértékegységet eredményezne.
            ("nevleges_teherbiras", "Névleges teherbírás", None),
            ("nevleges_emelesi_magassag", "Névleges emelési magasság", None),
            ("legnagyobb_emelesi_magassag", "Legnagyobb emelési magasság", "mm"),
            ("teherbiras_legnagyobb_emelesnel", "Teherbírás a legnagyobb emelési magasságnál", "t"),
            ("emelesi_sebesseg_terhelt", "Emelési sebesség - teherrel", "m/s"),
            ("emelesi_sebesseg_terheletlen", "Emelési sebesség - teher nélkül", "m/s"),
            ("oszlopdontes_elore", "Oszlopdöntés szöge - előre", "fok"),
            ("oszlopdontes_hatra", "Oszlopdöntés szöge - hátra", "fok"),
            ("szabad_emelesi_magassag", "Szabad emelési magasság", "mm"),
        ],
    },
    {
        "kod": "haladomu",
        "cim": "Haladómű",
        "mezok": [
            ("haladasi_szelesseg", "Haladási szélesség", "mm"),
            ("uzemi_hossz", "Üzemi hossz", "mm"),
            ("magassag_szallitasi_helyzetben", "Magasság (tehermegfogó szállítási helyzetében)", "mm"),
            ("szerkezeti_magassag_szallitaskor", "Legnagyobb szerkezeti magasság - szállításkor", "mm"),
            ("szerkezeti_magassag_max_emelesnel", "Legnagyobb szerkezeti magasság - legnagyobb emelésnél", "mm"),
            ("fordulasi_sugar_kulso", "Legkisebb fordulási sugár - külső", "mm"),
            ("fordulasi_sugar_belso", "Legkisebb fordulási sugár - belső", "mm"),
            ("tengelytav", "Tengelytáv", "mm"),
            ("nyomtav_melso", "Nyomtáv - mellső tengelynél", "mm"),
            ("nyomtav_hatso", "Nyomtáv - hátsó tengelynél", "mm"),
            ("ut_feletti_szabad_magassag", "Út feletti szabad magasság", "mm"),
            ("haladasi_sebesseg_terhelt", "Haladási sebesség - teherrel", "km/óra"),
            ("haladasi_sebesseg_terheletlen", "Haladási sebesség - teher nélkül", "km/óra"),
            ("legnagyobb_vonoero", "Legnagyobb vonóerő", "N"),
            ("kerekek_szama_elol", "Kerekek száma - elöl", "db"),
            ("kerekek_szama_hatul", "Kerekek száma - hátul", "db"),
            ("kerekek_merete_elol", "Kerekek mérete - elöl", "mm"),
            ("kerekek_merete_hatul", "Kerekek mérete - hátul", "mm"),
            ("levegonyomas_elol", "Fúvott kerekek levegőnyomása - elöl", "bar"),
            ("levegonyomas_hatul", "Fúvott kerekek levegőnyomása - hátul", "bar"),
            ("sajat_tomeg", "Saját tömeg üzemkész állapotban", "kg"),
            ("akkumulator_tomege", "Villamos hajtás esetén az akkumulátor tömege", "kg"),
            ("fekrendszer_uzemi", "Fékrendszer - üzemi", None),
            ("fekrendszer_rogzito", "Fékrendszer - rögzítő", None),
        ],
    },
    {
        "kod": "villamos_hajtas",
        "cim": "Villamos hajtás",
        "mezok": [
            ("akku_tipus", "Akkumulátor típusa", None),
            ("akku_gyarto", "Akkumulátor gyártója", None),
            ("akku_kapacitas", "Akkumulátor névleges kapacitása", "Ah"),
            ("akku_kapocsfeszultseg", "Akkumulátor kapocsfeszültsége", "V"),
            ("akku_cellak_szama", "Akkumulátor cellák száma", "db"),
            ("hajtomotor_teljesitmeny", "Hajtómotor teljesítménye", "kW"),
            ("hajtomotor_fordulatszam", "Hajtómotor fordulatszáma", "1/perc"),
            ("hajtomotor_gyarto", "Hajtómotor gyártója", None),
            ("aramatalakito_tipus", "Beépített áramátalakító típusa", None),
            ("aramatalakito_gyarto", "Beépített áramátalakító gyártója", None),
            ("aramatalakito_teljesitmeny", "Beépített áramátalakító teljesítménye", None),
            ("frekvenciavalto_tipus", "Beépített frekvenciaváltó típusa", None),
            ("frekvenciavalto_gyarto", "Beépített frekvenciaváltó gyártója", None),
            ("frekvenciavalto_teljesitmeny", "Beépített frekvenciaváltó teljesítménye", None),
        ],
    },
    {
        "kod": "belsoegesu_hajtas",
        "cim": "Belső égésű motoros hajtás",
        "mezok": [
            ("motor_tipusa", "Típusa", None),
            ("motor_gyartoja", "Gyártója", None),
            ("motor_szama", "Motor száma", None),
            ("motor_teljesitmenye", "Teljesítménye", "kW"),
            ("motor_lokettarfogata", "Összes lökettérfogata", "cm³"),
            ("kornyezetvedelmi_besorolas", "Környezetvédelmi besorolása", None),
            ("katalizator_tipusa", "Katalizátor típusa, ha van", None),
            ("uzemanyagtartaly_terfogata", "Üzemanyagtartály térfogata", "liter"),
            ("biztonsagi_szelep_azonosito", "Gázüzem esetén a biztonsági szelep azonosítója", None),
        ],
    },
]


# 3.4 - "Az üzembe helyezés dokumentumai" checklist katalógusa. `forras`:
#   "file"       - kizárólag egy File.file_type feltöltés elégíti ki
#   "vegyes"     - File.file_type VAGY egy meglévő Inspection.vizsgalat_tipusa is elégítheti
#   "deferred"   - nem valódi checklist-tétel, csak egy megjegyzés-sor (később/máshol kezelve)
MSZ16226_DOKUMENTUM_TIPUSOK = [
    {"kod": "megfeleloseg_tanusitvany", "cim": "Megfelelőségi tanúsítvány", "forras": "file",
     "file_types": ["Megfelelőségi tanúsítvány"]},
    {"kod": "megfeleloseg_nyilatkozat", "cim": "Megfelelőségi nyilatkozat", "forras": "file",
     "file_types": ["Megfelelőségi nyilatkozat"]},
    {"kod": "hasznalati_utasitas", "cim": "Használati utasítás (kezelési, karbantartási utasítás)", "forras": "file",
     "file_types": ["Használati utasítás"]},
    {"kod": "alkalmassagi_fovizsgalati_jkv", "cim": "Alkalmassági, vagy fővizsgálati jegyzőkönyv", "forras": "vegyes",
     "file_types": ["Fővizsgálat jkv", "Szerkezeti vizsgálat jkv", "Vizsgálati jegyzőkönyv",
                    "Időszakos biztonsági felülvizsgálat jkv", "Rendkívüli vizsgálat jkv"],
     "inspection_tipusok": ["Fővizsgálat", "Szerkezeti vizsgálat"]},
    {"kod": "zajvizsgalati_tanusitvany", "cim": "Tanúsítvány zajvizsgálatról, ha indokolt", "forras": "file",
     "file_types": ["Zajvizsgálati tanúsítvány"]},
    {"kod": "idoszakos_vizsgalatok_rendje", "cim": "Időszakos vizsgálatok rendje", "forras": "deferred",
     "megjegyzes": "Ez a szabvány 3.9. szakasza szerinti, az MSZ 9750 csoportszám-rendszerrel átfedő rész - külön kerül kidolgozásra."},
    {"kod": "mubizonylat_vonoelem", "cim": "Műbizonylat a hajlékony vonóelemről", "forras": "file",
     "file_types": ["Műbizonylat - hajlékony vonóelem"]},
    {"kod": "targonca_gepkonyve", "cim": "Targonca gépkönyve", "forras": "file",
     "file_types": ["Targonca gépkönyve"]},
    {"kod": "emelogepnaplo", "cim": "Emelőgépnapló", "forras": "file",
     "file_types": ["Gépnapló"]},
    {"kod": "hatosagi_engedelyek", "cim": "Hatósági engedélyek, ha szükségesek", "forras": "file",
     "file_types": ["Hatósági engedély"]},
    {"kod": "munkavedelmi_elozetes_jkv", "cim": "Munkavédelmi szempontú előzetes vizsgálat jegyzőkönyve", "forras": "file",
     "file_types": ["Munkavédelmi előzetes vizsgálat jkv"]},
    {"kod": "uzembehelyezesi_jkv", "cim": "Üzemeltető munkáltató üzembehelyezési jegyzőkönyve", "forras": "file",
     "file_types": ["Üzembehelyezési jkv / Ismételt üzembehelyezés"]},
]


def gep_msz16226_checklist_statusz(gep):
    """3.4 checklist - a MÁR BETÖLTÖTT gep.fajlok/gep.vizsgalatok relationokból (nincs új
    query) számolja ki soronként a megvan/hiányzik státuszt. A "vegyes" forrású tételeknél
    egy meglévő Inspection is kielégítheti a sort, nem kell hozzá duplikált feltöltés."""
    eredmeny = []
    for tetel in MSZ16226_DOKUMENTUM_TIPUSOK:
        if tetel["forras"] == "deferred":
            eredmeny.append({
                "kod": tetel["kod"], "cim": tetel["cim"], "forras": "deferred",
                "megvan": None, "forras_reszlet": tetel.get("megjegyzes"), "uj_feltoltes_file_type": None,
                "fajlok": [],
            })
            continue

        megvan = False
        forras_reszlet = None

        # A "fajlok" listát is visszaadjuk (nemcsak a leíró szöveget), hogy a PDF-
        # összeállítás (Fázis 7) ugyanezt a találati logikát tudja újrahasznosítani a
        # szkennelt dokumentumok beillesztéséhez, anélkül hogy duplikálná a keresést.
        egyezo_fajlok = [f for f in gep.fajlok if f.file_type in tetel["file_types"]]
        if egyezo_fajlok:
            megvan = True
            legujabb = max(egyezo_fajlok, key=lambda f: f.uploaded_at)
            forras_reszlet = f"Feltöltött fájl: {legujabb.file_type} ({helyi_ido(legujabb.uploaded_at, '%Y-%m-%d')})"

        if not megvan and tetel.get("inspection_tipusok"):
            egyezo_vizsgalatok = [v for v in gep.vizsgalatok if v.vizsgalat_tipusa in tetel["inspection_tipusok"]]
            if egyezo_vizsgalatok:
                megvan = True
                legujabb = max(egyezo_vizsgalatok, key=lambda v: v.datum)
                forras_reszlet = f"Meglévő vizsgálat: {legujabb.vizsgalat_tipusa} ({legujabb.datum})"

        eredmeny.append({
            "kod": tetel["kod"], "cim": tetel["cim"], "forras": tetel["forras"],
            "megvan": megvan, "forras_reszlet": forras_reszlet,
            "uj_feltoltes_file_type": tetel["file_types"][0],
            "fajlok": egyezo_fajlok,
        })
    return eredmeny


def egyeb_dokumentumtipusok_checklist(gep, egyeb_tipusok: list[str]):
    """A user által szabadon elnevezett, egyedi dokumentumtípusok (a szabvány 3.4-es
    táblázatának szabad soraihoz) - mindegyiket egy pontosan egyező File.file_type
    feltöltés elégíti ki."""
    eredmeny = []
    for nev in egyeb_tipusok:
        nev = (nev or "").strip()
        if not nev:
            continue
        egyezo_fajlok = [f for f in gep.fajlok if f.file_type == nev]
        megvan = bool(egyezo_fajlok)
        forras_reszlet = None
        if megvan:
            legujabb = max(egyezo_fajlok, key=lambda f: f.uploaded_at)
            forras_reszlet = f"Feltöltött fájl: {legujabb.file_type} ({helyi_ido(legujabb.uploaded_at, '%Y-%m-%d')})"
        eredmeny.append({
            "kod": f"egyeb__{nev}", "cim": nev, "forras": "file",
            "megvan": megvan, "forras_reszlet": forras_reszlet, "uj_feltoltes_file_type": nev,
            "fajlok": egyezo_fajlok,
        })
    return eredmeny


# 3.6/3.7 - ismétlődő-soros (személy/szervezet lehet több is) adatok. Generikus
# (kód, cím) lista csoportonként, ugyanúgy, mint a MUSZAKI_CSOPORTOK - a sablon egy
# indexelt name-mintával (megbizott__{csoport_kod}__{sor_index}__{mezo_kod}) rendereli.
MEGBIZOTT_SZAKASZOK = [
    {
        "kod": "dokumentum_vezeto",
        "cim": "Az üzemviteli dokumentum vezetésével megbízott személy/szervezet",
        "mezok": [
            ("nev", "Neve"),
            ("cime", "Címe"),
            ("elerhetoseg", "Elérhetősége (e-mail, telefon vagy fax)"),
            ("ugyintezo_neve", "Ügyintézőjének neve"),
            ("kezdete", "A megbízás kezdete"),
            ("vege", "A megbízás vége"),
        ],
    },
    {
        "kod": "karbantarto_megbizott",
        "cim": "A targonca karbantartásával megbízott személy/szervezet",
        "mezok": [
            ("nev", "Neve"),
            ("cime", "Címe"),
            ("elerhetoseg", "Elérhetősége (e-mail, telefon vagy fax)"),
            ("karbantarto_neve", "Karbantartójának neve"),
            ("kezdete", "A megbízás kezdete"),
            ("vege", "A megbízás vége"),
        ],
    },
]


def build_msz16226_javitasi_naplo(gep, db: Session):
    """3.8 - javítások, cserék. NEM önálló napló, hanem a MÁR MEGLÉVŐ
    build_gep_teljes_naplo() (routers/files.py) szűrt nézete: csak a LEZÁRT
    hibajegy-eseményeket tartja meg, kiegészítve a "Szervíz munkalap" típusú
    File-feltöltésekkel (a hozzájuk fűzött rövid megjegyzéssel)."""
    from routers.files import build_gep_teljes_naplo

    teljes_naplo = build_gep_teljes_naplo(gep, db)
    esemenyek = [
        e for e in teljes_naplo
        if e["tipus"] == "Hibajegy" and e["cim"] == "Hibajegy lezárva / Karbantartás"
    ]

    for f in gep.fajlok:
        if f.file_type == "Szervíz munkalap":
            esemenyek.append({
                "idopont": helyi_datetime(f.uploaded_at),
                "tipus": "Szervíz munkalap",
                "cim": "Szervíz munkalap feltöltve",
                "reszletek": f.megjegyzes or "-",
                "user": None,
                "dokumentum": f.file_path,
            })

    esemenyek.sort(key=lambda e: e["idopont"], reverse=True)
    return esemenyek


def build_msz16226_vizsgalat_nyilvantartas(gep, db: Session):
    """3.10 - Időszakos vizsgálatok nyilvántartása. Csak-olvasható nézet, teljes egészében
    a MEGLÉVŐ Inspection rekordokból - nincs hozzá külön adatbevitel, a jegyzőkönyv-szám
    kivételével, ami opcionálisan (kapcsolóval) felülírható egyedi értékkel, egyébként a
    belső adatbázis-azonosító jelenik meg "#<id>" formában."""
    vizsgalatok = db.query(models.Inspection).options(joinedload(models.Inspection.user)).filter(
        models.Inspection.machine_id == gep.id
    ).all()

    sorok = []
    for v in sorted(vizsgalatok, key=lambda x: x.datum or date.min, reverse=True):
        if v.jegyzokonyv_szam_egyedi and v.jegyzokonyv_szam:
            jkv_szam = v.jegyzokonyv_szam
        else:
            jkv_szam = f"#{v.id}"
        sorok.append({
            "inspection_id": v.id,
            "datum": v.datum,
            "tipus": v.vizsgalat_tipusa,
            "uzemora": v.uzemora_a_vizsgalatkor,
            "eredmeny": v.eredmeny,
            "vegzo_neve": v.user.username if v.user else "-",
            "jegyzokonyv_szam": jkv_szam,
            "jegyzokonyv_szam_egyedi": v.jegyzokonyv_szam_egyedi,
            "jegyzokonyv_szam_nyers": v.jegyzokonyv_szam or "",
            "dokumentum": v.jegyzokonyv_pdf_path,
        })
    return sorok


def build_msz16226_telephely_tortenet(gep, db: Session):
    """3.5 - üzemeltetésre vonatkozó adatok. NEM egy önálló telephely-történet napló,
    hanem a MÁR MEGLÉVŐ, generikus AuditLog site_id-változás bejegyzéseket egészíti ki
    (routers/machines.py gép-mentő route-ja ezt automatikusan írja minden telephely-
    váltáskor, field_name="site_id") a szabad szöveges mezőkkel, amiknek máshol nincs
    otthonuk (MszTelephelyMegjegyzes)."""
    valtozasok = db.query(models.AuditLog).filter(
        models.AuditLog.machine_id == gep.id,
        models.AuditLog.field_name == "site_id"
    ).order_by(models.AuditLog.timestamp.asc()).all()

    site_idk = set()
    if gep.site_id:
        site_idk.add(gep.site_id)
    for v in valtozasok:
        for ertek in (v.old_value, v.new_value):
            try:
                site_idk.add(int(ertek))
            except (TypeError, ValueError):
                pass

    site_nevek = {}
    if site_idk:
        for site in db.query(models.Site).filter(models.Site.id.in_(site_idk)).all():
            site_nevek[site.id] = site.nev

    def site_nev(ertek):
        if not ertek:
            return "-"
        try:
            return site_nevek.get(int(ertek), f"Ismeretlen telephely (#{ertek})")
        except (TypeError, ValueError):
            return "-"

    # A kezdő (első ismert) telephely: az első site_id-váltás előtti érték, vagy - ha
    # soha nem változott - a gép jelenlegi telephelye.
    kezdo_site_ertek = valtozasok[0].old_value if valtozasok else (str(gep.site_id) if gep.site_id else None)

    idovonal = [{
        "audit_log_id": None,
        "site_nev": site_nev(kezdo_site_ertek),
        "datum": gep.uzembe_helyezes_datum,
    }]
    for v in valtozasok:
        idovonal.append({
            "audit_log_id": v.id,
            "site_nev": site_nev(v.new_value),
            "datum": v.timestamp.date() if v.timestamp else None,
        })

    megjegyzesek = db.query(models.MszTelephelyMegjegyzes).filter(
        models.MszTelephelyMegjegyzes.machine_id == gep.id
    ).all()
    megjegyzes_by_audit = {m.audit_log_id: m for m in megjegyzesek}

    for sor in idovonal:
        m = megjegyzes_by_audit.get(sor["audit_log_id"])
        sor["mukodesi_terulet_megnevezese"] = m.mukodesi_terulet_megnevezese if m else ""
        sor["felelos_szervezet_nev"] = m.felelos_szervezet_nev if m else ""
        sor["felelos_szervezet_vezetoje"] = m.felelos_szervezet_vezetoje if m else ""
        sor["megjegyzes"] = m.megjegyzes if m else ""

    return idovonal


def derive_msz16226_tulajdonos_uzemeltetto(gep):
    """3.2 - a tulajdonos/üzemeltető adatai a gép meglévő bérlet-adataiból (berelt_eszkoz)
    származtatva, NEM kézzel bevitt adat. Ha a gép külső féltől bérelt, a bérbeadó a
    tulajdonos, mi vagyunk az üzemeltető - egyébként a saját cégünk mindkettő."""
    ceg = gep.ceg
    if gep.berelt_eszkoz:
        return {
            "tulajdonos_nev": gep.berbeado_neve or "-",
            "tulajdonos_elerhetoseg": gep.berbeado_elerhetoseg or "-",
            "azonos": False,
            "uzemeltetto_nev": ceg.nev if ceg else "-",
            "uzemeltetto_cim": ceg.cim if ceg else "-",
        }
    return {
        "tulajdonos_nev": ceg.nev if ceg else "-",
        "tulajdonos_elerhetoseg": ceg.cim if ceg else "-",
        "azonos": True,
        "uzemeltetto_nev": None,
        "uzemeltetto_cim": None,
    }
