﻿import math
import os
import shutil
from datetime import date, datetime

from fastapi import APIRouter, Request, Depends, Form, File, UploadFile, HTTPException, status
from fastapi.encoders import jsonable_encoder
from fastapi.responses import HTMLResponse, RedirectResponse, JSONResponse, FileResponse
from sqlalchemy import or_, case, cast, func, String
from sqlalchemy.orm import Session

import models
from database import get_db
from security import (
    get_current_user, get_working_company_id, is_company_active,
    irasi_tiltas_oka, IRASI_TILTAS_UZENETEK,
    is_safe_extension, sanitize_filename, get_oe_alapterulet_szamitas, require_modul,
    safe_json_for_script, get_allowed_companies_list, van_e_tobb_modulja,
    is_rendszeradminisztrator, is_company_allowed, tartalom_illeszkedik_e_kiterjesztesre,
)
from fastapi.responses import StreamingResponse
import io
from image_utils import tomorit_kepet
from pdf_utils import TuzvedelmiNaploPDF
from tuzvedelem_constants import (
    SZAKVIZSGA_KATEGORIAK, AKTIV_SZAKVIZSGA_KATEGORIAK, GYARTASI_SZABVANYOK, OLTOANYAG_TIPUSOK,
    szukseges_oe_alapterulet_alapjan, FOLDSZINT_VALTOZATOK, ALAP_FOLDSZINT_VALTOZAT, szint_lista,
)
from tuzvedelem_logic import compute_tuzoltokeszulek_esedekesseg
from hibakodok import hiba_uzenet
from templates_env import templates, helyi_ido

router = APIRouter(dependencies=[Depends(require_modul("TUZVEDELEM"))])

LEZART_STATUSZOK = ["Selejtezve"]

# J-13 (v71): a készülék-szerkesztő és az ellenőrzés-rögzítő űrlap select-jeinek értékei (templates/tuzvedelem_keszulek_adatlap.html).
KESZULEK_STATUSZOK = ("Aktív", "Elszállítva karbantartásra", "Raktáron", "Selejtezve")
ELLENORZES_TIPUSOK = ("UZEMELTETOI_ELLENORZES", "ALAP", "KOZEP", "TELJES_KORU")


def _id_vagy_hiba(nyers, mezo_nev: str):
    """(id | None, hiba): az üres érték None (nincs hivatkozás); a számjegyes szöveg egész szám; bármi más hibaüzenet.
    A nem szám érték korábban 500-at okozott (int() kivétel)."""
    if nyers is None or not str(nyers).strip():
        return None, None
    nyers = str(nyers).strip()
    if not nyers.isdigit():
        return None, f"Érvénytelen {mezo_nev} azonosító!"
    return int(nyers), None


def keszulek_hivatkozasok_ellenorzese(db, working_company_id: int, hely_id_nyers, karbantarto_ceg_id_nyers):
    """J-13 (v71): a készülék-szerkesztés hivatkozott azonosítói. (hely_id, karbantarto_ceg_id, hiba) - hibánál az első két érték None.
    A készenléti hely és a karbantartó cég a MUNKAKÖRNYEZET cégéé kell legyen (eddig bármely cég azonosítója elfogadott volt:
    a készülék idegen helyre kerülhetett, az idegen karbantartó neve megjelent)."""
    hely_id, hiba = _id_vagy_hiba(hely_id_nyers, "készenléti hely")
    if hiba:
        return None, None, hiba
    if hely_id is not None and not db.query(models.KeszenletiHely.id).filter(
            models.KeszenletiHely.id == hely_id, models.KeszenletiHely.company_id == working_company_id).first():
        return None, None, "A kiválasztott készenléti hely nem ehhez a céghez tartozik!"
    kc_id, hiba = karbantarto_ceg_ellenorzese(db, working_company_id, karbantarto_ceg_id_nyers)
    if hiba:
        return None, None, hiba
    return hely_id, kc_id, None


def karbantarto_ceg_ellenorzese(db, working_company_id: int, karbantarto_ceg_id_nyers):
    """(karbantarto_ceg_id | None, hiba): a karbantartó cég a munkakörnyezet cégének karbantartója kell legyen."""
    kc_id, hiba = _id_vagy_hiba(karbantarto_ceg_id_nyers, "karbantartó cég")
    if hiba:
        return None, hiba
    if kc_id is not None and not db.query(models.KarbantartoCeg.id).filter(
            models.KarbantartoCeg.id == kc_id, models.KarbantartoCeg.company_id == working_company_id).first():
        return None, "A kiválasztott karbantartó cég nem ehhez a céghez tartozik!"
    return kc_id, None

KESZULEK_RENDEZHETO_OSZLOPOK = {
    "gyarto": models.TuzoltoKeszulek.gyarto,
    "tipus_nev": models.TuzoltoKeszulek.tipus_nev,
    "gyari_szam": models.TuzoltoKeszulek.gyari_szam,
    "gyartasi_szabvany": models.TuzoltoKeszulek.gyartasi_szabvany,
    "oltoanyag_tipus": models.TuzoltoKeszulek.oltoanyag_tipus,
    "oe_ertek": models.TuzoltoKeszulek.oe_ertek,
    "toltettomeg_kg": models.TuzoltoKeszulek.toltettomeg_kg,
    "gyartas_datum": models.TuzoltoKeszulek.gyartas_datum,
    "statusz": models.TuzoltoKeszulek.statusz,
}


def keres_duplikatum_keszuleket(db: Session, company_id: int, gyari_szam: str, kizart_keszulek_id: int = None):
    """Megkeresi, hogy a cégnél van-e már másik tűzoltó készülék ugyanazzal a gyári számmal -
    kis/nagybetűtől és szóközöktől függetlenül. Üres gyári számra nem keres."""
    gyari_szam = str(gyari_szam).strip() if gyari_szam is not None else ""
    if not gyari_szam:
        return None

    query = db.query(models.TuzoltoKeszulek).filter(
        models.TuzoltoKeszulek.company_id == company_id,
        models.TuzoltoKeszulek.gyari_szam.ilike(gyari_szam)
    )
    if kizart_keszulek_id:
        query = query.filter(models.TuzoltoKeszulek.id != kizart_keszulek_id)

    return query.first()


def _keszulek_kereses_szures(sz: str):
    term = f"%{sz}%"
    return or_(
        models.TuzoltoKeszulek.gyarto.ilike(term),
        models.TuzoltoKeszulek.tipus_nev.ilike(term),
        models.TuzoltoKeszulek.gyari_szam.ilike(term),
        models.TuzoltoKeszulek.gyartasi_szabvany.ilike(term),
        models.TuzoltoKeszulek.oltoanyag_tipus.ilike(term),
        models.TuzoltoKeszulek.oe_ertek.ilike(term),
        models.TuzoltoKeszulek.statusz.ilike(term),
        models.TuzoltoKeszulek.jelenlegi_hely.has(models.KeszenletiHely.hely_leiras.ilike(term)),
        cast(models.TuzoltoKeszulek.gyartas_datum, String).ilike(term),
    )


def _parse_date(ertek: str):
    if not ertek:
        return None
    try:
        return datetime.strptime(ertek, "%Y-%m-%d").date()
    except ValueError:
        return None


# J-11 (v74): a Tűzvédelem szerkesztő műveleteit (telephely/épület/hely/készülék felvétel és szerkesztés, státusz, szervizbe
# küldés, ellenőrzés-rögzítés, fájl feltöltés) csak ezek a szerepkörök végezhetik. Korábban nem volt szerepkör-kapu: bármely
# modulos felhasználó (szakértő, vizsgáló, Karbantartó is) módosíthatott. A törlések, a jóváhagyás, a szakvizsga, a karbantartó
# cégek és a napló lezárása továbbra is Admin-only (a saját, szigorúbb kapujukkal).
TUZVEDELEM_SZERKESZTO_SZEREPKOROK = ("Admin", "Felhasználó", "Emelőgép ügyintéző")


def _lehet_szerkeszteni(current_user, working_company_id, db) -> bool:
    if current_user.role not in TUZVEDELEM_SZERKESZTO_SZEREPKOROK:
        return False
    if not is_company_active(working_company_id, db):
        return False
    if current_user.csak_olvasas:
        return False
    return True


def _kolcsonzott_keszulek_idk_a_ceghez(working_company_id: int, db: Session) -> list:
    """Azok a (más cég - karbantartó - tulajdonában lévő) készülék-id-k, amik jelenleg
    aktív kölcsönzéssel a megadott (üzemeltető) cég valamelyik készenléti helyén állnak."""
    helyek_idk = [r[0] for r in db.query(models.KeszenletiHely.id).filter(
        models.KeszenletiHely.company_id == working_company_id
    ).all()]
    if not helyek_idk:
        return []
    return [
        r[0] for r in db.query(models.KeszulekKolcsonzes.keszulek_id).filter(
            models.KeszulekKolcsonzes.keszenleti_hely_id.in_(helyek_idk),
            models.KeszulekKolcsonzes.vege == None
        ).all()
    ]


def _epuletek_a_ceghez(working_company_id: int, db: Session) -> list:
    """Az adott cég telephelyeihez tartozó, aktív épületek - a telephely+épület
    lenyíló-lánc (cascading select) kliensoldali feltöltéséhez."""
    return db.query(models.TuzvedelmiEpulet).join(models.TuzvedelmiTelephely).filter(
        models.TuzvedelmiTelephely.company_id == working_company_id,
        models.TuzvedelmiEpulet.aktiv == True,
        models.TuzvedelmiTelephely.aktiv == True,
    ).all()


@router.get("/tuzvedelem/dashboard", response_class=HTMLResponse)
def tuzvedelem_dashboard(
    request: Request,
    db: Session = Depends(get_db),
    current_user: models.User = Depends(get_current_user)
):
    """A modul kezdőlapja - ez az egyetlen tűzvédelem-oldal, amin a modulváltó ikon
    megjelenik, innen navigál tovább a felhasználó a készüléklistára/beállításokra."""
    working_company_id = get_working_company_id(current_user, request)

    kolcsonzott_keszulek_idk = _kolcsonzott_keszulek_idk_a_ceghez(working_company_id, db)
    keszulekek_query = db.query(models.TuzoltoKeszulek)
    if kolcsonzott_keszulek_idk:
        keszulekek_query = keszulekek_query.filter(
            or_(models.TuzoltoKeszulek.company_id == working_company_id, models.TuzoltoKeszulek.id.in_(kolcsonzott_keszulek_idk))
        )
    else:
        keszulekek_query = keszulekek_query.filter(models.TuzoltoKeszulek.company_id == working_company_id)
    keszulekek = keszulekek_query.filter(models.TuzoltoKeszulek.statusz.notin_(LEZART_STATUSZOK)).all()

    hosszabbitasok = db.query(models.ElettartamHosszabbitas).filter(
        models.ElettartamHosszabbitas.keszulek_id.in_([k.id for k in keszulekek])
    ).all() if keszulekek else []
    hosszabbitas_map = {}
    for h in hosszabbitasok:
        hosszabbitas_map.setdefault(h.keszulek_id, []).append(h)

    mai_nap = date.today()
    esedekessegek = {}
    for k in keszulekek:
        esedekessegek[k.id] = compute_tuzoltokeszulek_esedekesseg(k, mai_nap, hosszabbitas_map.get(k.id, []))

    lejart_szam = sum(1 for es in esedekessegek.values() if es["allapot"] == "lejart")
    esedekes_tipus_szamlalo = {"ALAP": 0, "KOZEP": 0, "TELJES_KORU": 0}
    for es in esedekessegek.values():
        if es["allapot"] in ("lejart", "hamarosan") and es["kovetkezo_esemeny"] in esedekes_tipus_szamlalo:
            esedekes_tipus_szamlalo[es["kovetkezo_esemeny"]] += 1

    # A soron lévő esedékességek listája (lejárt + hamarosan), a legsürgősebbtől.
    sorolando = [
        (k, esedekessegek[k.id]) for k in keszulekek
        if esedekessegek[k.id]["allapot"] in ("lejart", "hamarosan") and esedekessegek[k.id]["kovetkezo_esedekesseg"]
    ]
    sorolando.sort(key=lambda pair: pair[1]["kovetkezo_esedekesseg"])
    esedekessegi_lista = sorolando[:20]

    # Naptár: a folyó hónap napjaihoz rendelt esedékességek száma (a dashboard-widgethez).
    naptar_map = {}
    for k, es in sorolando:
        if es["kovetkezo_esedekesseg"] and es["kovetkezo_esedekesseg"].year == mai_nap.year and es["kovetkezo_esedekesseg"].month == mai_nap.month:
            naptar_map.setdefault(es["kovetkezo_esedekesseg"].day, 0)
            naptar_map[es["kovetkezo_esedekesseg"].day] += 1

    import calendar
    ho_naptar = calendar.monthcalendar(mai_nap.year, mai_nap.month)
    honapnevek = ["Január", "Február", "Március", "Április", "Május", "Június", "Július", "Augusztus", "Szeptember", "Október", "November", "December"]

    return templates.TemplateResponse(
        request=request,
        name="tuzvedelem_dashboard.html",
        context={
            "user": current_user,
            "cegek": get_allowed_companies_list(current_user, db, "TUZVEDELEM"),
            "working_company_id": working_company_id,
            "aktiv_keszulekek_szama": len(keszulekek),
            "lejart_szam": lejart_szam,
            "esedekes_tipus_szamlalo": esedekes_tipus_szamlalo,
            "esedekessegi_lista": esedekessegi_lista,
            "mai_nap": mai_nap,
            "ho_naptar": ho_naptar,
            "naptar_map": naptar_map,
            "honap_nev": honapnevek[mai_nap.month - 1],
            "tobb_modul_van": van_e_tobb_modulja(current_user, db),
        }
    )


@router.get("/tuzvedelem/beallitasok", response_class=HTMLResponse)
def tuzvedelem_lista(
    request: Request,
    db: Session = Depends(get_db),
    current_user: models.User = Depends(get_current_user)
):
    working_company_id = get_working_company_id(current_user, request)

    telephelyek = db.query(models.TuzvedelmiTelephely).filter(
        models.TuzvedelmiTelephely.company_id == working_company_id, models.TuzvedelmiTelephely.aktiv == True
    ).all()
    helyek = db.query(models.KeszenletiHely).filter(
        models.KeszenletiHely.company_id == working_company_id,
        models.KeszenletiHely.aktiv == True
    ).all()

    # A saját készülékek mellett a karbantartótól kölcsönzött (más cég tulajdonában lévő,
    # de ideiglenesen ide kihelyezett csere-) készülékek is megjelennek.
    kolcsonzott_keszulek_idk = _kolcsonzott_keszulek_idk_a_ceghez(working_company_id, db)

    keszulekek_query = db.query(models.TuzoltoKeszulek)
    if kolcsonzott_keszulek_idk:
        keszulekek_query = keszulekek_query.filter(
            or_(models.TuzoltoKeszulek.company_id == working_company_id, models.TuzoltoKeszulek.id.in_(kolcsonzott_keszulek_idk))
        )
    else:
        keszulekek_query = keszulekek_query.filter(models.TuzoltoKeszulek.company_id == working_company_id)
    keszulekek = keszulekek_query.all()
    keszulek_map = {k.id: k for k in keszulekek}
    for k in keszulekek:
        k.kolcsonzott_nalam = (k.company_id != working_company_id)

    hosszabbitasok = db.query(models.ElettartamHosszabbitas).filter(
        models.ElettartamHosszabbitas.keszulek_id.in_([k.id for k in keszulekek])
    ).all()
    hosszabbitas_map = {}
    for h in hosszabbitasok:
        hosszabbitas_map.setdefault(h.keszulek_id, []).append(h)

    mai_nap = date.today()
    esedekessegek = {}
    for k in keszulekek:
        esedekessegek[k.id] = compute_tuzoltokeszulek_esedekesseg(k, mai_nap, hosszabbitas_map.get(k.id, []))

    helyek_telephely_szerint = {}
    for h in helyek:
        helyek_telephely_szerint.setdefault(h.telephely_id, []).append(h)

    raktaron = [k for k in keszulekek if k.jelenlegi_hely_id is None and k.statusz == "Raktáron"]
    jovahagyasra_var = [k for k in keszulekek if not k.jovahagyva] if current_user.role in ["Admin"] else []

    karbantarto_cegek = db.query(models.KarbantartoCeg).filter(
        models.KarbantartoCeg.company_id == working_company_id,
        models.KarbantartoCeg.aktiv == True
    ).all()
    karbantarto_szerzodes_map = {}
    if karbantarto_cegek:
        szerzodesek = db.query(models.KarbantartoSzerzodes).filter(
            models.KarbantartoSzerzodes.karbantarto_ceg_id.in_([c.id for c in karbantarto_cegek])
        ).all()
        for sz in szerzodesek:
            if sz.vege is None:
                karbantarto_szerzodes_map[sz.karbantarto_ceg_id] = sz

    ceges_felhasznalok = []
    szakvizsgak = []
    if current_user.role in ["Admin"]:
        ceges_felhasznalok = db.query(models.User).filter(models.User.company_id == working_company_id).all()
        szakvizsgak = db.query(models.Szakvizsga).filter(
            models.Szakvizsga.user_id.in_([u.id for u in ceges_felhasznalok])
        ).all() if ceges_felhasznalok else []

    return templates.TemplateResponse(
        request=request,
        name="tuzvedelem_lista.html",
        context={
            "user": current_user,
            "cegek": get_allowed_companies_list(current_user, db, "TUZVEDELEM"),
            "telephelyek": telephelyek,
            "ceges_felhasznalok": ceges_felhasznalok,
            "szakvizsgak": szakvizsgak,
            "szakvizsga_kategoriak": {k: SZAKVIZSGA_KATEGORIAK[k] for k in AKTIV_SZAKVIZSGA_KATEGORIAK},
            "mai_nap": mai_nap,
            "helyek_telephely_szerint": helyek_telephely_szerint,
            "keszulek_map": keszulek_map,
            "esedekessegek": esedekessegek,
            "raktaron": raktaron,
            "jovahagyasra_var": jovahagyasra_var,
            "karbantarto_cegek": karbantarto_cegek,
            "karbantarto_szerzodes_map": karbantarto_szerzodes_map,
            "szerkesztheto": _lehet_szerkeszteni(current_user, working_company_id, db),
            "working_company_id": working_company_id,
            "mai_ev": mai_nap.year,
        }
    )


@router.get("/tuzvedelem", response_class=HTMLResponse)
def tuzvedelem_keszulekek_lista(
    request: Request,
    kereses: str = "",
    page: int = 1,
    rendezes: str = "id",
    irany: str = "desc",
    db: Session = Depends(get_db),
    current_user: models.User = Depends(get_current_user)
):
    """Lapos, kereshető/rendezhető, teljes céges készüléklista - a saját készülékek mellett
    a karbantartótól kölcsönzött csere-készülékeket is tartalmazza."""
    working_company_id = get_working_company_id(current_user, request)
    kolcsonzott_keszulek_idk = _kolcsonzott_keszulek_idk_a_ceghez(working_company_id, db)

    if kolcsonzott_keszulek_idk:
        query = db.query(models.TuzoltoKeszulek).filter(
            or_(models.TuzoltoKeszulek.company_id == working_company_id, models.TuzoltoKeszulek.id.in_(kolcsonzott_keszulek_idk))
        )
    else:
        query = db.query(models.TuzoltoKeszulek).filter(models.TuzoltoKeszulek.company_id == working_company_id)

    if kereses:
        query = query.filter(_keszulek_kereses_szures(kereses))

    per_page = 20
    total_items = query.count()
    total_pages = max(1, math.ceil(total_items / per_page)) if total_items > 0 else 1

    if page < 1:
        page = 1
    if page > total_pages:
        page = total_pages

    if irany not in ("asc", "desc"):
        irany = "desc"

    if rendezes == "telephely":
        query = query.outerjoin(models.KeszenletiHely, models.TuzoltoKeszulek.jelenlegi_hely_id == models.KeszenletiHely.id) \
                      .outerjoin(models.TuzvedelmiTelephely, models.KeszenletiHely.telephely_id == models.TuzvedelmiTelephely.id)
        rendezo_oszlop = models.TuzvedelmiTelephely.nev
    elif rendezes == "eredet":
        rendezo_oszlop = case((models.TuzoltoKeszulek.company_id == working_company_id, 0), else_=1)
    else:
        rendezo_oszlop = KESZULEK_RENDEZHETO_OSZLOPOK.get(rendezes, models.TuzoltoKeszulek.id)

    query = query.order_by(rendezo_oszlop.asc() if irany == "asc" else rendezo_oszlop.desc())

    offset_value = (page - 1) * per_page
    keszulekek = query.offset(offset_value).limit(per_page).all()

    hosszabbitasok = db.query(models.ElettartamHosszabbitas).filter(
        models.ElettartamHosszabbitas.keszulek_id.in_([k.id for k in keszulekek])
    ).all() if keszulekek else []
    hosszabbitas_map = {}
    for h in hosszabbitasok:
        hosszabbitas_map.setdefault(h.keszulek_id, []).append(h)

    mai_nap = date.today()
    esedekessegek = {}
    for k in keszulekek:
        k.kolcsonzott_nalam = (k.company_id != working_company_id)
        esedekessegek[k.id] = compute_tuzoltokeszulek_esedekesseg(k, mai_nap, hosszabbitas_map.get(k.id, []))

    telephelyek = db.query(models.TuzvedelmiTelephely).filter(
        models.TuzvedelmiTelephely.company_id == working_company_id, models.TuzvedelmiTelephely.aktiv == True
    ).all()

    naplok = []
    if telephelyek:
        naplok = db.query(models.TuzvedelmiNaplo).filter(
            models.TuzvedelmiNaplo.telephely_id.in_([t.id for t in telephelyek])
        ).order_by(models.TuzvedelmiNaplo.ev.desc()).all()

    return templates.TemplateResponse(
        request=request,
        name="tuzvedelem_keszulekek_lista.html",
        context={
            "user": current_user,
            "cegek": get_allowed_companies_list(current_user, db, "TUZVEDELEM"),
            "working_company_id": working_company_id,
            "keszulekek": keszulekek,
            "esedekessegek": esedekessegek,
            "kereses": kereses,
            "current_page": page,
            "total_pages": total_pages,
            "rendezes": rendezes,
            "irany": irany,
            "telephelyek": telephelyek,
            "naplok": naplok,
            "mai_ev": mai_nap.year,
            "szerkesztheto": _lehet_szerkeszteni(current_user, working_company_id, db),
        }
    )


@router.get("/tuzvedelem/telephelyek", response_class=HTMLResponse)
def tuzvedelem_telephelyek_lista(
    request: Request,
    db: Session = Depends(get_db),
    current_user: models.User = Depends(get_current_user)
):
    working_company_id = get_working_company_id(current_user, request)

    telephelyek = db.query(models.TuzvedelmiTelephely).filter(
        models.TuzvedelmiTelephely.company_id == working_company_id, models.TuzvedelmiTelephely.aktiv == True
    ).all()
    epuletek = _epuletek_a_ceghez(working_company_id, db)

    epuletek_telephely_szerint = {}
    for e in epuletek:
        epuletek_telephely_szerint.setdefault(e.telephely_id, []).append(e)

    hely_szamlalo = {}
    if epuletek:
        helyek = db.query(models.KeszenletiHely).filter(
            models.KeszenletiHely.epulet_id.in_([e.id for e in epuletek]), models.KeszenletiHely.aktiv == True
        ).all()
        for h in helyek:
            hely_szamlalo[h.epulet_id] = hely_szamlalo.get(h.epulet_id, 0) + 1

    return templates.TemplateResponse(
        request=request,
        name="tuzvedelem_telephelyek.html",
        context={
            "user": current_user,
            "cegek": get_allowed_companies_list(current_user, db, "TUZVEDELEM"),
            "working_company_id": working_company_id,
            "telephelyek": telephelyek,
            "epuletek_telephely_szerint": epuletek_telephely_szerint,
            "hely_szamlalo": hely_szamlalo,
            "foldszint_valtozatok": FOLDSZINT_VALTOZATOK,
            "szerkesztheto": _lehet_szerkeszteni(current_user, working_company_id, db),
        }
    )


@router.post("/tuzvedelem/telephely/{telephely_id}/szerkesztes")
def telephely_szerkesztese(
    telephely_id: int,
    request: Request,
    nev: str = Form(...),
    cim: str = Form(""),
    db: Session = Depends(get_db),
    current_user: models.User = Depends(get_current_user)
):
    working_company_id = get_working_company_id(current_user, request)
    if not _lehet_szerkeszteni(current_user, working_company_id, db):
        return RedirectResponse(url="/tuzvedelem/telephelyek", status_code=303)

    telephely = db.query(models.TuzvedelmiTelephely).filter(
        models.TuzvedelmiTelephely.id == telephely_id, models.TuzvedelmiTelephely.company_id == working_company_id
    ).first()
    if telephely:
        telephely.nev = nev
        telephely.cim = cim or None
        db.commit()
    return RedirectResponse(url="/tuzvedelem/telephelyek", status_code=303)


@router.delete("/tuzvedelem/telephely/{telephely_id}")
def telephely_torlese(
    telephely_id: int,
    request: Request,
    db: Session = Depends(get_db),
    current_user: models.User = Depends(get_current_user)
):
    if current_user.role not in ["Admin"]:
        return JSONResponse(status_code=403, content={"message": "Csak Admin!"})

    working_company_id = get_working_company_id(current_user, request)

    if not is_company_active(working_company_id, db):
        return JSONResponse(status_code=403, content={"message": "Ez a cég inaktív státuszú, törlés nem lehetséges!"})

    if current_user.csak_olvasas:
        return JSONResponse(status_code=403, content={"message": "Csak megtekintési jogosultsággal rendelkezel, szerkesztés nem lehetséges!"})
    telephely = db.query(models.TuzvedelmiTelephely).filter(
        models.TuzvedelmiTelephely.id == telephely_id, models.TuzvedelmiTelephely.company_id == working_company_id
    ).first()
    if telephely:
        telephely.aktiv = False
        db.commit()
    return JSONResponse(status_code=200, content={"message": "Törölve."})


@router.post("/tuzvedelem/uj-epulet")
def uj_epulet_mentese(
    request: Request,
    telephely_id: int = Form(...),
    nev: str = Form(...),
    leiras: str = Form(""),
    pinceszintek: str = Form("0"),
    foldszint_valtozat: str = Form(ALAP_FOLDSZINT_VALTOZAT),
    emeletek: str = Form("0"),
    db: Session = Depends(get_db),
    current_user: models.User = Depends(get_current_user)
):
    working_company_id = get_working_company_id(current_user, request)
    if not _lehet_szerkeszteni(current_user, working_company_id, db):
        return RedirectResponse(url="/tuzvedelem/telephelyek", status_code=303)

    telephely = db.query(models.TuzvedelmiTelephely).filter(
        models.TuzvedelmiTelephely.id == telephely_id, models.TuzvedelmiTelephely.company_id == working_company_id
    ).first()
    if not telephely:
        return RedirectResponse(url="/tuzvedelem/telephelyek", status_code=303)

    db.add(models.TuzvedelmiEpulet(
        telephely_id=telephely_id, nev=nev, leiras=leiras or None,
        pinceszintek=int(pinceszintek) if pinceszintek else 0,
        foldszint_valtozat=foldszint_valtozat if foldszint_valtozat in FOLDSZINT_VALTOZATOK else ALAP_FOLDSZINT_VALTOZAT,
        emeletek=int(emeletek) if emeletek else 0,
    ))
    db.commit()
    return RedirectResponse(url="/tuzvedelem/telephelyek", status_code=303)


@router.post("/tuzvedelem/epulet/{epulet_id}/szerkesztes")
def epulet_szerkesztese(
    epulet_id: int,
    request: Request,
    nev: str = Form(...),
    leiras: str = Form(""),
    pinceszintek: str = Form("0"),
    foldszint_valtozat: str = Form(ALAP_FOLDSZINT_VALTOZAT),
    emeletek: str = Form("0"),
    db: Session = Depends(get_db),
    current_user: models.User = Depends(get_current_user)
):
    working_company_id = get_working_company_id(current_user, request)
    if not _lehet_szerkeszteni(current_user, working_company_id, db):
        return RedirectResponse(url="/tuzvedelem/telephelyek", status_code=303)

    epulet = db.query(models.TuzvedelmiEpulet).join(models.TuzvedelmiTelephely).filter(
        models.TuzvedelmiEpulet.id == epulet_id, models.TuzvedelmiTelephely.company_id == working_company_id
    ).first()
    if epulet:
        epulet.nev = nev
        epulet.leiras = leiras or None
        epulet.pinceszintek = int(pinceszintek) if pinceszintek else 0
        epulet.foldszint_valtozat = foldszint_valtozat if foldszint_valtozat in FOLDSZINT_VALTOZATOK else ALAP_FOLDSZINT_VALTOZAT
        epulet.emeletek = int(emeletek) if emeletek else 0
        db.commit()
    return RedirectResponse(url="/tuzvedelem/telephelyek", status_code=303)


@router.delete("/tuzvedelem/epulet/{epulet_id}")
def epulet_torlese(
    epulet_id: int,
    request: Request,
    db: Session = Depends(get_db),
    current_user: models.User = Depends(get_current_user)
):
    if current_user.role not in ["Admin"]:
        return JSONResponse(status_code=403, content={"message": "Csak Admin!"})

    working_company_id = get_working_company_id(current_user, request)

    if not is_company_active(working_company_id, db):
        return JSONResponse(status_code=403, content={"message": "Ez a cég inaktív státuszú, törlés nem lehetséges!"})

    if current_user.csak_olvasas:
        return JSONResponse(status_code=403, content={"message": "Csak megtekintési jogosultsággal rendelkezel, szerkesztés nem lehetséges!"})
    epulet = db.query(models.TuzvedelmiEpulet).join(models.TuzvedelmiTelephely).filter(
        models.TuzvedelmiEpulet.id == epulet_id, models.TuzvedelmiTelephely.company_id == working_company_id
    ).first()
    if epulet:
        epulet.aktiv = False
        db.commit()
    return JSONResponse(status_code=200, content={"message": "Törölve."})


@router.get("/tuzvedelem/keszulek-tipusok/kereses")
def keszulek_tipusok_keresese(
    request: Request,
    q: str = "",
    db: Session = Depends(get_db),
    current_user: models.User = Depends(get_current_user)
):
    """Típuskatalógus-kereső az új készülék felviteléhez (autocomplete): a globális
    (fireg.hu alapú) katalógus, plusz a cég saját, egyedi felvitelű típusai."""
    working_company_id = get_working_company_id(current_user, request)
    if not q or len(q) < 2:
        return JSONResponse(content={"talalatok": []})

    term = f"%{q}%"
    # A "gyártó + típus" összefűzött alakra is illesztünk, mert a felhasználó jellemzően
    # együtt gépeli be a kettőt (pl. "Total FX 6"), nem külön-külön a mezőket.
    osszefuzve = models.TuzoltoKeszulekTipus.gyarto.concat(" ").concat(models.TuzoltoKeszulekTipus.tipus_nev)
    tipusok = db.query(models.TuzoltoKeszulekTipus).filter(
        or_(models.TuzoltoKeszulekTipus.company_id == None, models.TuzoltoKeszulekTipus.company_id == working_company_id),
        models.TuzoltoKeszulekTipus.aktiv == True,
        or_(
            models.TuzoltoKeszulekTipus.gyarto.ilike(term),
            models.TuzoltoKeszulekTipus.tipus_nev.ilike(term),
            osszefuzve.ilike(term),
        ),
    ).order_by(models.TuzoltoKeszulekTipus.gyarto).limit(15).all()

    return JSONResponse(content={"talalatok": [
        {
            "id": t.id, "gyarto": t.gyarto, "tipus_nev": t.tipus_nev,
            "oltoanyag_tipus": t.oltoanyag_tipus, "gyartasi_szabvany": t.gyartasi_szabvany,
            "oe_ertek": t.oe_ertek, "toltettomeg_kg": t.toltettomeg_kg,
        } for t in tipusok
    ]})


@router.post("/tuzvedelem/uj-telephely")
def uj_telephely_mentese(
    request: Request,
    nev: str = Form(...),
    cim: str = Form(""),
    db: Session = Depends(get_db),
    current_user: models.User = Depends(get_current_user)
):
    """A tűzvédelmi modul saját telephely-nyilvántartása - teljesen független az
    emelőgépes Site-tól, még akkor is, ha fizikailag ugyanaz a cím."""
    working_company_id = get_working_company_id(current_user, request)
    if not _lehet_szerkeszteni(current_user, working_company_id, db):
        return RedirectResponse(url="/tuzvedelem/telephelyek", status_code=303)

    db.add(models.TuzvedelmiTelephely(company_id=working_company_id, nev=nev, cim=cim or None))
    db.commit()
    return RedirectResponse(url="/tuzvedelem/telephelyek", status_code=303)


@router.get("/tuzvedelem/uj-hely", response_class=HTMLResponse)
def uj_hely_oldal(
    request: Request,
    db: Session = Depends(get_db),
    current_user: models.User = Depends(get_current_user)
):
    working_company_id = get_working_company_id(current_user, request)
    telephelyek = db.query(models.TuzvedelmiTelephely).filter(
        models.TuzvedelmiTelephely.company_id == working_company_id, models.TuzvedelmiTelephely.aktiv == True
    ).all()
    epuletek = _epuletek_a_ceghez(working_company_id, db)
    return templates.TemplateResponse(
        request=request,
        name="tuzvedelem_hely_form.html",
        context={
            "user": current_user, "cegek": get_allowed_companies_list(current_user, db, "TUZVEDELEM"),
            "working_company_id": working_company_id,
            "telephelyek": telephelyek, "hely": None,
            "epuletek_json": safe_json_for_script([
                {"id": e.id, "telephely_id": e.telephely_id, "nev": e.nev, "szintek": szint_lista(e.pinceszintek, e.foldszint_valtozat, e.emeletek)} for e in epuletek
            ]),
            "oe_alapterulet_aktiv": get_oe_alapterulet_szamitas(working_company_id, db),
        }
    )


@router.post("/tuzvedelem/uj-hely")
def uj_hely_mentese(
    request: Request,
    epulet_id: int = Form(...),
    szint: str = Form(""),
    hely_leiras: str = Form(...),
    alapterulet_m2: str = Form(""),
    robbanasveszelyes: str = Form(""),
    db: Session = Depends(get_db),
    current_user: models.User = Depends(get_current_user)
):
    working_company_id = get_working_company_id(current_user, request)
    if not _lehet_szerkeszteni(current_user, working_company_id, db):
        return RedirectResponse(url="/tuzvedelem/beallitasok", status_code=303)

    epulet = db.query(models.TuzvedelmiEpulet).join(models.TuzvedelmiTelephely).filter(
        models.TuzvedelmiEpulet.id == epulet_id, models.TuzvedelmiTelephely.company_id == working_company_id
    ).first()
    if not epulet:
        return RedirectResponse(url="/tuzvedelem/uj-hely", status_code=303)

    hely = models.KeszenletiHely(
        company_id=working_company_id,
        telephely_id=epulet.telephely_id,
        epulet_id=epulet.id,
        szint=szint or None,
        hely_leiras=hely_leiras,
        alapterulet_m2=float(alapterulet_m2) if alapterulet_m2 else None,
        robbanasveszelyes=(robbanasveszelyes == "on"),
    )
    db.add(hely)
    db.commit()
    return RedirectResponse(url="/tuzvedelem/beallitasok", status_code=303)


@router.get("/tuzvedelem/hely/{hely_id}/szerkesztes", response_class=HTMLResponse)
def hely_szerkesztes_oldal(
    hely_id: int,
    request: Request,
    db: Session = Depends(get_db),
    current_user: models.User = Depends(get_current_user)
):
    working_company_id = get_working_company_id(current_user, request)
    hely = db.query(models.KeszenletiHely).filter(
        models.KeszenletiHely.id == hely_id, models.KeszenletiHely.company_id == working_company_id
    ).first()
    if not hely:
        return RedirectResponse(url="/tuzvedelem/beallitasok", status_code=303)

    telephelyek = db.query(models.TuzvedelmiTelephely).filter(
        models.TuzvedelmiTelephely.company_id == working_company_id, models.TuzvedelmiTelephely.aktiv == True
    ).all()
    epuletek = _epuletek_a_ceghez(working_company_id, db)
    return templates.TemplateResponse(
        request=request,
        name="tuzvedelem_hely_form.html",
        context={
            "user": current_user, "cegek": get_allowed_companies_list(current_user, db, "TUZVEDELEM"),
            "working_company_id": working_company_id,
            "telephelyek": telephelyek, "hely": hely,
            "epuletek_json": safe_json_for_script([
                {"id": e.id, "telephely_id": e.telephely_id, "nev": e.nev, "szintek": szint_lista(e.pinceszintek, e.foldszint_valtozat, e.emeletek)} for e in epuletek
            ]),
            "oe_alapterulet_aktiv": get_oe_alapterulet_szamitas(working_company_id, db),
        }
    )


@router.post("/tuzvedelem/hely/{hely_id}/szerkesztes")
def hely_szerkesztes_mentese(
    hely_id: int,
    request: Request,
    epulet_id: int = Form(...),
    szint: str = Form(""),
    hely_leiras: str = Form(...),
    alapterulet_m2: str = Form(""),
    robbanasveszelyes: str = Form(""),
    db: Session = Depends(get_db),
    current_user: models.User = Depends(get_current_user)
):
    working_company_id = get_working_company_id(current_user, request)
    if not _lehet_szerkeszteni(current_user, working_company_id, db):
        return RedirectResponse(url="/tuzvedelem/beallitasok", status_code=303)

    epulet = db.query(models.TuzvedelmiEpulet).join(models.TuzvedelmiTelephely).filter(
        models.TuzvedelmiEpulet.id == epulet_id, models.TuzvedelmiTelephely.company_id == working_company_id
    ).first()
    if not epulet:
        return RedirectResponse(url=f"/tuzvedelem/hely/{hely_id}/szerkesztes", status_code=303)

    hely = db.query(models.KeszenletiHely).filter(
        models.KeszenletiHely.id == hely_id, models.KeszenletiHely.company_id == working_company_id
    ).first()
    if hely:
        hely.telephely_id = epulet.telephely_id
        hely.epulet_id = epulet.id
        hely.szint = szint or None
        hely.hely_leiras = hely_leiras
        hely.alapterulet_m2 = float(alapterulet_m2) if alapterulet_m2 else None
        hely.robbanasveszelyes = (robbanasveszelyes == "on")
        db.commit()
    return RedirectResponse(url="/tuzvedelem/beallitasok", status_code=303)


@router.get("/tuzvedelem/uj-keszulek", response_class=HTMLResponse)
def uj_keszulek_oldal(
    request: Request,
    hely_id: int = 0,
    db: Session = Depends(get_db),
    current_user: models.User = Depends(get_current_user)
):
    working_company_id = get_working_company_id(current_user, request)
    telephelyek = db.query(models.TuzvedelmiTelephely).filter(
        models.TuzvedelmiTelephely.company_id == working_company_id, models.TuzvedelmiTelephely.aktiv == True
    ).all()
    epuletek = _epuletek_a_ceghez(working_company_id, db)

    elovalasztott_hely = None
    if hely_id:
        elovalasztott_hely = db.query(models.KeszenletiHely).filter(
            models.KeszenletiHely.id == hely_id, models.KeszenletiHely.company_id == working_company_id
        ).first()

    return templates.TemplateResponse(
        request=request,
        name="tuzvedelem_keszulek_form.html",
        context={
            "user": current_user, "cegek": get_allowed_companies_list(current_user, db, "TUZVEDELEM"),
            "working_company_id": working_company_id,
            "telephelyek": telephelyek,
            "epuletek_json": safe_json_for_script([
                {"id": e.id, "telephely_id": e.telephely_id, "nev": e.nev, "szintek": szint_lista(e.pinceszintek, e.foldszint_valtozat, e.emeletek)} for e in epuletek
            ]),
            "elovalasztott_hely": elovalasztott_hely,
            "keszulek": None,
            "gyartasi_szabvanyok": GYARTASI_SZABVANYOK, "oltoanyag_tipusok": OLTOANYAG_TIPUSOK,
        }
    )


@router.get("/tuzvedelem/keszulek/duplikatum-ellenorzes")
def keszulek_duplikatum_ellenorzes(
    request: Request,
    gyari_szam: str = "",
    db: Session = Depends(get_db),
    current_user: models.User = Depends(get_current_user)
):
    """Mentés előtti, élő ellenőrzés: van-e már a cégnél másik tűzoltó készülék ugyanazzal a
    gyári számmal - az új készülék felviteli űrlap ezt hívja meg mentés előtt."""
    working_company_id = get_working_company_id(current_user, request)

    talalat = keres_duplikatum_keszuleket(db, working_company_id, gyari_szam)

    if not talalat:
        return {"duplikatum": False}

    return {
        "duplikatum": True,
        "talalat": {
            "id": talalat.id,
            "gyarto": talalat.gyarto,
            "tipus_nev": talalat.tipus_nev,
            "gyari_szam": talalat.gyari_szam,
            "hely": talalat.jelenlegi_hely.hely_leiras if talalat.jelenlegi_hely else None,
            "statusz": talalat.statusz,
        }
    }


@router.post("/tuzvedelem/uj-keszulek")
def uj_keszulek_mentese(
    request: Request,
    epulet_id: str = Form(""),
    szint: str = Form(""),
    hely_leiras: str = Form(""),
    gyarto: str = Form(""),
    tipus_nev: str = Form(""),
    gyari_szam: str = Form(""),
    duplikatum_megerositve: str = Form("nem"),
    gyartasi_szabvany: str = Form(""),
    oltoanyag_tipus: str = Form(""),
    oe_ertek: str = Form(""),
    toltettomeg_kg: str = Form(""),
    gyartas_datum: str = Form(""),
    gyartoi_ellenorzes: str = Form(""),
    tipus_mentese_katalogusba: str = Form(""),
    db: Session = Depends(get_db),
    current_user: models.User = Depends(get_current_user)
):
    working_company_id = get_working_company_id(current_user, request)
    if not _lehet_szerkeszteni(current_user, working_company_id, db):
        return RedirectResponse(url="/tuzvedelem", status_code=303)

    # Védelem: ne engedjen automatikusan menteni azonos gyári számmal - kivéve, ha a
    # felhasználó a figyelmeztetés után kifejezetten megerősítette.
    if duplikatum_megerositve != "igen":
        duplikatum = keres_duplikatum_keszuleket(db, working_company_id, gyari_szam)
        if duplikatum:
            return JSONResponse(
                status_code=409,
                content={
                    "message": "Már létezik tűzoltó készülék ezzel a gyári számmal!",
                    "duplikatum": True,
                    "talalat": {
                        "gyarto": duplikatum.gyarto,
                        "tipus_nev": duplikatum.tipus_nev,
                        "gyari_szam": duplikatum.gyari_szam,
                        "hely": duplikatum.jelenlegi_hely.hely_leiras if duplikatum.jelenlegi_hely else None,
                    }
                }
            )

    gyartas_datum_obj = _parse_date(gyartas_datum)
    # Ha csak évet adtak meg (ÉÉÉÉ formátumban), az érvényesség január 1-től számít
    if not gyartas_datum_obj and gyartas_datum and gyartas_datum.isdigit() and len(gyartas_datum) == 4:
        gyartas_datum_obj = date(int(gyartas_datum), 1, 1)

    # Ha a felhasználó nem a saját (törzs) cégének kontextusában dolgozik - azaz külső
    # karbantartóként lép be egy másik (üzemeltető) cég munkaterébe -, az általa felvitt
    # készülék jóváhagyásra vár, amíg az adatgazda cég Admin-ja meg nem erősíti.
    kulso_felvitel = (current_user.company_id != working_company_id)

    # J-13 (v71): a nem szám épület-azonosító korábban 500-at okozott (int() kivétel)
    epulet_id_szam, epulet_hiba = _id_vagy_hiba(epulet_id, "épület")
    if epulet_hiba:
        return JSONResponse(status_code=400, content={"message": epulet_hiba})

    hely_id = None
    if epulet_id_szam is not None and hely_leiras.strip() and not kulso_felvitel:
        epulet = db.query(models.TuzvedelmiEpulet).join(models.TuzvedelmiTelephely).filter(
            models.TuzvedelmiEpulet.id == epulet_id_szam, models.TuzvedelmiTelephely.company_id == working_company_id
        ).first()
        if epulet:
            # Ha már van ilyen leírású (és szintű) hely ebben az épületben, azt használjuk -
            # nem duplikáljuk a készenléti pontot minden egyes új készülék felvitelekor.
            hely = db.query(models.KeszenletiHely).filter(
                models.KeszenletiHely.epulet_id == epulet.id,
                models.KeszenletiHely.company_id == working_company_id,
                models.KeszenletiHely.aktiv == True,
                func.lower(models.KeszenletiHely.hely_leiras) == hely_leiras.strip().lower(),
                models.KeszenletiHely.szint == (szint or None),
            ).first()
            if not hely:
                hely = models.KeszenletiHely(
                    company_id=working_company_id, telephely_id=epulet.telephely_id, epulet_id=epulet.id,
                    szint=szint or None, hely_leiras=hely_leiras.strip(),
                )
                db.add(hely)
                db.commit()
                db.refresh(hely)
            hely_id = hely.id

    keszulek = models.TuzoltoKeszulek(
        company_id=working_company_id,
        jelenlegi_hely_id=hely_id,
        gyarto=gyarto or None,
        tipus_nev=tipus_nev or None,
        gyari_szam=gyari_szam or None,
        gyartasi_szabvany=gyartasi_szabvany or None,
        oltoanyag_tipus=oltoanyag_tipus or None,
        oe_ertek=oe_ertek or None,
        toltettomeg_kg=float(toltettomeg_kg) if toltettomeg_kg else None,
        gyartas_datum=gyartas_datum_obj,
        gyartoi_ellenorzes=(gyartoi_ellenorzes == "on"),
        gyartoi_ellenorzes_kezdete=gyartas_datum_obj if gyartoi_ellenorzes == "on" else None,
        # A gyártói ellenőrzés az első évi "alap" karbantartási pontot helyettesíti - enélkül
        # a napló Alap oszlopa üresen maradna, holott a készülék éppen ettől számítva megfelelő.
        utolso_alap_karbantartas=gyartas_datum_obj if gyartoi_ellenorzes == "on" else None,
        statusz="Jóváhagyásra vár" if kulso_felvitel else "Aktív",
        jovahagyva=not kulso_felvitel,
        letrehozo_user_id=current_user.id,
    )
    db.add(keszulek)
    db.commit()
    db.refresh(keszulek)

    if keszulek.gyartoi_ellenorzes and gyartas_datum_obj:
        db.add(models.TuzvedelmiEllenorzes(
            keszulek_id=keszulek.id, tipus="ALAP", datum=gyartas_datum_obj,
            megjegyzes="Gyártói ellenőrzéssel érkezett.", rogzito_user_id=current_user.id,
        ))
        db.commit()

    if keszulek.jelenlegi_hely_id:
        db.add(models.KeszulekTortenet(
            keszenleti_hely_id=keszulek.jelenlegi_hely_id, keszulek_id=keszulek.id, kezdete=date.today()
        ))
        db.commit()

    # "Bővíthető lista": ha a felhasználó bejelölte, az itt felvitt típus bekerül a cég
    # saját (company_id-hoz kötött) típuskatalógusába, így legközelebb kereséssel elérhető.
    if tipus_mentese_katalogusba == "on" and gyarto and tipus_nev:
        mar_letezik = db.query(models.TuzoltoKeszulekTipus).filter(
            models.TuzoltoKeszulekTipus.company_id == working_company_id,
            models.TuzoltoKeszulekTipus.gyarto == gyarto,
            models.TuzoltoKeszulekTipus.tipus_nev == tipus_nev,
        ).first()
        if not mar_letezik:
            db.add(models.TuzoltoKeszulekTipus(
                company_id=working_company_id, gyarto=gyarto, tipus_nev=tipus_nev,
                oltoanyag_tipus=oltoanyag_tipus or None, gyartasi_szabvany=gyartasi_szabvany or None,
                oe_ertek=oe_ertek or None, toltettomeg_kg=float(toltettomeg_kg) if toltettomeg_kg else None,
            ))
            db.commit()

    return RedirectResponse(url="/tuzvedelem", status_code=303)


@router.get("/tuzvedelem/keszulek/{keszulek_id}", response_class=HTMLResponse)
def keszulek_adatlap(
    keszulek_id: int,
    request: Request,
    db: Session = Depends(get_db),
    current_user: models.User = Depends(get_current_user)
):
    working_company_id = get_working_company_id(current_user, request)
    kolcsonzott_keszulek_idk = _kolcsonzott_keszulek_idk_a_ceghez(working_company_id, db)
    keszulek = db.query(models.TuzoltoKeszulek).filter(
        models.TuzoltoKeszulek.id == keszulek_id,
        or_(models.TuzoltoKeszulek.company_id == working_company_id, models.TuzoltoKeszulek.id.in_(kolcsonzott_keszulek_idk))
    ).first()
    if not keszulek:
        return RedirectResponse(url="/tuzvedelem", status_code=303)

    kolcsonzott_nalam = (keszulek.company_id != working_company_id)

    hosszabbitasok = db.query(models.ElettartamHosszabbitas).filter(
        models.ElettartamHosszabbitas.keszulek_id == keszulek_id
    ).all()
    esedekesseg = compute_tuzoltokeszulek_esedekesseg(keszulek, date.today(), hosszabbitasok)

    ellenorzesek = db.query(models.TuzvedelmiEllenorzes).filter(
        models.TuzvedelmiEllenorzes.keszulek_id == keszulek_id
    ).order_by(models.TuzvedelmiEllenorzes.datum.desc()).all()

    helyek = db.query(models.KeszenletiHely).filter(
        models.KeszenletiHely.company_id == working_company_id, models.KeszenletiHely.aktiv == True
    ).all()
    karbantarto_cegek = db.query(models.KarbantartoCeg).filter(
        models.KarbantartoCeg.company_id == working_company_id, models.KarbantartoCeg.aktiv == True
    ).all()

    # Csere-lehetőségek "szervizbe küldéskor": saját raktáron lévő készülékek, plusz azon
    # karbantartó cégek elérhető (raktáron lévő) készülékei, akikkel aktív szerződésünk van
    # és akik maguk is rendszerhasználók (van tenant_company_id-juk).
    sajat_raktaron = db.query(models.TuzoltoKeszulek).filter(
        models.TuzoltoKeszulek.company_id == working_company_id,
        models.TuzoltoKeszulek.jelenlegi_hely_id == None,
        models.TuzoltoKeszulek.statusz == "Raktáron"
    ).all()

    karbantarto_raktarak = []
    for kc in karbantarto_cegek:
        if not kc.tenant_company_id:
            continue
        van_aktiv_szerzodes = db.query(models.KarbantartoSzerzodes).filter(
            models.KarbantartoSzerzodes.karbantarto_ceg_id == kc.id, models.KarbantartoSzerzodes.vege == None
        ).first()
        if not van_aktiv_szerzodes:
            continue
        elerheto_keszulekek = db.query(models.TuzoltoKeszulek).filter(
            models.TuzoltoKeszulek.company_id == kc.tenant_company_id,
            models.TuzoltoKeszulek.jelenlegi_hely_id == None,
            models.TuzoltoKeszulek.jovahagyva == True,
            models.TuzoltoKeszulek.statusz.notin_(["Selejtezve"])
        ).all()
        if elerheto_keszulekek:
            karbantarto_raktarak.append({"karbantarto_ceg": kc, "keszulekek": elerheto_keszulekek})

    # Ha ez a készülék jelenleg kölcsönbe van adva (ez egy karbantartó saját eszköze, ami
    # nálunk áll), vagy éppen szervizben van és van helyette aktív kölcsönzés
    aktiv_kolcsonzes_mint_csere = db.query(models.KeszulekKolcsonzes).filter(
        models.KeszulekKolcsonzes.eredeti_keszulek_id == keszulek_id, models.KeszulekKolcsonzes.vege == None
    ).first()
    aktiv_kolcsonzes_mint_kolcsonzott = None
    if kolcsonzott_nalam:
        aktiv_kolcsonzes_mint_kolcsonzott = db.query(models.KeszulekKolcsonzes).filter(
            models.KeszulekKolcsonzes.keszulek_id == keszulek_id, models.KeszulekKolcsonzes.vege == None
        ).first()

    return templates.TemplateResponse(
        request=request,
        name="tuzvedelem_keszulek_adatlap.html",
        context={
            "user": current_user, "cegek": get_allowed_companies_list(current_user, db, "TUZVEDELEM"),
            "working_company_id": working_company_id,
            "keszulek": keszulek, "esedekesseg": esedekesseg,
            "ellenorzesek": ellenorzesek, "helyek": helyek, "karbantarto_cegek": karbantarto_cegek,
            "hosszabbitasok": hosszabbitasok,
            "szerkesztheto": _lehet_szerkeszteni(current_user, working_company_id, db),
            "kolcsonzott_nalam": kolcsonzott_nalam,
            "sajat_raktaron": sajat_raktaron,
            "karbantarto_raktarak": karbantarto_raktarak,
            "aktiv_kolcsonzes_mint_csere": aktiv_kolcsonzes_mint_csere,
            "aktiv_kolcsonzes_mint_kolcsonzott": aktiv_kolcsonzes_mint_kolcsonzott,
        }
    )


@router.post("/tuzvedelem/keszulek/{keszulek_id}/szervizbe-kuldes")
def keszulek_szervizbe_kuldese(
    keszulek_id: int,
    request: Request,
    csere_keszulek_id: str = Form(""),
    db: Session = Depends(get_db),
    current_user: models.User = Depends(get_current_user)
):
    """A készüléket 'Elszállítva karbantartásra' állapotba teszi, kiüríti a készenléti helyét,
    és - ha választottak - egy csere-készüléket (saját raktárból vagy egy karbantartó cég
    saját tulajdonú, kölcsönözhető készüléke) helyez a helyére."""
    working_company_id = get_working_company_id(current_user, request)
    if not _lehet_szerkeszteni(current_user, working_company_id, db):
        return RedirectResponse(url=f"/tuzvedelem/keszulek/{keszulek_id}", status_code=303)

    keszulek = db.query(models.TuzoltoKeszulek).filter(
        models.TuzoltoKeszulek.id == keszulek_id, models.TuzoltoKeszulek.company_id == working_company_id
    ).first()
    if not keszulek or not keszulek.jelenlegi_hely_id:
        return RedirectResponse(url="/tuzvedelem", status_code=303)

    # J-13 (v71): a nem szám csere-készülék azonosító korábban 500-at okozott (int() kivétel)
    csere_id_szam, csere_hiba = _id_vagy_hiba(csere_keszulek_id, "csere-készülék")
    if csere_hiba:
        return JSONResponse(status_code=400, content={"message": csere_hiba})

    regi_hely_id = keszulek.jelenlegi_hely_id
    ma = date.today()

    regi_tortenet = db.query(models.KeszulekTortenet).filter(
        models.KeszulekTortenet.keszulek_id == keszulek.id,
        models.KeszulekTortenet.keszenleti_hely_id == regi_hely_id,
        models.KeszulekTortenet.vege == None
    ).first()
    if regi_tortenet:
        regi_tortenet.vege = ma

    keszulek.jelenlegi_hely_id = None
    keszulek.statusz = "Elszállítva karbantartásra"

    if csere_id_szam is not None:
        csere = db.query(models.TuzoltoKeszulek).filter(
            models.TuzoltoKeszulek.id == csere_id_szam,
            models.TuzoltoKeszulek.jelenlegi_hely_id == None,
        ).first()
        # A csere-készülék vagy a saját raktáramból, vagy egy olyan karbantartó cégtől jöhet,
        # akivel aktív szerződésünk van - ezt itt is leellenőrizzük (nem csak a form kitöltésekor).
        if csere and (csere.company_id == working_company_id or _van_aktiv_szerzodes_a_keszulekhez(csere, working_company_id, db)):
            csere.jelenlegi_hely_id = regi_hely_id
            db.add(models.KeszulekTortenet(keszenleti_hely_id=regi_hely_id, keszulek_id=csere.id, kezdete=ma))
            if csere.company_id != working_company_id:
                db.add(models.KeszulekKolcsonzes(
                    keszulek_id=csere.id, keszenleti_hely_id=regi_hely_id, eredeti_keszulek_id=keszulek.id,
                    kezdete=ma, letrehozo_user_id=current_user.id,
                ))

    db.commit()
    return RedirectResponse(url=f"/tuzvedelem/keszulek/{keszulek_id}", status_code=303)


def _van_aktiv_szerzodes_a_keszulekhez(csere_keszulek, working_company_id: int, db: Session) -> bool:
    """Ellenőrzi, hogy a csere-készülék tulajdonos cége valóban aktív szerződéses
    karbantartója-e az üzemeltetőnek - nem csak bárki más cégének eszközét fogadjuk el."""
    kc = db.query(models.KarbantartoCeg).filter(
        models.KarbantartoCeg.company_id == working_company_id,
        models.KarbantartoCeg.tenant_company_id == csere_keszulek.company_id
    ).first()
    if not kc:
        return False
    return db.query(models.KarbantartoSzerzodes).filter(
        models.KarbantartoSzerzodes.karbantarto_ceg_id == kc.id, models.KarbantartoSzerzodes.vege == None
    ).first() is not None


@router.post("/tuzvedelem/keszulek/{keszulek_id}/visszaerkezes")
def keszulek_visszaerkezese(
    keszulek_id: int,
    request: Request,
    db: Session = Depends(get_db),
    current_user: models.User = Depends(get_current_user)
):
    """A szervizből visszaérkezett (saját) készüléket visszahelyezi az eredeti készenléti
    helyére, és lezárja az esetleges csere-készülék kölcsönzését (a csere visszakerül a
    karbantartóhoz / saját raktárba)."""
    working_company_id = get_working_company_id(current_user, request)
    if not _lehet_szerkeszteni(current_user, working_company_id, db):
        return RedirectResponse(url=f"/tuzvedelem/keszulek/{keszulek_id}", status_code=303)

    keszulek = db.query(models.TuzoltoKeszulek).filter(
        models.TuzoltoKeszulek.id == keszulek_id, models.TuzoltoKeszulek.company_id == working_company_id
    ).first()
    if not keszulek or keszulek.statusz != "Elszállítva karbantartásra":
        return RedirectResponse(url="/tuzvedelem", status_code=303)

    ma = date.today()
    kolcsonzes = db.query(models.KeszulekKolcsonzes).filter(
        models.KeszulekKolcsonzes.eredeti_keszulek_id == keszulek.id, models.KeszulekKolcsonzes.vege == None
    ).first()

    if kolcsonzes:
        cel_hely_id = kolcsonzes.keszenleti_hely_id
        kolcsonzes.vege = ma

        csere_tortenet = db.query(models.KeszulekTortenet).filter(
            models.KeszulekTortenet.keszulek_id == kolcsonzes.keszulek_id,
            models.KeszulekTortenet.keszenleti_hely_id == cel_hely_id,
            models.KeszulekTortenet.vege == None
        ).first()
        if csere_tortenet:
            csere_tortenet.vege = ma

        csere_keszulek = db.query(models.TuzoltoKeszulek).filter(models.TuzoltoKeszulek.id == kolcsonzes.keszulek_id).first()
        if csere_keszulek:
            csere_keszulek.jelenlegi_hely_id = None
    else:
        # Nem volt csere-készülék - a hely azóta is üresen állt, csak visszatesszük a sajátunkat.
        legutobbi_tortenet = db.query(models.KeszulekTortenet).filter(
            models.KeszulekTortenet.keszulek_id == keszulek.id, models.KeszulekTortenet.vege != None
        ).order_by(models.KeszulekTortenet.vege.desc()).first()
        cel_hely_id = legutobbi_tortenet.keszenleti_hely_id if legutobbi_tortenet else None

    if cel_hely_id:
        keszulek.jelenlegi_hely_id = cel_hely_id
        db.add(models.KeszulekTortenet(keszenleti_hely_id=cel_hely_id, keszulek_id=keszulek.id, kezdete=ma))

    keszulek.statusz = "Aktív"
    db.commit()
    return RedirectResponse(url=f"/tuzvedelem/keszulek/{keszulek_id}", status_code=303)


@router.post("/tuzvedelem/keszulek/{keszulek_id}/szerkesztes")
def keszulek_szerkesztese(
    keszulek_id: int,
    request: Request,
    hely_id: str = Form(""),
    statusz: str = Form(...),
    gyarto: str = Form(""),
    tipus_nev: str = Form(""),
    gyari_szam: str = Form(""),
    gyartasi_szabvany: str = Form(""),
    oltoanyag_tipus: str = Form(""),
    oe_ertek: str = Form(""),
    toltettomeg_kg: str = Form(""),
    nyp_ervenyesseg_datuma: str = Form(""),
    karbantarto_ceg_id: str = Form(""),
    db: Session = Depends(get_db),
    current_user: models.User = Depends(get_current_user)
):
    working_company_id = get_working_company_id(current_user, request)
    if not _lehet_szerkeszteni(current_user, working_company_id, db):
        return RedirectResponse(url=f"/tuzvedelem/keszulek/{keszulek_id}", status_code=303)

    keszulek = db.query(models.TuzoltoKeszulek).filter(
        models.TuzoltoKeszulek.id == keszulek_id, models.TuzoltoKeszulek.company_id == working_company_id
    ).first()
    if not keszulek:
        return RedirectResponse(url="/tuzvedelem", status_code=303)

    # J-13 (v71): a hivatkozott azonosítók és a státusz ellenőrzése MENTÉS ELŐTT (hibánál 400, semmi sem változik).
    # A jelenlegi státusz (pl. a rendszer által adott "Jóváhagyásra vár") változatlanul visszaküldhető.
    if statusz not in KESZULEK_STATUSZOK and statusz != keszulek.statusz:
        return JSONResponse(status_code=400, content={"message": "Érvénytelen készülék-státusz!"})
    uj_hely_id, uj_karbantarto_ceg_id, hivatkozas_hiba = keszulek_hivatkozasok_ellenorzese(db, working_company_id, hely_id, karbantarto_ceg_id)
    if hivatkozas_hiba:
        return JSONResponse(status_code=400, content={"message": hivatkozas_hiba})

    if uj_hely_id != keszulek.jelenlegi_hely_id:
        # Lezárjuk az előző hely-történetet, és nyitunk egy újat (audit-nyom a karbantartás/csere miatt)
        if keszulek.jelenlegi_hely_id:
            regi_tortenet = db.query(models.KeszulekTortenet).filter(
                models.KeszulekTortenet.keszulek_id == keszulek.id,
                models.KeszulekTortenet.keszenleti_hely_id == keszulek.jelenlegi_hely_id,
                models.KeszulekTortenet.vege == None
            ).first()
            if regi_tortenet:
                regi_tortenet.vege = date.today()
        if uj_hely_id:
            db.add(models.KeszulekTortenet(keszenleti_hely_id=uj_hely_id, keszulek_id=keszulek.id, kezdete=date.today()))
        keszulek.jelenlegi_hely_id = uj_hely_id

    keszulek.statusz = statusz
    keszulek.gyarto = gyarto or None
    keszulek.tipus_nev = tipus_nev or None
    keszulek.gyari_szam = gyari_szam or None
    keszulek.gyartasi_szabvany = gyartasi_szabvany or None
    keszulek.oltoanyag_tipus = oltoanyag_tipus or None
    keszulek.oe_ertek = oe_ertek or None
    keszulek.toltettomeg_kg = float(toltettomeg_kg) if toltettomeg_kg else None
    keszulek.nyp_ervenyesseg_datuma = _parse_date(nyp_ervenyesseg_datuma)
    keszulek.karbantarto_ceg_id = uj_karbantarto_ceg_id        # J-13 (v71): fent ellenőrizve

    db.commit()
    return RedirectResponse(url=f"/tuzvedelem/keszulek/{keszulek_id}", status_code=303)


@router.post("/tuzvedelem/keszulek/{keszulek_id}/jovahagyas")
def keszulek_jovahagyasa(
    keszulek_id: int,
    request: Request,
    db: Session = Depends(get_db),
    current_user: models.User = Depends(get_current_user)
):
    if current_user.role not in ["Admin"]:
        return JSONResponse(status_code=403, content={"message": "Csak Admin hagyhatja jóvá!"})

    working_company_id = get_working_company_id(current_user, request)
    # J-09 (v65): inaktív cégben / csak_olvasas fiókkal nincs jóváhagyás (a többi form-post is a beállítások oldalra dob vissza)
    if irasi_tiltas_oka(current_user, working_company_id, db):
        return RedirectResponse(url="/tuzvedelem/beallitasok", status_code=303)

    keszulek = db.query(models.TuzoltoKeszulek).filter(
        models.TuzoltoKeszulek.id == keszulek_id, models.TuzoltoKeszulek.company_id == working_company_id
    ).first()
    if keszulek:
        keszulek.jovahagyva = True
        if keszulek.statusz == "Jóváhagyásra vár":
            keszulek.statusz = "Aktív"
        db.commit()
    return RedirectResponse(url="/tuzvedelem/beallitasok", status_code=303)


@router.post("/tuzvedelem/keszulek/{keszulek_id}/ellenorzes-rogzitese")
async def ellenorzes_rogzitese(
    keszulek_id: int,
    request: Request,
    tipus: str = Form(...),
    datum: str = Form(...),
    negyedev: str = Form(""),
    karbantarto_ceg_id: str = Form(""),
    vegzo_neve: str = Form(""),
    szakvizsga_szam: str = Form(""),
    szakvizsga_ervenyesseg: str = Form(""),
    is_egyben_ellenorzes_is: str = Form(""),
    tapasztalt_hianyossag: str = Form(""),
    intezkedes: str = Form(""),
    megjegyzes: str = Form(""),
    fenykep: UploadFile = File(None),
    db: Session = Depends(get_db),
    current_user: models.User = Depends(get_current_user)
):
    working_company_id = get_working_company_id(current_user, request)
    if not _lehet_szerkeszteni(current_user, working_company_id, db):
        return RedirectResponse(url=f"/tuzvedelem/keszulek/{keszulek_id}", status_code=303)

    # OTSZ/TvMI szerint az üzemeltetői ellenőrzés bárki (betanított személy) által
    # végezhető, a karbantartás (alap/közép/teljes körű) viszont szakvizsgához kötött -
    # ezért csak Admin/Karbantartó rögzíthet ilyen bejegyzést.
    if tipus != "UZEMELTETOI_ELLENORZES" and current_user.role not in ["Admin", "Karbantartó"]:
        return JSONResponse(status_code=403, content={"message": "Karbantartás rögzítéséhez szakvizsgához kötött (Karbantartó) jogosultság szükséges!"})

    keszulek = db.query(models.TuzoltoKeszulek).filter(
        models.TuzoltoKeszulek.id == keszulek_id, models.TuzoltoKeszulek.company_id == working_company_id
    ).first()
    if not keszulek:
        return RedirectResponse(url="/tuzvedelem", status_code=303)

    # J-13 (v71): az ellenőrzés típusa fehérlistás, a karbantartó cég a munkakörnyezet cégéé kell legyen (hibánál 400, semmi sem mentődik)
    if tipus not in ELLENORZES_TIPUSOK:
        return JSONResponse(status_code=400, content={"message": "Érvénytelen ellenőrzés-típus!"})
    uj_karbantarto_ceg_id, hivatkozas_hiba = karbantarto_ceg_ellenorzese(db, working_company_id, karbantarto_ceg_id)
    if hivatkozas_hiba:
        return JSONResponse(status_code=400, content={"message": hivatkozas_hiba})

    datum_obj = _parse_date(datum) or date.today()
    egyben_ellenorzes = (is_egyben_ellenorzes_is == "on")

    try:
        fenykep_path = None
        if fenykep and getattr(fenykep, "filename", "") != "":
            if not is_safe_extension(fenykep.filename):
                return JSONResponse(status_code=400, content={"message": "Nem engedélyezett fájlformátum!"})
            mappa = f"uploads/{working_company_id}/tuzvedelem/{keszulek_id}"
            os.makedirs(mappa, exist_ok=True)
            safe_filename = sanitize_filename(fenykep.filename)
            kep_bytes = tomorit_kepet(await fenykep.read())
            if kep_bytes is None:
                return JSONResponse(status_code=400, content={"message": "A feltöltött fájl nem érvényes kép!"})
            safe_filename = safe_filename.rsplit(".", 1)[0] + ".jpg"
            file_loc = f"{mappa}/{datetime.now().strftime('%Y%m%d%H%M%S')}_{safe_filename}"
            with open(file_loc, "wb+") as f:
                f.write(kep_bytes)
            fenykep_path = "/" + file_loc

        bejegyzes = models.TuzvedelmiEllenorzes(
            keszulek_id=keszulek_id,
            tipus=tipus,
            datum=datum_obj,
            negyedev=int(negyedev) if negyedev else None,
            karbantarto_ceg_id=uj_karbantarto_ceg_id,        # J-13 (v71): fent ellenőrizve
            vegzo_neve=vegzo_neve or None,
            szakvizsga_szam=szakvizsga_szam or None,
            szakvizsga_ervenyesseg=_parse_date(szakvizsga_ervenyesseg),
            is_egyben_ellenorzes_is=egyben_ellenorzes,
            tapasztalt_hianyossag=tapasztalt_hianyossag or None,
            intezkedes=intezkedes or None,
            megjegyzes=megjegyzes or None,
            fenykep_path=fenykep_path,
            rogzito_user_id=current_user.id,
        )
        db.add(bejegyzes)

        if tipus == "ALAP":
            keszulek.utolso_alap_karbantartas = datum_obj
        elif tipus == "KOZEP":
            keszulek.utolso_kozep_karbantartas = datum_obj
            keszulek.utolso_alap_karbantartas = datum_obj
        elif tipus == "TELJES_KORU":
            keszulek.utolso_teljes_korbe = datum_obj
            keszulek.utolso_alap_karbantartas = datum_obj

        if tipus != "UZEMELTETOI_ELLENORZES" and egyben_ellenorzes:
            negyedev_szam = negyedev_szamitasa(datum_obj)
            db.add(models.TuzvedelmiEllenorzes(
                keszulek_id=keszulek_id, tipus="UZEMELTETOI_ELLENORZES", datum=datum_obj,
                negyedev=negyedev_szam, is_egyben_ellenorzes_is=True,
                megjegyzes="A karbantartással egyidejűleg elvégzett üzemeltetői ellenőrzés.",
                rogzito_user_id=current_user.id,
            ))

        db.commit()
    except (ValueError, OSError) as e:
        db.rollback()
        print(f"❌ Hibás adat vagy fájlművelet a tűzvédelmi mentésnél: {type(e).__name__}: {e}")
        return JSONResponse(status_code=400, content={"message": hiba_uzenet("Hibás adat vagy fájlművelet!", "E-TUZ-01")})

    return RedirectResponse(url=f"/tuzvedelem/keszulek/{keszulek_id}", status_code=303)


TUZVEDELEM_DOKUMENTUM_TIPUSOK = [
    "Fénykép",
    "Gyártói tanúsítvány / megfelelőségi nyilatkozat",
    "Számla / beszerzési bizonylat",
    "Karbantartási jegyzőkönyv (külső)",
    "Egyéb dokumentum",
]


@router.get("/tuzvedelem/keszulek/{keszulek_id}/fajlok")
def keszulek_fajljai(
    keszulek_id: int,
    request: Request,
    db: Session = Depends(get_db),
    current_user: models.User = Depends(get_current_user)
):
    working_company_id = get_working_company_id(current_user, request)
    keszulek = db.query(models.TuzoltoKeszulek).filter(
        models.TuzoltoKeszulek.id == keszulek_id, models.TuzoltoKeszulek.company_id == working_company_id
    ).first()
    if not keszulek:
        return JSONResponse(status_code=404, content={"message": "Készülék nem található!"})

    fajlok = db.query(models.TuzvedelemFajl).filter(
        models.TuzvedelemFajl.keszulek_id == keszulek_id
    ).order_by(models.TuzvedelemFajl.uploaded_at.desc()).all()

    return {
        "fajlok": [
            {
                "id": f.id,
                "file_path": f.file_path,
                "file_type": f.file_type,
                "uploaded_at": helyi_ido(f.uploaded_at),
                "filename": f.file_path.rsplit("/", 1)[-1],
            }
            for f in fajlok
        ]
    }


@router.post("/tuzvedelem/keszulek/{keszulek_id}/fajl-feltoltes")
async def keszulek_fajl_feltoltese(
    keszulek_id: int,
    request: Request,
    file_type: str = Form(...),
    file: UploadFile = File(...),
    db: Session = Depends(get_db),
    current_user: models.User = Depends(get_current_user)
):
    working_company_id = get_working_company_id(current_user, request)
    if not _lehet_szerkeszteni(current_user, working_company_id, db):
        return JSONResponse(status_code=403, content={"message": "Nincs jogosultságod fájl feltöltésére!"})

    if file_type not in TUZVEDELEM_DOKUMENTUM_TIPUSOK:
        return JSONResponse(status_code=400, content={"message": "Érvénytelen dokumentumtípus!"})

    if not is_safe_extension(file.filename):
        return JSONResponse(status_code=400, content={"message": "Nem engedélyezett fájlformátum!"})

    keszulek = db.query(models.TuzoltoKeszulek).filter(
        models.TuzoltoKeszulek.id == keszulek_id, models.TuzoltoKeszulek.company_id == working_company_id
    ).first()
    if not keszulek:
        return JSONResponse(status_code=404, content={"message": "Készülék nem található!"})

    try:
        mappa = f"uploads/{working_company_id}/tuzvedelem/{keszulek_id}"
        os.makedirs(mappa, exist_ok=True)
        safe_filename = sanitize_filename(file.filename)

        if file_type == "Fénykép":
            if not any(file.filename.lower().endswith(ext) for ext in (".jpg", ".jpeg", ".png", ".gif", ".webp")):
                return JSONResponse(status_code=400, content={"message": "Fénykép típushoz csak képfájl tölthető fel!"})
            kep_bytes = tomorit_kepet(await file.read())
            if kep_bytes is None:
                return JSONResponse(status_code=400, content={"message": "A feltöltött fájl nem érvényes kép!"})
            safe_filename = safe_filename.rsplit(".", 1)[0] + ".jpg"
            file_location = f"{mappa}/{datetime.now().strftime('%Y%m%d%H%M%S%f')}_{safe_filename}"
            with open(file_location, "wb+") as f:
                f.write(kep_bytes)
        else:
            if not file.filename.lower().endswith(".pdf"):
                return JSONResponse(status_code=400, content={"message": "Dokumentum csak PDF formátumban tölthető fel!"})
            fejresz = file.file.read(8)
            file.file.seek(0)
            if not tartalom_illeszkedik_e_kiterjesztesre(file.filename, fejresz):
                return JSONResponse(status_code=400, content={"message": "A feltöltött fájl tartalma nem egyezik a kiterjesztésével!"})
            if not safe_filename.lower().endswith(".pdf"):
                safe_filename += ".pdf"
            file_location = f"{mappa}/{datetime.now().strftime('%Y%m%d%H%M%S%f')}_{safe_filename}"
            with open(file_location, "wb+") as f:
                shutil.copyfileobj(file.file, f)

        uj_fajl = models.TuzvedelemFajl(
            keszulek_id=keszulek_id,
            file_path="/" + file_location,
            file_type=file_type,
        )
        db.add(uj_fajl)
        db.commit()
        return JSONResponse(status_code=200, content={"message": "Sikeres feltöltés!"})
    except Exception as e:
        print(f"❌ Hiba a tűzvédelmi fájlfeltöltés során: {type(e).__name__}: {e}")
        return JSONResponse(status_code=400, content={"message": hiba_uzenet("Hiba a feltöltés során!", "E-TUZ-02")})


@router.delete("/tuzvedelem/fajl/{fajl_id}")
def keszulek_fajl_torlese(
    fajl_id: int,
    request: Request,
    db: Session = Depends(get_db),
    current_user: models.User = Depends(get_current_user)
):
    if current_user.role not in ["Admin"]:
        return JSONResponse(status_code=403, content={"message": "Nincs jogod dokumentum törlésére!"})

    working_company_id = get_working_company_id(current_user, request)

    if not is_company_active(working_company_id, db):
        return JSONResponse(status_code=403, content={"message": "Ez a cég inaktív státuszú, törlés nem lehetséges!"})

    if current_user.csak_olvasas:
        return JSONResponse(status_code=403, content={"message": "Csak megtekintési jogosultsággal rendelkezel, szerkesztés nem lehetséges!"})
    fajl = db.query(models.TuzvedelemFajl).join(models.TuzoltoKeszulek).filter(
        models.TuzvedelemFajl.id == fajl_id,
        models.TuzoltoKeszulek.company_id == working_company_id
    ).first()
    if not fajl:
        return JSONResponse(status_code=404, content={"message": "Fájl nem található!"})

    try:
        fs_path = fajl.file_path.lstrip("/")
        if os.path.exists(fs_path):
            os.remove(fs_path)
    except OSError:
        pass

    db.delete(fajl)
    db.commit()
    return JSONResponse(status_code=200, content={"message": "Fájl törölve!"})


@router.get("/uploads/{company_id}/tuzvedelem/{keszulek_id}/{filename}")
def tuzvedelem_fajl_kiszolgalas(
    company_id: int,
    keszulek_id: int,
    filename: str,
    db: Session = Depends(get_db),
    current_user: models.User = Depends(get_current_user)
):
    keszulek = db.query(models.TuzoltoKeszulek).filter(
        models.TuzoltoKeszulek.id == keszulek_id,
        models.TuzoltoKeszulek.company_id == company_id
    ).first()

    van_hozzaferese = is_company_allowed(current_user, company_id)
    if not keszulek or not van_hozzaferese:
        raise HTTPException(status_code=status.HTTP_403_FORBIDDEN, detail="Nincs jogosultságod a kért dokumentum eléréséhez!")

    safe_filename = sanitize_filename(filename)
    file_path = f"uploads/{company_id}/tuzvedelem/{keszulek_id}/{safe_filename}"

    if not os.path.exists(file_path):
        raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="A keresett fájl nem található a szerveren.")

    return FileResponse(file_path)


def negyedev_szamitasa(datum: date) -> int:
    return (datum.month - 1) // 3 + 1


@router.post("/tuzvedelem/szakvizsga")
def uj_szakvizsga(
    request: Request,
    user_id: int = Form(...),
    kategoria_kod: int = Form(...),
    bizonyitvany_szam: str = Form(""),
    kiallito: str = Form(""),
    ervenyesseg_datuma: str = Form(""),
    db: Session = Depends(get_db),
    current_user: models.User = Depends(get_current_user)
):
    working_company_id = get_working_company_id(current_user, request)
    if current_user.role not in ["Admin"] or not _lehet_szerkeszteni(current_user, working_company_id, db):
        return RedirectResponse(url="/tuzvedelem/beallitasok", status_code=303)

    cel_user = db.query(models.User).filter(
        models.User.id == user_id, models.User.company_id == working_company_id
    ).first()
    if not cel_user:
        return RedirectResponse(url="/tuzvedelem/beallitasok", status_code=303)

    db.add(models.Szakvizsga(
        user_id=user_id, kategoria_kod=kategoria_kod,
        bizonyitvany_szam=bizonyitvany_szam or None, kiallito=kiallito or None,
        ervenyesseg_datuma=_parse_date(ervenyesseg_datuma),
    ))
    db.commit()
    return RedirectResponse(url="/tuzvedelem/beallitasok", status_code=303)


@router.delete("/tuzvedelem/szakvizsga/{szakvizsga_id}")
def torol_szakvizsga(
    szakvizsga_id: int,
    request: Request,
    db: Session = Depends(get_db),
    current_user: models.User = Depends(get_current_user)
):
    if current_user.role not in ["Admin"]:
        return JSONResponse(status_code=403, content={"message": "Csak Admin!"})

    working_company_id = get_working_company_id(current_user, request)

    if not is_company_active(working_company_id, db):
        return JSONResponse(status_code=403, content={"message": "Ez a cég inaktív státuszú, törlés nem lehetséges!"})

    if current_user.csak_olvasas:
        return JSONResponse(status_code=403, content={"message": "Csak megtekintési jogosultsággal rendelkezel, szerkesztés nem lehetséges!"})
    szakvizsga = db.query(models.Szakvizsga).join(models.User).filter(
        models.Szakvizsga.id == szakvizsga_id, models.User.company_id == working_company_id
    ).first()
    if szakvizsga:
        db.delete(szakvizsga)
        db.commit()
    return JSONResponse(status_code=200, content={"message": "Törölve."})


@router.post("/tuzvedelem/karbantarto-ceg")
def uj_karbantarto_ceg(
    request: Request,
    nev: str = Form(...),
    szekhely: str = Form(""),
    okf_azonosito_jel: str = Form(""),
    szerzodes_kezdete: str = Form(""),
    db: Session = Depends(get_db),
    current_user: models.User = Depends(get_current_user)
):
    if current_user.role not in ["Admin"]:
        return RedirectResponse(url="/tuzvedelem/beallitasok", status_code=303)

    working_company_id = get_working_company_id(current_user, request)
    # J-09 (v65): ld. keszulek_jovahagyasa
    if irasi_tiltas_oka(current_user, working_company_id, db):
        return RedirectResponse(url="/tuzvedelem/beallitasok", status_code=303)

    ceg = models.KarbantartoCeg(
        company_id=working_company_id, nev=nev, szekhely=szekhely or None,
        okf_azonosito_jel=okf_azonosito_jel or None,
    )
    db.add(ceg)
    db.commit()
    db.refresh(ceg)

    kezdete_datum = _parse_date(szerzodes_kezdete) or date.today()
    db.add(models.KarbantartoSzerzodes(
        karbantarto_ceg_id=ceg.id, kezdete=kezdete_datum, letrehozo_user_id=current_user.id,
    ))
    db.commit()
    return RedirectResponse(url="/tuzvedelem/beallitasok", status_code=303)


@router.post("/tuzvedelem/karbantarto-ceg/{ceg_id}/szerzodes-lezarasa")
def karbantarto_szerzodes_lezarasa(
    ceg_id: int,
    request: Request,
    db: Session = Depends(get_db),
    current_user: models.User = Depends(get_current_user)
):
    if current_user.role not in ["Admin"]:
        return JSONResponse(status_code=403, content={"message": "Csak Admin!"})

    working_company_id = get_working_company_id(current_user, request)
    # J-09 (v65): a szerződés lezárása is szerkesztés
    tiltas = irasi_tiltas_oka(current_user, working_company_id, db)
    if tiltas:
        return JSONResponse(status_code=403, content={"message": IRASI_TILTAS_UZENETEK[tiltas]})
    ceg = db.query(models.KarbantartoCeg).filter(
        models.KarbantartoCeg.id == ceg_id, models.KarbantartoCeg.company_id == working_company_id
    ).first()
    if not ceg:
        return JSONResponse(status_code=404, content={"message": "Karbantartó cég nem található!"})

    aktiv_szerzodes = db.query(models.KarbantartoSzerzodes).filter(
        models.KarbantartoSzerzodes.karbantarto_ceg_id == ceg_id, models.KarbantartoSzerzodes.vege == None
    ).first()
    if aktiv_szerzodes:
        aktiv_szerzodes.vege = date.today()
        db.commit()
    return JSONResponse(status_code=200, content={"message": "Szerződés lezárva."})


@router.post("/tuzvedelem/karbantarto-ceg/{ceg_id}/szerzodes-inditasa")
def karbantarto_szerzodes_inditasa(
    ceg_id: int,
    request: Request,
    kezdete: str = Form(""),
    db: Session = Depends(get_db),
    current_user: models.User = Depends(get_current_user)
):
    if current_user.role not in ["Admin"]:
        return JSONResponse(status_code=403, content={"message": "Csak Admin!"})

    working_company_id = get_working_company_id(current_user, request)
    # J-09 (v65): a szerződés indítása is szerkesztés
    tiltas = irasi_tiltas_oka(current_user, working_company_id, db)
    if tiltas:
        return JSONResponse(status_code=403, content={"message": IRASI_TILTAS_UZENETEK[tiltas]})
    ceg = db.query(models.KarbantartoCeg).filter(
        models.KarbantartoCeg.id == ceg_id, models.KarbantartoCeg.company_id == working_company_id
    ).first()
    if not ceg:
        return JSONResponse(status_code=404, content={"message": "Karbantartó cég nem található!"})

    mar_van_aktiv = db.query(models.KarbantartoSzerzodes).filter(
        models.KarbantartoSzerzodes.karbantarto_ceg_id == ceg_id, models.KarbantartoSzerzodes.vege == None
    ).first()
    if mar_van_aktiv:
        return JSONResponse(status_code=400, content={"message": "Már van aktív szerződés ennél a karbantartó cégnél!"})

    kezdete_datum = _parse_date(kezdete) or date.today()
    db.add(models.KarbantartoSzerzodes(
        karbantarto_ceg_id=ceg_id, kezdete=kezdete_datum, letrehozo_user_id=current_user.id,
    ))
    db.commit()
    return JSONResponse(status_code=200, content={"message": "Szerződés elindítva."})


@router.delete("/tuzvedelem/karbantarto-ceg/{ceg_id}")
def torol_karbantarto_ceg(
    ceg_id: int,
    request: Request,
    db: Session = Depends(get_db),
    current_user: models.User = Depends(get_current_user)
):
    if current_user.role not in ["Admin"]:
        return JSONResponse(status_code=403, content={"message": "Csak Admin!"})

    working_company_id = get_working_company_id(current_user, request)

    if not is_company_active(working_company_id, db):
        return JSONResponse(status_code=403, content={"message": "Ez a cég inaktív státuszú, törlés nem lehetséges!"})

    if current_user.csak_olvasas:
        return JSONResponse(status_code=403, content={"message": "Csak megtekintési jogosultsággal rendelkezel, szerkesztés nem lehetséges!"})
    ceg = db.query(models.KarbantartoCeg).filter(
        models.KarbantartoCeg.id == ceg_id, models.KarbantartoCeg.company_id == working_company_id
    ).first()
    if ceg:
        ceg.aktiv = False
        db.commit()
    return JSONResponse(status_code=200, content={"message": "Törölve."})


def _naplo_adatok(telephely_id: int, ev: int, working_company_id: int, db: Session):
    """A napló nézethez és a PDF-hez közösen összeállított adatok: a telephely
    készenléti helyei, a rajtuk jelenleg kihelyezett készülékek, és az adott évi
    negyedéves üzemeltetői ellenőrzések dátumai készülékenként."""
    telephely = db.query(models.TuzvedelmiTelephely).filter(
        models.TuzvedelmiTelephely.id == telephely_id, models.TuzvedelmiTelephely.company_id == working_company_id
    ).first()
    if not telephely:
        return None, None, None, None

    helyek = db.query(models.KeszenletiHely).filter(
        models.KeszenletiHely.telephely_id == telephely_id, models.KeszenletiHely.company_id == working_company_id
    ).all()
    hely_ids = [h.id for h in helyek]

    keszulekek = db.query(models.TuzoltoKeszulek).filter(
        models.TuzoltoKeszulek.jelenlegi_hely_id.in_(hely_ids)
    ).all() if hely_ids else []
    keszulek_ids = [k.id for k in keszulekek]

    negyedevek_map = {}
    legutobbi_esemeny = None
    if keszulek_ids:
        esemenyek = db.query(models.TuzvedelmiEllenorzes).filter(
            models.TuzvedelmiEllenorzes.keszulek_id.in_(keszulek_ids)
        ).order_by(models.TuzvedelmiEllenorzes.datum.desc()).all()

        for e in esemenyek:
            if e.tipus == "UZEMELTETOI_ELLENORZES" and e.negyedev and e.datum.year == ev:
                negyedevek_map.setdefault(e.keszulek_id, {})[e.negyedev] = e.datum

        karbantartasok = [e for e in esemenyek if e.tipus in ("ALAP", "KOZEP", "TELJES_KORU")]
        if karbantartasok:
            e = karbantartasok[0]
            legutobbi_esemeny = {
                "tipus": {"ALAP": "alap", "KOZEP": "közép", "TELJES_KORU": "teljes körű"}[e.tipus],
                "datum": e.datum.strftime("%Y-%m-%d") if e.datum else "-",
                "ceg_nev": e.karbantarto_ceg.nev if e.karbantarto_ceg else "-",
                "ceg_szekhely": e.karbantarto_ceg.szekhely if e.karbantarto_ceg else "-",
                "vegzo_neve": e.vegzo_neve or "-",
                "szakvizsga_szam": e.szakvizsga_szam or "-",
                "szakvizsga_ervenyesseg": e.szakvizsga_ervenyesseg.strftime("%Y-%m-%d") if e.szakvizsga_ervenyesseg else "-",
            }

    hely_keszulek_parok = []
    for hely in helyek:
        keszulek = next((k for k in keszulekek if k.jelenlegi_hely_id == hely.id), None)
        hely_keszulek_parok.append((hely, keszulek))

    return telephely, hely_keszulek_parok, negyedevek_map, legutobbi_esemeny


@router.get("/tuzvedelem/naplo/{telephely_id}/{ev}", response_class=HTMLResponse)
def naplo_nezet(
    telephely_id: int, ev: int, request: Request,
    db: Session = Depends(get_db),
    current_user: models.User = Depends(get_current_user)
):
    working_company_id = get_working_company_id(current_user, request)
    telephely, hely_keszulek_parok, negyedevek_map, legutobbi_esemeny = _naplo_adatok(telephely_id, ev, working_company_id, db)
    if not telephely:
        return RedirectResponse(url="/tuzvedelem", status_code=303)

    naplo = db.query(models.TuzvedelmiNaplo).filter(
        models.TuzvedelmiNaplo.telephely_id == telephely_id, models.TuzvedelmiNaplo.ev == ev
    ).first()

    return templates.TemplateResponse(
        request=request,
        name="tuzvedelem_naplo.html",
        context={
            "user": current_user, "cegek": get_allowed_companies_list(current_user, db, "TUZVEDELEM"),
            "working_company_id": working_company_id,
            "telephely": telephely, "ev": ev,
            "hely_keszulek_parok": hely_keszulek_parok, "negyedevek_map": negyedevek_map,
            "legutobbi_esemeny": legutobbi_esemeny, "naplo": naplo,
        }
    )


@router.get("/tuzvedelem/naplo/{telephely_id}/{ev}/pdf")
def naplo_pdf(
    telephely_id: int, ev: int, request: Request,
    db: Session = Depends(get_db),
    current_user: models.User = Depends(get_current_user)
):
    working_company_id = get_working_company_id(current_user, request)
    telephely, hely_keszulek_parok, negyedevek_map, legutobbi_esemeny = _naplo_adatok(telephely_id, ev, working_company_id, db)
    if not telephely:
        return RedirectResponse(url="/tuzvedelem", status_code=303)

    ceg = db.query(models.Company).filter(models.Company.id == working_company_id).first()

    pdf = TuzvedelmiNaploPDF(telephely, ceg, ev, legutobbi_esemeny)
    pdf.alias_nb_pages()
    pdf.add_page()

    for hely, keszulek in hely_keszulek_parok:
        if not keszulek:
            pdf.sor_hozzaadasa([hely.hely_leiras, "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-"])
            continue

        negyedevek = negyedevek_map.get(keszulek.id, {})
        if keszulek.oltoanyag_tipus == "CO2":
            megjegyzes = f"NYP érv.: {keszulek.nyp_ervenyesseg_datuma.strftime('%Y-%m-%d') if keszulek.nyp_ervenyesseg_datuma else '-'}"
        else:
            megjegyzes = "-"

        pdf.sor_hozzaadasa([
            hely.hely_leiras,
            keszulek.tipus_nev or "-",
            keszulek.gyari_szam or "-",
            keszulek.gyartas_datum.strftime("%Y-%m-%d") if keszulek.gyartas_datum else "-",
            keszulek.oe_ertek or "-",
            keszulek.utolso_alap_karbantartas.strftime("%Y-%m-%d") if keszulek.utolso_alap_karbantartas else "-",
            keszulek.utolso_kozep_karbantartas.strftime("%Y-%m-%d") if keszulek.utolso_kozep_karbantartas else "-",
            keszulek.utolso_teljes_korbe.strftime("%Y-%m-%d") if keszulek.utolso_teljes_korbe else "-",
            megjegyzes,
            negyedevek.get(1, "-") if not isinstance(negyedevek.get(1), date) else negyedevek[1].strftime("%m-%d"),
            negyedevek.get(2, "-") if not isinstance(negyedevek.get(2), date) else negyedevek[2].strftime("%m-%d"),
            negyedevek.get(3, "-") if not isinstance(negyedevek.get(3), date) else negyedevek[3].strftime("%m-%d"),
            negyedevek.get(4, "-") if not isinstance(negyedevek.get(4), date) else negyedevek[4].strftime("%m-%d"),
            "-", "-",
        ])

    pdf_bytes = bytes(pdf.output())
    return StreamingResponse(
        io.BytesIO(pdf_bytes), media_type="application/pdf",
        headers={"Content-Disposition": f"inline; filename=tuzvedelmi_naplo_{telephely.nev}_{ev}.pdf"}
    )


@router.post("/tuzvedelem/naplo/{telephely_id}/{ev}/lezaras")
def naplo_lezarasa(
    telephely_id: int, ev: int, request: Request,
    hianyossag_indoklas: str = Form(""),
    db: Session = Depends(get_db),
    current_user: models.User = Depends(get_current_user)
):
    if current_user.role not in ["Admin"]:
        return JSONResponse(status_code=403, content={"message": "Csak Admin zárhatja le a naplót!"})

    working_company_id = get_working_company_id(current_user, request)
    # J-09 (v65): a napló lezárása visszafordíthatatlan írás - inaktív cégben / csak_olvasas fiókkal tilos
    tiltas = irasi_tiltas_oka(current_user, working_company_id, db)
    if tiltas:
        return JSONResponse(status_code=403, content={"message": IRASI_TILTAS_UZENETEK[tiltas]})
    telephely, hely_keszulek_parok, negyedevek_map, _ = _naplo_adatok(telephely_id, ev, working_company_id, db)
    if not telephely:
        return JSONResponse(status_code=404, content={"message": "Telephely nem található!"})

    # J-11 (v74): a már lezárt napló nem zárható le újra - a lezárás dátuma, a lezáró és a (hiányosság-)indoklás véglegesen
    # rögzül, nem írható felül (korábban minden újabb lezárás felülírta őket).
    korabbi_naplo = db.query(models.TuzvedelmiNaplo).filter(
        models.TuzvedelmiNaplo.telephely_id == telephely_id, models.TuzvedelmiNaplo.ev == ev
    ).first()
    if korabbi_naplo and korabbi_naplo.lezarva:
        return JSONResponse(status_code=409, content={"message": (
            f"A napló már le van zárva ({korabbi_naplo.lezaras_datuma}), újralezárás nem lehetséges!")})

    hianyzo = []
    for hely, keszulek in hely_keszulek_parok:
        if not keszulek:
            continue
        negyedevek = negyedevek_map.get(keszulek.id, {})
        if len(negyedevek) < 4:
            hianyzo.append(f"{hely.hely_leiras}: hiányzó negyedéves ellenőrzés")
        van_e_evi_karbantartas = any(
            d and d.year == ev for d in [keszulek.utolso_alap_karbantartas, keszulek.utolso_kozep_karbantartas, keszulek.utolso_teljes_korbe]
        )
        if not van_e_evi_karbantartas:
            hianyzo.append(f"{hely.hely_leiras}: nincs rögzítve karbantartás {ev}-ben")

    # Ha hiányos a napló, csak akkor zárható le, ha az Admin egy dátumbélyeges hiányosság-
    # indoklást is rögzít - visszamenőleges (hamisított) bejegyzés helyett a hiány marad
    # dokumentált, örökre látható a naplóban/PDF-en.
    if hianyzo and not hianyossag_indoklas.strip():
        return JSONResponse(status_code=400, content={
            "message": "A napló hiányos. Indoklás megadásával hiányosan is lezárható.",
            "hianyos": True,
            "hianyzo_lista": hianyzo,
        })

    naplo = korabbi_naplo
    if not naplo:
        naplo = models.TuzvedelmiNaplo(telephely_id=telephely_id, ev=ev)
        db.add(naplo)

    naplo.lezarva = True
    naplo.lezaras_datuma = date.today()
    naplo.lezaro_user_id = current_user.id
    if hianyzo:
        naplo.hianyosan_zarva = True
        naplo.hianyossag_indoklas = (
            f"[{date.today().strftime('%Y-%m-%d')}, {current_user.username}] {hianyossag_indoklas.strip()}\n\n"
            f"Rendszer által észlelt hiányosságok:\n- " + "\n- ".join(hianyzo)
        )
    db.commit()
    return RedirectResponse(url=f"/tuzvedelem/naplo/{telephely_id}/{ev}", status_code=303)
