import csv
import io
import math
import os
import re
import shutil
from datetime import date, datetime, timezone

from fastapi import APIRouter, Request, Depends, Form, status, Response
from fastapi.responses import HTMLResponse, RedirectResponse, JSONResponse
from fastapi.encoders import jsonable_encoder
from sqlalchemy import or_, cast, String, case, func
from sqlalchemy.orm import Session

import models
from security import EMELOGEP_KEZELO_SZEREPKOROK, EMELOGEP_SZAKMAI_SZEREPKOROK
from database import get_db
from security import (
    is_safe_extension, safe_json_for_script, sanitize_filename, get_current_user,
    get_working_company_id, apply_user_data_scope_filter, is_machine_allowed,
    get_allowed_companies_list, is_company_active, get_azonositas_mod, require_modul,
    irasi_tiltas_oka, IRASI_TILTAS_LISTA_URL,
    is_rendszeradminisztrator, sugo_engedelyezve, tartalom_illeszkedik_e_kiterjesztesre
)
from msz_logic import (
    recompute_msz_classification, compute_vizsgalati_esedekesseg, gep_hianyzo_kotelezo_mezok,
    get_vizsgalati_datum_kotelezo_mod
)
from licenc_utils import licenc_tullepne_uj_gepnel
from image_utils import tomorit_kepet, kep_e
from routers.ai_scan import ai_szkenneles_engedelyezve
from berles_utils import is_gep_allowed_berlo_szamara, aktiv_berlet, berelt_gep_idk_a_ceghez
import partner_ceg_utils as pcu
from templates_env import templates
from naplo_utils import naploz

router = APIRouter(dependencies=[Depends(require_modul("EMELOGEP"))])


def _configs_json(configs) -> str:
    """A géptípus-konfigurációkat (kötelező/rejtett mezők, kaméleon-mezőnevek, kezelői
    munkahely szükségessége) JSON-ban szolgáltatja az index.html-nek - a lap CSP miatt
    külső fájlban lévő szkriptje ebből építi fel kliens oldalon a configMap/hiddenConfigMap/
    typeConfigs/kezeloMezoMap objektumokat, amiket korábban Jinja for-ciklus generált be
    közvetlenül a beágyazott <script>-be."""
    return safe_json_for_script([
        {
            "geptipus": c.geptipus,
            "kotelezo_mezok": [s.strip() for s in (c.kotelezo_mezok or "").split(",")],
            "rejtett_mezok": [s.strip() for s in (c.rejtett_mezok or "").split(",")],
            "egyedi_1_nev": c.egyedi_1_nev or "",
            "egyedi_2_nev": c.egyedi_2_nev or "",
            "egyedi_3_nev": c.egyedi_3_nev or "",
            "kezeloi_munkahely_szukseges": bool(c.kezeloi_munkahely_szukseges),
        }
        for c in configs
    ])


def keres_duplikatum_gepet(db: Session, company_id: int, gyari_szam: str, leltari_szam: str, kizart_gep_id: int = None):
    """Megkeresi, hogy a cégnél van-e már másik gép ugyanazzal a gyári számmal vagy belső
    azonosítóval (leltári szám) - kis/nagybetűtől és szóközöktől függetlenül. Üres és "-"
    (nincs adat jelölő) értékekre nem keres (egy cégnél több gépnek is lehet üres/"-" a
    gyári/leltári száma - enélkül két, valójában különböző gyári számú gép is "ütköző
    duplikátumnak" látszott, ha mindkettőnek "-" volt a leltári száma)."""
    gyari_szam = str(gyari_szam).strip() if gyari_szam is not None else ""
    leltari_szam = str(leltari_szam).strip() if leltari_szam is not None else ""
    if gyari_szam == "-":
        gyari_szam = ""
    if leltari_szam == "-":
        leltari_szam = ""
    if not gyari_szam and not leltari_szam:
        return None

    feltetelek = []
    if gyari_szam:
        feltetelek.append(models.Machine.gyari_szam.ilike(gyari_szam))
    if leltari_szam:
        feltetelek.append(models.Machine.leltari_szam.ilike(leltari_szam))

    query = db.query(models.Machine).filter(
        models.Machine.company_id == company_id,
        or_(*feltetelek)
    )
    if kizart_gep_id:
        query = query.filter(models.Machine.id != kizart_gep_id)

    return query.first()


# --- TÍPUS ALAPÚ ADATÁTVÉTEL ÚJ GÉPNÉL (v79) -------------------------------------------------------------------------------------------
# Új gép felvételekor, ha a cégnél már van azonos gyártójú és típusú gép, az űrlap felajánlja ezek TÍPUS-szintű műszaki adatainak átvételét
# (Miklós kérése). Csak a TÍPUSRA jellemző adatok vehetők át; a gépre egyedi adat (gyári szám, leltári szám, dátumok, üzemóra, telephely,
# státusz, bérlet, rendszám, QR, megnevezés/helyszín, megjegyzés, egyedi mezők) SOHA. Az átvételt az űrlapon át kell nézni és jóvá kell hagyni;
# a szerver mindkettőt ellenőrzi és az eseménynaplóba (AuditLog, a gép eseményei közé) beírja. Leírás: docs/TIPUS_ATVETEL.md
TIPUS_ATVETEL_MEZOK = (
    # (űrlapmező / Machine-oszlop, megjelenített név, logikai-e)
    ("geptipus", "Géptípus", False),
    ("teherbiras", "Teherbírás", False),
    ("emelesi_magassag", "Emelési magasság", False),
    ("fesztav_gemhossz", "Fesztáv / gémhossz", False),
    ("meghajtas", "Meghajtás", False),
    ("teljesitmeny", "Teljesítmény", False),
    ("is_teherfelvevo", "Nem emelőgép (teherfelvevő)", True),
    ("kezelo_egyutt_emelkedik", "Kezelő együtt emelkedik", True),
    ("kezeloi_munkahely_magassaga", "Kezelői munkahely magassága (mm)", False),
)
TIPUS_ATVETEL_KERESES_MAX = 200


def _tipus_norm(ertek) -> str:
    """Gyártó / típus összevetéshez: szélső és többszörös szóközök összevonva, kis-nagybetű-független."""
    return re.sub(r"\s+", " ", str(ertek or "").strip()).upper()


def tipus_egyezo_gepek(db: Session, company_id: int, gyarto, tipus, geptipus=None) -> list:
    """A cég azon gépei, amelyeknek a gyártója ÉS típusa (szóköz- és kis-nagybetű-függetlenül) egyezik. Üres vagy "-" gyártó/típusra nincs
    találat. Sorrend: előbb az azonos géptípusúak, azon belül a legújabb gép elöl. A hozzáférési szűrést (is_machine_allowed) a hívó végzi."""
    gy, ti = _tipus_norm(gyarto), _tipus_norm(tipus)
    if not gy or not ti or gy == "-" or ti == "-":
        return []
    # Az összevetés PYTHONBAN történik (nem SQL upper()/lower()-rel): az SQLite upper()/lower() csak az ASCII betűket kezeli, így az ékezetes
    # nagybetű/kisbetű különbség (pl. "Köhler" / "KÖHLER") SQL-ben nem egyeznék. Csak három oszlopot kérünk le, a találatokat azonosító szerint töltjük be.
    azonositok = [
        sor.id for sor in db.query(models.Machine.id, models.Machine.gyarto, models.Machine.tipus).filter(
            models.Machine.company_id == company_id, models.Machine.gyarto.isnot(None), models.Machine.tipus.isnot(None)
        ).order_by(models.Machine.id.desc()).all()
        if _tipus_norm(sor.gyarto) == gy and _tipus_norm(sor.tipus) == ti
    ][:TIPUS_ATVETEL_KERESES_MAX]
    if not azonositok:
        return []
    betoltott = {g.id: g for g in db.query(models.Machine).filter(models.Machine.id.in_(azonositok)).all()}
    talalatok = [betoltott[i] for i in azonositok if i in betoltott]       # legújabb elöl
    gt = _tipus_norm(geptipus)
    if gt:
        talalatok.sort(key=lambda g: 0 if _tipus_norm(g.geptipus) == gt else 1)     # stabil rendezés: az id szerinti csökkenő sorrend megmarad
    return talalatok


def tipus_atveheto_adatok(gep) -> dict:
    """A forrásgép átvehető, NEM üres típus-adatai: {mező: érték}. Szöveg: levágott szöveg; logikai: True (a hamis az alapérték, nincs mit átvenni)."""
    adatok = {}
    for kulcs, _nev, logikai in TIPUS_ATVETEL_MEZOK:
        ertek = getattr(gep, kulcs, None)
        if logikai:
            if ertek:
                adatok[kulcs] = True
        elif ertek is not None and str(ertek).strip() not in ("", "-"):
            adatok[kulcs] = str(ertek).strip()
    return adatok


def _tipus_urlap_ertek(form_data, kulcs: str, logikai: bool):
    """Az űrlapon beküldött érték a forrásgép adatával összevethető alakban (logikai: True / None)."""
    if logikai:
        return True if form_data.get(kulcs) == "on" else None
    ertek = str(form_data.get(kulcs) or "").strip()
    return ertek or None


def _tipus_ertek_szoveg(ertek) -> str:
    return "igen" if ertek is True else ("-" if ertek is None else str(ertek))


def tipus_atvetel_forras(db: Session, current_user, working_company_id: int, form_data):
    """A mentéskor beküldött átvétel-adatok ellenőrzése (CSAK új gépnél hívjuk). Visszatérés: (forrásgép | None, hibaválasz | None).
    Nincs forrás-azonosító -> nincs átvétel. Hiba (400, semmi sem mentődik): érvénytelen / idegen cégű / nem látható forrás, a forrás gyártója-típusa
    nem egyezik a mentett gépével, vagy hiányzik az átvett adatok átnézésének jóváhagyása."""
    nyers = (form_data.get("adat_forras_gep_id") or "").strip()
    if not nyers:
        return None, None
    forras = None
    if nyers.isdigit():
        forras = db.query(models.Machine).filter(
            models.Machine.id == int(nyers), models.Machine.company_id == working_company_id
        ).first()
    if not forras or not is_machine_allowed(forras, current_user) or current_user.role not in EMELOGEP_KEZELO_SZEREPKOROK:
        return None, JSONResponse(status_code=400, content={"message": "Az adatátvétel forrásgépe érvénytelen vagy nem elérhető!"})
    if _tipus_norm(forras.gyarto) != _tipus_norm(form_data.get("gyarto")) or _tipus_norm(forras.tipus) != _tipus_norm(form_data.get("tipus")):
        return None, JSONResponse(status_code=400, content={"message": "Az adatátvétel forrásgépének gyártója/típusa nem egyezik a mentett gépével!"})
    if form_data.get("adat_atnezve") != "igen":
        return None, JSONResponse(status_code=400, content={
            "message": "Az átvett adatok átnézését jóvá kell hagyni (Ellenőrizd, hogy az áthozott adatok erre a gépre is megfelelőek-e)!"})
    return forras, None


def naploz_tipus_atvetel(db: Session, current_user, gep, forras, form_data):
    """Az átvétel két eseménye a GÉP eseményei közé (nem commitol; a gép mentésével egy tranzakcióban kerül be):
    1) "Adatok átvétele típus alapján" - a forrásgép és az átvett (a mentett értékkel egyező) adatok;
    2) "Átvett adatok jóváhagyva" - mely átvett adatot módosította a felhasználó az átvétel után (a SZERVER számolja a forrásgép és a beküldött
       érték különbségéből, nem a kliens állításából), és hogy a felhasználó átnézte."""
    forras_adatok = tipus_atveheto_adatok(forras)
    atvett, eltero = [], []
    for kulcs, nev, logikai in TIPUS_ATVETEL_MEZOK:
        if kulcs not in forras_adatok:
            continue
        mentett = _tipus_urlap_ertek(form_data, kulcs, logikai)
        if mentett == forras_adatok[kulcs]:
            atvett.append(f"{nev}: {_tipus_ertek_szoveg(mentett)}")
        else:
            eltero.append(f"{nev}: {_tipus_ertek_szoveg(forras_adatok[kulcs])} → {_tipus_ertek_szoveg(mentett)}")
    forras_nev = f"#{forras.id} {forras.megnevezes or '-'} ({(forras.gyarto or '-').strip()} {(forras.tipus or '-').strip()})"
    naploz(db, current_user, None, "Adatok átvétele típus alapján", regi=f"Forrásgép: {forras_nev}",
           uj="Átvett: " + ("; ".join(atvett) if atvett else "-"), machine_id=gep.id)
    naploz(db, current_user, None, "Átvett adatok jóváhagyva", regi="Eltérés a forrásgéptől: " + ("; ".join(eltero) if eltero else "nincs"),
           uj="Átnézve, jóváhagyva", machine_id=gep.id)


@router.get("/gep/tipus-ajanlat")
def gep_tipus_ajanlat(
    request: Request,
    gyarto: str = "",
    tipus: str = "",
    geptipus: str = "",
    db: Session = Depends(get_db),
    current_user: models.User = Depends(get_current_user)
):
    """ÚJ gép felvételekor (az űrlap hívja, ha a gyártó és a típus ki van töltve): van-e a cégnél azonos gyártójú és típusú gép, amelynek az adatait
    át lehet venni. CSAK OLVAS. Csak annak adunk ajánlatot, aki új gépet felvihet (kezelő szerepkör, nem csak olvasó, aktív cég), és csak olyan
    gépről, amelyet látnia is szabad (is_machine_allowed) - így egy szűkített hatókörű felhasználó nem szivárogtat ki másik telephely gépéből."""
    working_company_id = get_working_company_id(current_user, request)
    if (current_user.csak_olvasas or current_user.role not in EMELOGEP_KEZELO_SZEREPKOROK
            or (current_user.role == "Admin" and working_company_id == 1)
            or not is_company_active(working_company_id, db)):
        return {"van": False}

    talalatok = [g for g in tipus_egyezo_gepek(db, working_company_id, gyarto, tipus, geptipus) if is_machine_allowed(g, current_user)]
    if not talalatok:
        return {"van": False}
    forras = talalatok[0]
    return {
        "van": True,
        "db": len(talalatok),
        "forras": {
            "id": forras.id,
            "megnevezes": forras.megnevezes,
            "gyarto": forras.gyarto,
            "tipus": forras.tipus,
            "telephely": forras.telephely.nev if forras.telephely else None,
            "adatok": tipus_atveheto_adatok(forras),
        },
        "mezok": [{"kulcs": k, "nev": n, "logikai": l} for k, n, l in TIPUS_ATVETEL_MEZOK],
    }


def get_lehetseges_fo_gepek(working_company_id, db, kizart_gep_id=None):
    """A lehetséges 'fő gép' választék: a cég aktív, önálló (nem tartozék) gépei, ÉS a cégnél
    jelenleg aktív/jóváhagyott bérlettel kihelyezett ("bérelt nálam") gépek is (2026-10-10-i
    user-jelzés: egy bérelt gép meglévő tartozékai, vagy egy saját eszköz a bérelt géphez, eddig
    nem volt felvehető, mert ez a lista kizárólag a saját gépekre szűkített). Szigorú 2-szintű
    hierarchia - egy már tartozéknak jelölt gép nem választható fő gépnek."""
    berelt_gep_idk = berelt_gep_idk_a_ceghez(working_company_id, db)
    sajat_vagy_berelt = or_(models.Machine.company_id == working_company_id, models.Machine.id.in_(berelt_gep_idk)) \
        if berelt_gep_idk else models.Machine.company_id == working_company_id
    query = db.query(models.Machine).filter(
        sajat_vagy_berelt,
        models.Machine.fo_gep_id == None,
        models.Machine.statusz.notin_(["Végleg kivonva/Selejtezve", "Eladva", "Bérleti idő lejárt / Visszaadva"])
    )
    if kizart_gep_id:
        query = query.filter(models.Machine.id != kizart_gep_id)
    return query.order_by(models.Machine.megnevezes).all()


@router.get("/gep-naptar/{machine_id}")
def gep_naptar(
    request: Request,
    machine_id: int,
    db: Session = Depends(get_db),
    current_user: models.User = Depends(get_current_user)
):
    working_company_id = get_working_company_id(current_user, request)
    berelt_gep_idk = berelt_gep_idk_a_ceghez(working_company_id, db)
    gep = db.query(models.Machine).filter(
        models.Machine.id == machine_id,
        or_(models.Machine.company_id == working_company_id, models.Machine.id.in_(berelt_gep_idk))
    ).first()

    if not gep or not (is_machine_allowed(gep, current_user) or is_gep_allowed_berlo_szamara(gep, current_user, db)):
        return JSONResponse(status_code=404, content={"message": "A keresett gép nem található!"})

    config = db.query(models.MachineTypeConfig).filter(
        models.MachineTypeConfig.company_id == gep.company_id,
        models.MachineTypeConfig.geptipus == gep.geptipus
    ).first()
    datum_kotelezo_mod = get_vizsgalati_datum_kotelezo_mod(working_company_id, db)

    return {
        "gep_nev": gep.megnevezes or "Ismeretlen gép",
        "is_teherfelvevo": bool(gep.is_teherfelvevo),
        "csoportszam": gep.calculated_csoportszam,
        "esedekessegek": compute_vizsgalati_esedekesseg(gep, date.today(), config, datum_kotelezo_mod)
    }


@router.get("/gep/duplikatum-ellenorzes")
def gep_duplikatum_ellenorzes(
    request: Request,
    gyari_szam: str = "",
    leltari_szam: str = "",
    machine_id: int = None,
    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 gép ugyanazzal a gyári számmal
    vagy belső azonosítóval (leltári szám) - a gépfelvételi/szerkesztési űrlap ezt hívja meg
    mentés előtt, hogy figyelmeztethessen és megerősítést kérhessen egyezés esetén."""
    working_company_id = get_working_company_id(current_user, request)

    talalat = keres_duplikatum_gepet(db, working_company_id, gyari_szam, leltari_szam, kizart_gep_id=machine_id)

    if not talalat:
        return {"duplikatum": False}

    # v29 (GET-átvizsgálás S-3): a duplikátum-ellenőrzés a CÉG összes gépét átnézi (ez kell ahhoz, hogy a figyelmeztetés ne maradjon
    # el), de a TALÁLAT RÉSZLETEIT csak annak adjuk, aki azt a gépet egyébként is láthatná (telephely/gép szintű hozzáférés).
    # Különben egy szűkített hatókörű felhasználó a figyelmeztetésből megtudhatná egy másik telephely gépének adatait.
    # Ilyenkor csak a TÉNY derül ki ("létezik ilyen gép"), a részletek nem. A mentés előtti ellenőrzés ettől működőképes marad.
    if not is_machine_allowed(talalat, current_user):
        return {"duplikatum": True, "talalat": {"korlatozott": True}}

    return {
        "duplikatum": True,
        "talalat": {
            "id": talalat.id,
            "megnevezes": talalat.megnevezes,
            "gyarto": talalat.gyarto,
            "tipus": talalat.tipus,
            "gyari_szam": talalat.gyari_szam,
            "leltari_szam": talalat.leltari_szam,
            "telephely": talalat.telephely.nev if talalat.telephely else None,
            "statusz": talalat.statusz,
        }
    }


# --- GÉPFELVITEL ÉS SZERKESZTÉS ---
@router.get("/uj-gep", response_class=HTMLResponse)
def uj_gep_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)

    if current_user.role not in EMELOGEP_KEZELO_SZEREPKOROK:      # J-25 (v76): pozitív lista
        return RedirectResponse(url="/lista")

    if current_user.role == "Admin" and working_company_id == 1:
        return RedirectResponse(url="/lista")

    if not is_company_active(working_company_id, db):
        return RedirectResponse(url="/lista?inaktiv_ceg=1")

    if current_user.csak_olvasas:
        return RedirectResponse(url="/lista?csak_olvasas=1")

    telephelyek = db.query(models.Site).filter(models.Site.company_id == working_company_id).all()

    gyartok_records = db.query(models.Dictionary).filter(
        models.Dictionary.company_id == working_company_id,
        models.Dictionary.kategoria == "Gyarto"
    ).all()

    gyartok = []
    for r in gyartok_records:
        gyartok.append(r.ertek)

    tipusok_records = db.query(models.Dictionary).filter(
        models.Dictionary.company_id == working_company_id,
        models.Dictionary.kategoria == "Tipus"
    ).all()

    tipusok = []
    for r in tipusok_records:
        tipusok.append(r.ertek)

    configs = db.query(models.MachineTypeConfig).filter(models.MachineTypeConfig.company_id == working_company_id).all()

    # --- ÚJ: EDDIGI GÉP MODELLEK (TÍPUSOK) KIGYŰJTÉSE (AUTOMATA DEDUPLIKÁCIÓVAL) ---
    eddigi_tipusok_records = db.query(models.Machine.tipus).filter(
        models.Machine.company_id == working_company_id,
        models.Machine.tipus != None
    ).distinct().all()

    eddigi_tipusok = []
    for r in eddigi_tipusok_records:
        if r[0].strip() != "":
            eddigi_tipusok.append(r[0].strip())
    # ------------------------------------------------------------------------------

    # --- ÚJ (2026-10-10-i user-kérés): a "Helyszín" mezőnél is felkínáljuk a cégnél már
    # használt értékeket, pontosan az "eddigi_tipusok" mintáját követve (automatikus,
    # admin-kezelés nélküli, a Machine tábla tényleges tartalmából élőben számolt lista). ---
    eddigi_helyszinek_records = db.query(models.Machine.megnevezes).filter(
        models.Machine.company_id == working_company_id,
        models.Machine.megnevezes != None
    ).distinct().all()

    eddigi_helyszinek = []
    for r in eddigi_helyszinek_records:
        if r[0].strip() != "":
            eddigi_helyszinek.append(r[0].strip())
    # ------------------------------------------------------------------------------

    cegek = get_allowed_companies_list(current_user, db, "EMELOGEP")
    lehetseges_fo_gepek = get_lehetseges_fo_gepek(working_company_id, db)
    azonositas_mod = get_azonositas_mod(working_company_id, db)

    uzemelteto_ceg = db.query(models.Company).filter(models.Company.id == working_company_id).first()
    uzemelteto_nev = uzemelteto_ceg.nev if uzemelteto_ceg else ""

    return templates.TemplateResponse(
        request=request,
        name="index.html",
        context={
            "gep_json": "null",
            "user": current_user,
            "telephelyek": telephelyek,
            "gyartok": gyartok,
            "tipusok": tipusok,
            "configs": configs,
            "configs_json": _configs_json(configs),
            "manual_datum_engedelyezve": bool(current_user.jog_datum_szerkesztes),
            "cegek": cegek,
            "working_company_id": working_company_id,
            "eddigi_tipusok": eddigi_tipusok,
            "eddigi_helyszinek": eddigi_helyszinek,
            "lehetseges_fo_gepek": lehetseges_fo_gepek,
            "tartozekok": [],
            "azonositas_mod": azonositas_mod,
            "uzemelteto_nev_json": safe_json_for_script(uzemelteto_nev),
            "tulajdonos_nev_json": safe_json_for_script(None),
            "sugo_e": sugo_engedelyezve(working_company_id, db),
        }
    )


@router.get("/szerkesztes/{uuid}", response_class=HTMLResponse)
def szerkesztes(
    request: Request,
    uuid: str,
    db: Session = Depends(get_db),
    current_user: models.User = Depends(get_current_user)
):
    if current_user.role not in EMELOGEP_SZAKMAI_SZEREPKOROK:      # J-25 (v76): pozitív lista
        return RedirectResponse(url="/lista")

    working_company_id = get_working_company_id(current_user, request)
    berelt_gep_idk = berelt_gep_idk_a_ceghez(working_company_id, db)

    gep = db.query(models.Machine).filter(
        models.Machine.uuid == uuid,
        or_(models.Machine.company_id == working_company_id, models.Machine.id.in_(berelt_gep_idk))
    ).first()

    if not gep:
        return RedirectResponse(url="/lista")

    if gep.statusz in ["Végleg kivonva/Selejtezve", "Eladva", "Bérleti idő lejárt / Visszaadva"]:
        return RedirectResponse(url="/lista")

    if not is_machine_allowed(gep, current_user) and not is_gep_allowed_berlo_szamara(gep, current_user, db):
        return RedirectResponse(url="/lista")

    if not is_company_active(working_company_id, db):
        return RedirectResponse(url="/lista?inaktiv_ceg=1")

    if current_user.csak_olvasas:
        return RedirectResponse(url="/lista?csak_olvasas=1")

    telephelyek = db.query(models.Site).filter(models.Site.company_id == working_company_id).all()

    gyartok_records = db.query(models.Dictionary).filter(
        models.Dictionary.company_id == working_company_id,
        models.Dictionary.kategoria == "Gyarto"
    ).all()

    gyartok = []
    for r in gyartok_records:
        gyartok.append(r.ertek)

    tipusok_records = db.query(models.Dictionary).filter(
        models.Dictionary.company_id == working_company_id,
        models.Dictionary.kategoria == "Tipus"
    ).all()

    tipusok = []
    for r in tipusok_records:
        tipusok.append(r.ertek)

    configs = db.query(models.MachineTypeConfig).filter(models.MachineTypeConfig.company_id == working_company_id).all()

    # --- ÚJ: EDDIGI GÉP MODELLEK KIGYŰJTÉSE A SZERKESZTÉSHEZ IS ---
    eddigi_tipusok_records = db.query(models.Machine.tipus).filter(
        models.Machine.company_id == working_company_id,
        models.Machine.tipus != None
    ).distinct().all()

    eddigi_tipusok = []
    for r in eddigi_tipusok_records:
        if r[0].strip() != "":
            eddigi_tipusok.append(r[0].strip())
    # ------------------------------------------------------------------------------

    eddigi_helyszinek_records = db.query(models.Machine.megnevezes).filter(
        models.Machine.company_id == working_company_id,
        models.Machine.megnevezes != None
    ).distinct().all()

    eddigi_helyszinek = []
    for r in eddigi_helyszinek_records:
        if r[0].strip() != "":
            eddigi_helyszinek.append(r[0].strip())

    cegek = get_allowed_companies_list(current_user, db, "EMELOGEP")
    lehetseges_fo_gepek = get_lehetseges_fo_gepek(working_company_id, db, kizart_gep_id=gep.id)
    azonositas_mod = get_azonositas_mod(working_company_id, db)

    # --- Bérbeadás (kihelyezés) - csak a gép tényleges tulajdonosánál (saját gép, nem bérelt-nálam) ---
    # FONTOS: a berbeado_e_ez_a_ceg egy TISZTA tulajdonosi ellenőrzés is (lásd lent a
    # tulajdonos_nev QR-matrica logikát) - a bérbeadási JOGOSULTSÁGOT (Company.berbeadhat,
    # rendszeradmin által cégenként engedélyezhető) egy KÜLÖN flag jelzi, hogy ez a
    # jogosultsági szűkítés csak a bérbeadás UI/route-ot érintse, ne a tulajdonos-kijelzést.
    berbeado_e_ez_a_ceg = (gep.company_id == working_company_id)
    berbeadas_engedelyezve = berbeado_e_ez_a_ceg and bool(gep.ceg and gep.ceg.berbeadhat)
    berlo_cegek_valaszthato = []
    aktiv_berlet_obj = None
    berlet_elozmenyek = []
    if berbeadas_engedelyezve:
        # ÚJ (2026-10-06-i user-jelzés): korábban ITT MINDEN aktív cég fel lett sorolva név
        # szerint - ez önmagában adatszivárgás volt (bármely cég megtudhatta, kik mások
        # használják a rendszert). Mostantól csak a kódos meghívással ("Partner cégek",
        # routers/partner_cegek.py) már összekapcsolt partner-cégek választhatók.
        berlo_cegek_valaszthato = [c for c in pcu.partner_cegek_listaja(db, working_company_id) if c.aktiv]
    if berbeado_e_ez_a_ceg:
        aktiv_berlet_obj = aktiv_berlet(gep, db)
        berlet_elozmenyek = db.query(models.BerletiIdoszak).filter(
            models.BerletiIdoszak.machine_id == gep.id
        ).order_by(models.BerletiIdoszak.kezdete.desc()).all()

    # --- ÚJ: Smart QR matrica fejléce - üzemeltető (a jelenlegi munkakörnyezet cége) és,
    # bérgépnél, a tulajdonos (rendszeren belüli bérbeadó cég neve, vagy - külsős, nem
    # rendszerhasználó bérbeadónál - a szabadon rögzített "Bérbeadó neve" mező). ---
    uzemelteto_ceg = db.query(models.Company).filter(models.Company.id == working_company_id).first()
    uzemelteto_nev = uzemelteto_ceg.nev if uzemelteto_ceg else ""
    if gep.berelt_eszkoz:
        tulajdonos_nev = gep.berbeado_neve or "Külsős bérbeadó (nincs megadva a neve)"
    elif not berbeado_e_ez_a_ceg:
        tulajdonos_nev = gep.ceg.nev if gep.ceg else None
    else:
        tulajdonos_nev = None

    # MAGAS (2026-10-03-i külső biztonsági audit, 2. kör): korábban jsonable_encoder(gep) a nyers
    # ORM-objektumot kódolta, ami - ha a függvényben ADDIG betöltött (pl. a fenti gep.ceg eléréssel
    # már lazy-loadolt) relationship ÉRINTVE lett volna - rekurzívan a kapcsolódó tábla(k) MINDEN
    # oszlopát is beleírta volna a kliensnek küldött JSON-ba (pl. egy később hozzáadott gep.X.user
    # elérés akár jelszó-hash-t is kiszivárogtathatott volna). Mostantól csak a Machine tábla
    # SAJÁT oszlopaiból épül a dict (models.Machine.__table__.columns) - ez explicit módon
    # SOHA nem tartalmaz relationship-objektumot, függetlenül attól, mit ér el a jövőben a
    # függvény ezen a sor felett.
    gep_mezok = {oszlop.name: getattr(gep, oszlop.name) for oszlop in models.Machine.__table__.columns}

    return templates.TemplateResponse(
        request=request,
        name="index.html",
        context={
            "gep_json": safe_json_for_script(jsonable_encoder(gep_mezok)),
            "uuid": gep.uuid,
            "user": current_user,
            "telephelyek": telephelyek,
            "gyartok": gyartok,
            "tipusok": tipusok,
            "configs": configs,
            "configs_json": _configs_json(configs),
            "manual_datum_engedelyezve": bool(current_user.jog_datum_szerkesztes),
            "cegek": cegek,
            "working_company_id": working_company_id,
            "eddigi_tipusok": eddigi_tipusok,
            "eddigi_helyszinek": eddigi_helyszinek,
            "lehetseges_fo_gepek": lehetseges_fo_gepek,
            "azonositas_mod": azonositas_mod,
            "tartozekok": gep.tartozekok,
            "berbeado_e_ez_a_ceg": berbeado_e_ez_a_ceg,
            "berbeadas_engedelyezve": berbeadas_engedelyezve,
            "berlo_cegek_valaszthato": berlo_cegek_valaszthato,
            "aktiv_berlet_obj": aktiv_berlet_obj,
            "berlet_elozmenyek": berlet_elozmenyek,
            "uzemelteto_nev_json": safe_json_for_script(uzemelteto_nev),
            "tulajdonos_nev_json": safe_json_for_script(tulajdonos_nev),
            "sugo_e": sugo_engedelyezve(working_company_id, db),
        }
    )


@router.get("/gep-adatlap/{uuid}", response_class=HTMLResponse)
def gep_adatlap(
    request: Request,
    uuid: str,
    db: Session = Depends(get_db),
    current_user: models.User = Depends(get_current_user)
):
    """Egyszerűsített, csak-olvasható nézet a gép tárolt adatairól - a /szerkesztes
    oldallal ellentétben Felhasználó (Gépkezelő) szerepkörnek és csak_olvasas fiókoknak
    is elérhető, mert nincs mentés/módosítás, csak megtekintés."""
    working_company_id = get_working_company_id(current_user, request)
    berelt_gep_idk = berelt_gep_idk_a_ceghez(working_company_id, db)

    gep = db.query(models.Machine).filter(
        models.Machine.uuid == uuid,
        or_(models.Machine.company_id == working_company_id, models.Machine.id.in_(berelt_gep_idk))
    ).first()

    if not gep:
        return RedirectResponse(url="/lista")

    if not is_machine_allowed(gep, current_user) and not is_gep_allowed_berlo_szamara(gep, current_user, db):
        return RedirectResponse(url="/lista")

    # ÚJ (2026-10-10-i user-jelzés): l. /lista ugyanerről - a bérelt gép adatlapja ne a bérbeadó
    # saját telephelyét/"Készenléti hely" adatát mutassa, ha a bérlő jóváhagyáskor megadta a sajátját.
    gep.megjelenitett_telephely = gep.telephely
    gep.megjelenitett_keszenleti_hely = gep.megnevezes
    if gep.company_id != working_company_id:
        berlet = aktiv_berlet(gep, db)
        if berlet and berlet.jovahagyva:
            if berlet.berlo_site_id:
                gep.megjelenitett_telephely = berlet.berlo_site
            if berlet.berlo_keszenleti_hely:
                gep.megjelenitett_keszenleti_hely = berlet.berlo_keszenleti_hely

    config = db.query(models.MachineTypeConfig).filter(
        models.MachineTypeConfig.company_id == working_company_id,
        models.MachineTypeConfig.geptipus == gep.geptipus
    ).first()
    rejtett_mezok = set()
    if config and config.rejtett_mezok:
        rejtett_mezok = set(m.strip() for m in config.rejtett_mezok.split(",") if m.strip())

    return templates.TemplateResponse(
        request=request,
        name="gep_adatlap.html",
        context={
            "gep": gep,
            "user": current_user,
            "config": config,
            "rejtett_mezok": rejtett_mezok,
            "working_company_id": working_company_id,
            "sugo_e": sugo_engedelyezve(working_company_id, db),
        }
    )


@router.post("/gep-mentese")
async def gep_mentese(
    request: Request,
    db: Session = Depends(get_db),
    current_user: models.User = Depends(get_current_user),
    emelesi_magassag: str = Form(default=""),
    fesztav_gemhossz: str = Form(default=""),
    meghajtas: str = Form(default=""),
    teljesitmeny: str = Form(default=""),
    egyedi_1: str = Form(default=""),
    egyedi_2: str = Form(default=""),
    egyedi_3: str = Form(default=""),
    ):

    form_data = await request.form()

    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ú, gép adatai nem menthetők!"}
        )

    if current_user.csak_olvasas:
        return JSONResponse(
            status_code=403,
            content={"message": "Csak megtekintési jogosultsággal rendelkezel, szerkesztés nem lehetséges!"}
        )

    if current_user.role not in EMELOGEP_SZAKMAI_SZEREPKOROK:      # J-25 (v76): pozitív lista
        return JSONResponse(
            status_code=403,
            content={"message": "Nincs jogosultságod a gép mentésére!"}
        )

    if current_user.role in ("Emelőgép szakértő", "Emelőgép vizsgáló"):
        # Emelőgép szakértő/vizsgáló csak akkor szerkeszthet MEGLÉVŐ gépet, ha ezt a jogát
        # egyedileg engedélyezték - új gép felvitelére ilyenkor sem jogosult.
        if not (current_user.jog_gep_szerkesztes and form_data.get("machine_id")):
            return JSONResponse(
                status_code=403,
                content={"message": "Nincs jogosultságod a gép mentésére!"}
            )

    if current_user.role == "Admin" and working_company_id == 1:
        return JSONResponse(
            status_code=403,
            content={"message": "A Mester Cégbe nem rögzíthető emelőgép!"}
        )

    def parse_date(date_str):
        if date_str:
            return datetime.strptime(date_str, "%Y-%m-%d").date()
        return None

    # J-13 (v69): a telephely a gép cégéhez (working_company_id) tartozzon - eddig bármilyen azonosítót elfogadott, így idegen
    # cég telephelye is a géphez köthető volt (a neve megjelent a listában / PDF-ben). Hibánál 400, és SEMMI sem mentődik
    # (az ellenőrzés a gép létrehozása/módosítása ELŐTT fut).
    site_id_nyers = (form_data.get("site_id") or "").strip()
    uj_site_id = None
    if site_id_nyers:
        telephely = None
        if site_id_nyers.isdigit():
            telephely = db.query(models.Site).filter(
                models.Site.id == int(site_id_nyers), models.Site.company_id == working_company_id
            ).first()
        if not telephely:
            return JSONResponse(status_code=400, content={"message": "A kiválasztott telephely érvénytelen vagy nem ehhez a céghez tartozik!"})
        uj_site_id = telephely.id

    machine_id = form_data.get("machine_id")
    is_new = False
    atvetel_forras = None

    if machine_id:
        gep = db.query(models.Machine).filter(
            models.Machine.id == int(machine_id),
            models.Machine.company_id == working_company_id
        ).first()

        if not gep or not is_machine_allowed(gep, current_user):
            return RedirectResponse(url="/lista")
    else:
        ceg = db.query(models.Company).filter(models.Company.id == working_company_id).first()
        tullepne, jelenlegi, limit = licenc_tullepne_uj_gepnel(ceg, db)
        if tullepne:
            return JSONResponse(
                status_code=403,
                content={"message": f"Elérted a licenced szerinti maximális gépszámot ({jelenlegi}/{limit})! A bővítéshez keresd az üzemeltetőt."}
            )

        # Védelem: ne engedjen automatikusan menteni azonos gyári számmal/belső azonosítóval
        # (leltári szám) - kivéve, ha a felhasználó a figyelmeztetés után kifejezetten
        # megerősítette (l. index.html JS: mentés előtti duplikátum-ellenőrzés + confirm()).
        if form_data.get("duplikatum_megerositve") != "igen":
            duplikatum = keres_duplikatum_gepet(
                db, working_company_id, form_data.get("gyari_szam"), form_data.get("leltari_szam")
            )
            if duplikatum:
                return JSONResponse(
                    status_code=409,
                    content={
                        "message": "Már létezik gép ezzel a gyári számmal vagy belső azonosítóval!",
                        "duplikatum": True,
                        "talalat": {
                            "megnevezes": duplikatum.megnevezes,
                            "gyarto": duplikatum.gyarto,
                            "tipus": duplikatum.tipus,
                            "gyari_szam": duplikatum.gyari_szam,
                            "leltari_szam": duplikatum.leltari_szam,
                            "telephely": duplikatum.telephely.nev if duplikatum.telephely else None,
                        }
                    }
                )

        # v79: típus alapú adatátvétel - a forrás és a jóváhagyás ellenőrzése a gép létrehozása ELŐTT (hibánál 400, semmi sem mentődik)
        atvetel_forras, atvetel_hiba = tipus_atvetel_forras(db, current_user, working_company_id, form_data)
        if atvetel_hiba:
            return atvetel_hiba

        gep = models.Machine(company_id=working_company_id)
        db.add(gep)
        is_new = True

    eredeti_adatok = {}
    if not is_new:
        for col in gep.__table__.columns:
            eredeti_adatok[col.name] = getattr(gep, col.name)

    # Alapadatok mentése
    gep.site_id = uj_site_id        # J-13 (v69): fent ellenőrizve (a gép cégének telephelye vagy None)

    gep.megnevezes = form_data.get("megnevezes")
    gep.gyarto = form_data.get("gyarto")
    gep.tipus = form_data.get("tipus")
    gep.gyari_szam = form_data.get("gyari_szam")
    gep.leltari_szam = form_data.get("leltari_szam")
    gep.geptipus = form_data.get("geptipus")
    gep.teherbiras = form_data.get("teherbiras")
    gep.alapadat_megjegyzes = form_data.get("alapadat_megjegyzes")

    # Műszaki és speciális paraméterek (géptípusonként dinamikusan megjelenő mezők) - ezek eddig
    # csak a függvény paraméterei között léteztek, a gep objektumra sosem kerültek rá, ezért
    # kitöltés után sem mentődtek el.
    gep.emelesi_magassag = emelesi_magassag or None
    gep.fesztav_gemhossz = fesztav_gemhossz or None
    gep.meghajtas = meghajtas or None
    gep.teljesitmeny = teljesitmeny or None
    gep.egyedi_1 = egyedi_1 or None
    gep.egyedi_2 = egyedi_2 or None
    gep.egyedi_3 = egyedi_3 or None

    # --- ÚJ: FŐ GÉP / TARTOZÉK KAPCSOLAT MENTÉSE (szigorú 2-szintű hierarchia) ---
    # 2026-10-10-i user-jelzés: a jelölt fő gép a saját cég gépei MELLETT a cégnél jelenleg
    # aktív/jóváhagyott bérlettel kihelyezett ("bérelt nálam") gép is lehet - l. get_lehetseges_fo_gepek.
    jelolt_fo_gep_id_nyers = form_data.get("fo_gep_id")
    if jelolt_fo_gep_id_nyers and (is_new or not gep.tartozekok):
        jelolt_fo_gep_id = int(jelolt_fo_gep_id_nyers)
        if jelolt_fo_gep_id != gep.id:
            berelt_gep_idk_jelolt = berelt_gep_idk_a_ceghez(working_company_id, db)
            jelolt = db.query(models.Machine).filter(
                models.Machine.id == jelolt_fo_gep_id,
                or_(models.Machine.company_id == working_company_id, models.Machine.id.in_(berelt_gep_idk_jelolt)),
                models.Machine.fo_gep_id == None
            ).first()
            gep.fo_gep_id = jelolt.id if jelolt else None
        else:
            gep.fo_gep_id = None
    else:
        gep.fo_gep_id = None
    # ----------------------------------------

    # --- ÚJ: TEHERFELVEVŐ KAPCSOLÓ MENTÉSE ---
    if form_data.get("is_teherfelvevo") == "on":
        gep.is_teherfelvevo = True
    else:
        gep.is_teherfelvevo = False
    # ----------------------------------------

    # --- ÚJ: BÉRELT ESZKÖZ MENTÉSE (külső, a rendszert nem használó tulajdonostól bérelt gép) ---
    if form_data.get("berelt_eszkoz") == "on":
        gep.berelt_eszkoz = True
        gep.berbeado_neve = form_data.get("berbeado_neve") or None
        gep.berbeado_elerhetoseg = form_data.get("berbeado_elerhetoseg") or None
        gep.berlet_lejarat_datum = parse_date(form_data.get("berlet_lejarat_datum"))
    else:
        gep.berelt_eszkoz = False
        gep.berbeado_neve = None
        gep.berbeado_elerhetoseg = None
        gep.berlet_lejarat_datum = None
    # ----------------------------------------

    # Dátumok mentése - meglévő gépnél csak akkor engedjük felülírni, ha a felhasználónak
    # egyedileg (Admin/Emelőgép szakértő/Emelőgép vizsgáló/Emelőgép ügyintéző szerepkörnél) engedélyezve van a kézi
    # dátumszerkesztés - új gép felvitelénél a dátumok mindig szabadon megadhatók.
    uj_datumok = {
        "gyartas_datum": parse_date(form_data.get("gyartas_datum")),
        "uzembe_helyezes_datum": parse_date(form_data.get("uzembe_helyezes_datum")),
        "szerkezeti_vizsgalat_datum": parse_date(form_data.get("szerkezeti_vizsgalat_datum")),
        "fovizsgalat_datum": parse_date(form_data.get("fovizsgalat_datum")),
        "biztonsagi_vizsgalat_datum": parse_date(form_data.get("biztonsagi_vizsgalat_datum")),
    }

    # JAVÍTÁS (2026-09-23): Teherfelvevő eszközöknél a szerkesztőlap (toggleTeherfelvevo(),
    # l. static/js/pages/index.js) a Szerkezeti/Fővizsgálat mezőket a beküldés előtt MINDIG
    # kiüríti (mert ezeknél az eszközöknél külön dátumként nem értelmezhető - l. a
    # msz_constants.py compute_vizsgalati_esedekesseg()-ben ma javított Joker szabályt is).
    # Enélkül a lenti feltétel nélküli hozzárendelés minden egyes mentéskor NULL-ra írta volna
    # felül ezt a két mezőt a ténylegesen korábban rögzített dátum helyett - VALÓS ADATVESZTÉS
    # -, akkor is, ha a felhasználó egyáltalán nem ezeket a mezőket akarta módosítani. Ezért
    # teherfelvevő eszközöknél a beküldött (mindig üres) értéket figyelmen kívül hagyjuk, és
    # megőrizzük, ami eddig a gépen szerepelt (új gépnél ez None, ami rendben van).
    if gep.is_teherfelvevo:
        uj_datumok["szerkezeti_vizsgalat_datum"] = eredeti_adatok.get("szerkezeti_vizsgalat_datum")
        uj_datumok["fovizsgalat_datum"] = eredeti_adatok.get("fovizsgalat_datum")

    if not is_new and not current_user.jog_datum_szerkesztes:
        datum_valtozott = any(uj_datumok[mezo] != eredeti_adatok.get(mezo) for mezo in uj_datumok)
        if datum_valtozott:
            return JSONResponse(
                status_code=403,
                content={"message": "Nincs jogosultságod a gép dátumainak kézi módosítására! A dátumok csak hivatalos jegyzőkönyv rögzítésével vagy dokumentum feltöltésével frissülhetnek - ezt a jogot a rendszeradminisztrátor/céges admin egyedileg engedélyezheti."}
            )

    gep.gyartas_datum = uj_datumok["gyartas_datum"]
    gep.uzembe_helyezes_datum = uj_datumok["uzembe_helyezes_datum"]
    gep.szerkezeti_vizsgalat_datum = uj_datumok["szerkezeti_vizsgalat_datum"]
    gep.fovizsgalat_datum = uj_datumok["fovizsgalat_datum"]
    gep.biztonsagi_vizsgalat_datum = uj_datumok["biztonsagi_vizsgalat_datum"]

    # MSZ 9750 paraméterek és Okos Üzemóra mentése
    if form_data.get("uzemora"):
        gep.uzemora = float(form_data.get("uzemora"))
    else:
        gep.uzemora = 0.0

    if form_data.get("napi_atlag_uzemido"):
        # Egy napnak legfeljebb 24 órája van - a beírt értéket erre a tartományra korlátozzuk
        beirt_napi_atlag = float(form_data.get("napi_atlag_uzemido"))
        gep.napi_atlag_uzemido = max(0.0, min(24.0, beirt_napi_atlag))
        # >>> BÁZISPONT BEÁLLÍTÁSA <<<
        # Mentéskor "lenullázzuk" a Mátrix kezdőpontját, így nem lesz irreális ugrás!
        gep.matrix_kezdo_datum = datetime.now(timezone.utc)
        gep.matrix_kezdo_uzemora = gep.uzemora
        gep.uzemora_riasztas_szint = None
    else:
        gep.napi_atlag_uzemido = 0.0

    gep.teher_class = form_data.get("teher_class")

    if form_data.get("veszelyes_kornyezet") == "on":
        gep.veszelyes_kornyezet = True
    else:
        gep.veszelyes_kornyezet = False

    if form_data.get("kezelo_egyutt_emelkedik") == "on":
        gep.kezelo_egyutt_emelkedik = True
    else:
        gep.kezelo_egyutt_emelkedik = False

    kezeloi_munkahely_magassaga = form_data.get("kezeloi_munkahely_magassaga")
    try:
        gep.kezeloi_munkahely_magassaga = int(kezeloi_munkahely_magassaga) if kezeloi_munkahely_magassaga else None
    except (TypeError, ValueError):
        gep.kezeloi_munkahely_magassaga = None

    if form_data.get("veszelyes_teher_mozgatas") == "on":
        gep.veszelyes_teher_mozgatas = True
    else:
        gep.veszelyes_teher_mozgatas = False

    if form_data.get("egyedi_csoportszam_kockazat_alapjan") == "on":
        gep.egyedi_csoportszam_kockazat_alapjan = True
    else:
        gep.egyedi_csoportszam_kockazat_alapjan = False

    if hasattr(gep, 'ebsz_ciklus_honap'):
        if form_data.get("ebsz_ciklus_honap"):
            gep.ebsz_ciklus_honap = int(form_data.get("ebsz_ciklus_honap"))
        else:
            gep.ebsz_ciklus_honap = 60

    # Közúti forgalom adatok
    if form_data.get("kozuti_forgalom") == "on":
        gep.kozuti_forgalom = True
    else:
        gep.kozuti_forgalom = False

    gep.rendszam = form_data.get("rendszam")
    gep.forgalmi_szam = form_data.get("forgalmi_szam")
    gep.kozuti_vizsga_datum = parse_date(form_data.get("kozuti_vizsga_datum"))

    # Biztonsági okokból a szerver számolja újra az M-fokozatot és a csoportszámot,
    # nem fogadja el vakon a kliens JS által beküldött értéket.
    recompute_msz_classification(gep, form_data)

    # --- ÚJ: INTELLIGENS SZÓTÁR AUTOMATIZÁLÁS (DUPLIKÁCIÓ SZŰRÉSSEL) ---
    def auto_szotar_bovites(kategoria, ertek):
        if ertek and str(ertek).strip():
            tiszta_ertek = str(ertek).strip()

            # Szűrjük a duplikációkat kis/nagybetű függetlenül (ilike)
            letezo = db.query(models.Dictionary).filter(
                models.Dictionary.company_id == working_company_id,
                models.Dictionary.kategoria == kategoria,
                models.Dictionary.ertek.ilike(tiszta_ertek)
            ).first()

            # Csak akkor mentjük, ha tényleg nincs még ilyen a szótárban
            if not letezo:
                uj_elem = models.Dictionary(
                    company_id=working_company_id,
                    kategoria=kategoria,
                    ertek=tiszta_ertek
                )
                db.add(uj_elem)

    # Elmentjük az új Gyártót és a Géptípust (ami a szótárban "Tipus" néven fut)
    auto_szotar_bovites("Gyarto", form_data.get("gyarto"))
    auto_szotar_bovites("Tipus", form_data.get("geptipus"))
    # -------------------------------------------------------------------

    if is_new:
        db.flush()
        uj_audit_log = models.AuditLog(

            machine_id=gep.id,
            user_id=current_user.id,
            field_name="ÚJ GÉP",
            old_value="-",
            new_value="Rendszerbe rögzítve"
        )
        db.add(uj_audit_log)
        if atvetel_forras:
            naploz_tipus_atvetel(db, current_user, gep, atvetel_forras, form_data)

    kockazat_file = form_data.get("kockazatertekeles_file")
    if kockazat_file:
        if getattr(kockazat_file, "filename", "") != "":
            if not is_safe_extension(kockazat_file.filename):
                return JSONResponse(
                    status_code=400,
                    content={"message": "Biztonsági hiba: Nem engedélyezett fájlformátum a kockázatértékelésnél!"}
                )
            mappa = f"uploads/{working_company_id}/{gep.id}"
            os.makedirs(mappa, exist_ok=True)
            safe_filename = sanitize_filename(kockazat_file.filename)

            if kep_e(kockazat_file.filename):
                # Kép-kiterjesztésnél (jpg/png/gif/webp) a tartalom_illeszkedik_e_kiterjesztesre()
                # a függvény docstringje szerint automatikusan True-t ad - a valódi tartalmi
                # ellenőrzést a tomorit_kepet() PIL-alapú újratömörítése végzi el, ugyanúgy, mint
                # a lejjebb lévő offline_fenykepek feltöltésnél. Korábban ez a végpont kép-
                # kiterjesztés esetén a nyers, teljesen ellenőrizetlen bájtokat mentette el.
                kep_bytes = tomorit_kepet(await kockazat_file.read())
                if kep_bytes is None:
                    return JSONResponse(
                        status_code=400,
                        content={"message": "A feltöltött kép nem érvényes vagy sérült!"}
                    )
                safe_filename = safe_filename.rsplit(".", 1)[0] + ".jpg"
                file_path = f"/{mappa}/kockazatertekeles_{safe_filename}"
                with open(file_path.lstrip('/'), "wb+") as f:
                    f.write(kep_bytes)
            else:
                _fejresz = kockazat_file.file.read(8)
                kockazat_file.file.seek(0)
                if not tartalom_illeszkedik_e_kiterjesztesre(kockazat_file.filename, _fejresz):
                    return JSONResponse(
                        status_code=400,
                        content={"message": "A feltöltött fájl tartalma nem egyezik a kiterjesztésével!"}
                    )
                file_path = f"/{mappa}/kockazatertekeles_{safe_filename}"
                with open(file_path.lstrip('/'), "wb+") as f:
                    shutil.copyfileobj(kockazat_file.file, f)

            gep.kockazatertekeles_pdf_path = file_path

            # JAVÍTVA (2026-10-11-i user-jelzés): eddig a fájl KIZÁRÓLAG ebbe a saját mezőbe
            # (kockazatertekeles_pdf_path) mentődött, SOHA nem lett belőle File-sor - ezért nem
            # jelent meg a "Csatolt dokumentumok" listájában (GET /gep-fajlok) és a Gépnaplóban
            # sem (mindkettő kizárólag a File táblából dolgozik). Egy géphez csak egy kockázat-
            # értékelés tartozhat, ezért újra-feltöltésnél a korábbi File-sort lecseréljük, nem
            # halmozzuk.
            db.query(models.File).filter(
                models.File.machine_id == gep.id,
                models.File.file_type == "Kockázatértékelés"
            ).delete(synchronize_session=False)
            db.add(models.File(machine_id=gep.id, file_path=file_path, file_type="Kockázatértékelés"))

            pdf_audit_log = models.AuditLog(
                machine_id=gep.id,
                user_id=current_user.id,
                field_name="KOCKÁZATÉRTÉKELÉS",
                old_value="-",
                new_value="Dokumentum csatolva"
            )
            db.add(pdf_audit_log)

    # --- OFFLINE ÚJ GÉP FELVITEL: a helyszínen (jellemzően jelerősség nélkül) készített,
    # kliens oldalon már tömörített fotók csatolása - csak az offline gépbeviteli lap küldi ezt a mezőt. ---
    offline_fenykepek = form_data.getlist("offline_fenykep")
    if offline_fenykepek:
        mappa = f"uploads/{working_company_id}/{gep.id}"
        os.makedirs(mappa, exist_ok=True)
        for kep_file in offline_fenykepek:
            if getattr(kep_file, "filename", "") and is_safe_extension(kep_file.filename):
                safe_filename = sanitize_filename(kep_file.filename)
                kep_bytes = tomorit_kepet(await kep_file.read())
                if kep_bytes is None:
                    continue
                safe_filename = safe_filename.rsplit(".", 1)[0] + ".jpg"
                file_loc = f"{mappa}/{datetime.now().strftime('%Y%m%d%H%M%S%f')}_{safe_filename}"
                with open(file_loc, "wb+") as f:
                    f.write(kep_bytes)
                db.add(models.File(machine_id=gep.id, file_path="/" + file_loc, file_type="Fénykép"))
    # ----------------------------------------

    for col in gep.__table__.columns:
        if col.name == "kockazatertekeles_pdf_path":
            continue

        old_val = None
        if not is_new:
            old_val = eredeti_adatok.get(col.name)

        new_val = getattr(gep, col.name)

        # Üres mezők kezeélése
        if old_val is None and new_val == "":
            continue
        if old_val == "" and new_val is None:
            continue

        if old_val is not None:
            old_str = str(old_val)
        else:
            old_str = "-"

        if new_val is not None:
            new_str = str(new_val)
        else:
            new_str = "-"

        if str(old_val if old_val is not None else "") != str(new_val if new_val is not None else "") and not is_new:
            valtozas_log = models.AuditLog(
                machine_id=gep.id,
                user_id=current_user.id,
                field_name=col.name,
                old_value=old_str,
                new_value=new_str
            )
            db.add(valtozas_log)

    db.commit()

    # Ha ÚJ gép rögzítése történt (nem volt machine_id elküldve):
    if not form_data.get("machine_id"):
        # Visszadobjuk a listára, de egy rejtett URL paraméterrel:
        return RedirectResponse(url="/lista?kockazat_emlekezteto=true", status_code=303)
        # (Ha mentés után a szerkesztőben maradsz, akkor: url=f"/szerkesztes/{uj_gep.uuid}?kockazat_emlekezteto=true")

    return RedirectResponse(url="/lista", status_code=303)


# --- LISTA ---
def get_search_filter(sz, models):
    term = f"%{sz}%"
    return or_(
        # Szöveges mezők:
        models.Machine.megnevezes.ilike(term),
        models.Machine.gyari_szam.ilike(term),
        models.Machine.geptipus.ilike(term),
        models.Machine.tipus.ilike(term),
        models.Machine.gyarto.ilike(term),
        models.Machine.leltari_szam.ilike(term),
        models.Machine.statusz.ilike(term),
        # Kapcsolt tábla (Telephely neve):
        models.Machine.telephely.has(models.Site.nev.ilike(term)),
        # Számok és Dátumok (szöveggé alakítva a kereséshez):
        cast(models.Machine.teherbiras, String).ilike(term),
        cast(models.Machine.gyartas_datum, String).ilike(term),
        cast(models.Machine.uzembe_helyezes_datum, String).ilike(term),
        cast(models.Machine.szerkezeti_vizsgalat_datum, String).ilike(term),
        cast(models.Machine.fovizsgalat_datum, String).ilike(term),
        cast(models.Machine.biztonsagi_vizsgalat_datum, String).ilike(term)
    )


RENDEZHETO_OSZLOPOK = {
    "megnevezes": models.Machine.megnevezes,
    "gyarto": models.Machine.gyarto,
    "tipus": models.Machine.tipus,
    "gyari_szam": models.Machine.gyari_szam,
    "geptipus": models.Machine.geptipus,
    "csoportszam": models.Machine.calculated_csoportszam,
    "uzemora": models.Machine.uzemora,
    "leltari_szam": models.Machine.leltari_szam,
    "teherbiras": models.Machine.teherbiras,
    "gyartas": models.Machine.gyartas_datum,
    "uzembe": models.Machine.uzembe_helyezes_datum,
    "statusz": models.Machine.statusz,
}


def _gepek_szurt_lekerdezes(working_company_id, current_user, db: Session, search1="", search2="", search3="", rendezes="id", irany="desc"):
    """Az emelőgép-lista szűrési/rendezési logikája - a /lista és a tömeges matrica-nyomtatás is
    ezt használja, hogy a kettő mindig pontosan ugyanazt a (szűrt) eredményhalmazt adja."""
    berelt_gep_idk = berelt_gep_idk_a_ceghez(working_company_id, db)
    if berelt_gep_idk:
        query = db.query(models.Machine).filter(
            or_(models.Machine.company_id == working_company_id, models.Machine.id.in_(berelt_gep_idk))
        )
    else:
        query = db.query(models.Machine).filter(models.Machine.company_id == working_company_id)
    query = apply_user_data_scope_filter(query, current_user)

    if search1:
        query = query.filter(get_search_filter(search1, models))
    if search2:
        query = query.filter(get_search_filter(search2, models))
    if search3:
        query = query.filter(get_search_filter(search3, models))

    if irany not in ("asc", "desc"):
        irany = "desc"

    if rendezes == "telephely":
        query = query.outerjoin(models.Site, models.Machine.site_id == models.Site.id)
        rendezo_oszlop = models.Site.nev
    elif rendezes == "eredet":
        rendezo_oszlop = case((models.Machine.company_id == working_company_id, 0), else_=1)
    else:
        rendezo_oszlop = RENDEZHETO_OSZLOPOK.get(rendezes, models.Machine.id)

    return query.order_by(rendezo_oszlop.asc() if irany == "asc" else rendezo_oszlop.desc())


def _gepek_kivalasztott_lista(working_company_id, current_user, db: Session, ids="", search1="", search2="", search3="", rendezes="id", irany="desc"):
    """A tömeges matrica-nyomtatás és a Brady CSV-export közös gép-kiválasztási logikája:
    vagy a kifejezetten kijelölt gépeket adja vissza (ids), vagy - ha nincs ids megadva -
    a lista aktuális szűrésének TELJES eredményét, a _gepek_szurt_lekerdezes-szel."""
    if ids:
        id_lista = [int(i) for i in ids.split(",") if i.strip().isdigit()]
        berelt_gep_idk = berelt_gep_idk_a_ceghez(working_company_id, db)
        return db.query(models.Machine).filter(
            models.Machine.id.in_(id_lista),
            or_(models.Machine.company_id == working_company_id, models.Machine.id.in_(berelt_gep_idk))
        ).all()
    query = _gepek_szurt_lekerdezes(working_company_id, current_user, db, search1, search2, search3, rendezes, irany)
    return query.all()


@router.get("/lista", response_class=HTMLResponse)
def lista(
    request: Request,
    search1: str = "",
    search2: str = "",
    search3: str = "",
    page: str = "1",
    rendezes: str = "id",
    irany: str = "desc",
    db: Session = Depends(get_db),
    current_user: models.User = Depends(get_current_user)
):
    # A "page" query-paramétert stringként fogadjuk (nem int-ként), mert az "Ugrás oldalra"
    # mező value nélkül, csak placeholder-rel rendelkezik - üresen elküldve "page="-t generál,
    # amit egy sima `page: int` FastAPI-paraméter 422-es hibával elutasítana. Érvénytelen/üres
    # érték esetén az 1. oldalra esünk vissza, a lenti clamp-logika ettől még változatlan marad.
    try:
        page = int(page)
    except (TypeError, ValueError):
        page = 1

    working_company_id = get_working_company_id(current_user, request)

    is_master_company = False
    if working_company_id == 1 and current_user.role == "Admin":
        is_master_company = True

    gepek = []
    total_pages = 1

    if not is_master_company:
        if irany not in ("asc", "desc"):
            irany = "desc"

        query = _gepek_szurt_lekerdezes(working_company_id, current_user, db, search1, search2, search3, rendezes, irany)

        per_page = 20
        total_items = query.count()

        if total_items > 0:
            total_pages = math.ceil(total_items / per_page)
        else:
            total_pages = 1

        if page < 1:
            page = 1
        if page > total_pages:
            page = total_pages

        offset_value = (page - 1) * per_page
        gepek = query.offset(offset_value).limit(per_page).all()

        # Egyetlen lekérdezés az N+1 helyett: az oldalon lévő összes gép utolsó vizsgálata egyszerre
        utolso_vizsgalatok = {}
        jegyzokonyv_gep_idk = set()
        gep_ids = [g.id for g in gepek]
        if gep_ids:
            inspections = db.query(models.Inspection).filter(
                models.Inspection.machine_id.in_(gep_ids)
            ).order_by(models.Inspection.datum.desc()).all()
            for insp in inspections:
                if insp.machine_id not in utolso_vizsgalatok:
                    utolso_vizsgalatok[insp.machine_id] = insp
                if insp.jegyzokonyv_pdf_path:
                    jegyzokonyv_gep_idk.add(insp.machine_id)

        # Feltöltött fájlok (fénykép / jkv-típusok) gépenkénti csoportosítása - egyetlen lekérdezéssel
        fajlok_by_gep = {}
        if gep_ids:
            fajlok = db.query(models.File).filter(models.File.machine_id.in_(gep_ids)).all()
            for f in fajlok:
                fajlok_by_gep.setdefault(f.machine_id, []).append(f)

        # Aktív bérletek gépenként - egyetlen lekérdezéssel, mindkét irányhoz (bérelt nálam / kihelyezve tőlem) felhasználva lent.
        aktiv_berletek_by_gep = {}
        if gep_ids:
            aktiv_berletek = db.query(models.BerletiIdoszak).filter(
                models.BerletiIdoszak.machine_id.in_(gep_ids),
                models.BerletiIdoszak.vege == None
            ).all()
            for b in aktiv_berletek:
                aktiv_berletek_by_gep[b.machine_id] = b

        # Géptípusonkénti kötelező-mező konfiguráció (a "Dinamikus kötelező mezők" adatlap-logika
        # lista-nézetbeli tükrözéséhez)
        configs_by_geptipus = {
            c.geptipus: c for c in
            db.query(models.MachineTypeConfig).filter(models.MachineTypeConfig.company_id == working_company_id).all()
        }
        datum_kotelezo_mod = get_vizsgalati_datum_kotelezo_mod(working_company_id, db)

        mai_nap = date.today()

        for gep in gepek:
            gep.status_color = ""
            utolso_vizsgalat = utolso_vizsgalatok.get(gep.id)

            if utolso_vizsgalat:
                if "Nem" in utolso_vizsgalat.eredmeny:
                    gep.status_color = "danger"
                elif "Korlátozás" in utolso_vizsgalat.eredmeny:
                    gep.status_color = "warning"

            # Eredet jelölés: a bérbeadótól kihelyezett gép is megjelenik a bérlő listájában
            gep.berelt_nalam = (gep.company_id != working_company_id)
            gep.berbeado_nev_kihelyezve = gep.ceg.nev if gep.berelt_nalam and gep.ceg else None

            berlet = aktiv_berletek_by_gep.get(gep.id)

            # ÚJ (2026-10-10-i user-jelzés): a bérelt gép eddig a bérbeadó SAJÁT telephelyét és
            # "Készenléti hely" (megnevezes) adatát mutatta a bérlő listájában is - ez a bérlőnek
            # értelmetlen (idegen cég adata). Ha a bérlő jóváhagyáskor megadta a saját telephelyét/
            # helyét (l. berlet_jovahagyasa), azt mutatjuk helyette; a Machine saját adatai nem változnak.
            gep.megjelenitett_telephely = gep.telephely
            gep.megjelenitett_keszenleti_hely = gep.megnevezes
            if gep.berelt_nalam and berlet and berlet.jovahagyva:
                if berlet.berlo_site_id:
                    gep.megjelenitett_telephely = berlet.berlo_site
                if berlet.berlo_keszenleti_hely:
                    gep.megjelenitett_keszenleti_hely = berlet.berlo_keszenleti_hely

            # ÚJ: a bérbeadó saját listájában is jelezzük (a bérlő "Bérelt nálam" jelölésének
            # megfelelője), ha a gép jelenleg ki van helyezve egy bérlőhöz.
            gep.kihelyezve_e = bool(berlet) and not gep.berelt_nalam
            gep.kihelyezve_cegnev = None
            gep.kihelyezve_fuggoben = False
            if gep.kihelyezve_e:
                gep.kihelyezve_cegnev = berlet.berlo_ceg.nev if berlet.berlo_ceg else (berlet.berlo_nev_kulso or "Ismeretlen")
                gep.kihelyezve_fuggoben = not berlet.jovahagyva

            # Adatlap (ceruza gomb) - hiányzik-e valamelyik, a géptípushoz kötelezőnek jelölt mező
            gep.hianyzo_mezok = gep_hianyzo_kotelezo_mezok(gep, configs_by_geptipus.get(gep.geptipus))

            # MSZ 16226 üzemviteli dokumentum gomb - csak azoknál a géptípusoknál jelenjen meg,
            # amiknél a cég ezt bekapcsolta (MachineTypeConfig.msz16226_szukseges)
            geptipus_konfig = configs_by_geptipus.get(gep.geptipus)
            gep.msz16226_szukseges = bool(geptipus_konfig and geptipus_konfig.msz16226_szukseges)

            # Dokumentumok (gemkapocs gomb) - van-e legalább 1 fénykép és legalább 1 jegyzőkönyv
            gep_fajljai = fajlok_by_gep.get(gep.id, [])
            van_kep = any(f.file_type == "Fénykép" for f in gep_fajljai)
            van_jkv = gep.id in jegyzokonyv_gep_idk or any("jkv" in (f.file_type or "").lower() for f in gep_fajljai)
            gep.hianyzo_dokumentumok = []
            if not van_kep:
                gep.hianyzo_dokumentumok.append("fénykép")
            if not van_jkv:
                gep.hianyzo_dokumentumok.append("jegyzőkönyv")

            # Naptár gomb - lejárt/hiányzó (piros) vagy 30 napon belül esedékes (sárga) vizsgálat
            esedekessegek = compute_vizsgalati_esedekesseg(gep, mai_nap, configs_by_geptipus.get(gep.geptipus), datum_kotelezo_mod)
            allapotok = {e["allapot"] for e in esedekessegek}
            if allapotok & {"lejart", "hianyzik"}:
                gep.naptar_szin = "danger"
            elif "hamarosan" in allapotok:
                gep.naptar_szin = "warning"
            else:
                gep.naptar_szin = ""

            # ÚJ: "Lejárt vizsgálat" - automatikusan számított (nem kézzel beállítható) állapot,
            # ami a Státusz oszlopban felülírja az "Aktív" jelölést, ha a gép ténylegesen aktív,
            # de valamelyik vizsgálati dátuma lejárt vagy hiányzik. A gep.statusz mezőt magát NEM
            # módosítja, csak a megjelenítést - a mögöttes üzleti logika (pl. vizsgálat rögzítése,
            # amihez a gépnek ténylegesen "Aktív"-nak kell lennie) így változatlanul működik.
            if gep.statusz == "Aktív" and gep.naptar_szin == "danger":
                gep.effektiv_statusz = "Lejárt vizsgálat"
            else:
                gep.effektiv_statusz = gep.statusz

    telephelyek = db.query(models.Site).filter(models.Site.company_id == working_company_id).all()
    cegek = get_allowed_companies_list(current_user, db, "EMELOGEP")
    ceg_aktiv = is_company_active(working_company_id, db)
    ai_szkenneles = ai_szkenneles_engedelyezve(working_company_id, db)

    # Függőben lévő, jóváhagyásra váró bérbevételi kérések erre a cégre - csak Admin/Emelőgép
    # ügyintéző hagyhatja jóvá (lásd routers/machines.py berlet_jovahagyasa), ezért a sávot is csak
    # nekik mutatjuk.
    fuggo_berletek_szama = 0
    if current_user.role in ["Admin", "Emelőgép ügyintéző"]:
        fuggo_berletek_szama = db.query(models.BerletiIdoszak).filter(
            models.BerletiIdoszak.berlo_company_id == working_company_id,
            models.BerletiIdoszak.vege == None,
            models.BerletiIdoszak.jovahagyva == False
        ).count()

    return templates.TemplateResponse(
        request=request,
        name="list.html",
        context={
            "gepek": gepek,
            "user": current_user,
            "search1": search1,
            "search2": search2,
            "search3": search3,
            "current_page": page,
            "total_pages": total_pages,
            "telephelyek": telephelyek,
            "working_company_id": working_company_id,
            "cegek": cegek,
            "is_master_company": is_master_company,
            "ceg_aktiv": ceg_aktiv,
            "ai_szkenneles": ai_szkenneles,
            "rendezes": rendezes,
            "irany": irany,
            "is_rendszeradmin": is_rendszeradminisztrator(current_user),
            "sugo_e": sugo_engedelyezve(working_company_id, db),
            "fuggo_berletek_szama": fuggo_berletek_szama,
        }
    )


@router.get("/gepek/tomeges-matrica", response_class=HTMLResponse)
def gepek_tomeges_matrica(
    request: Request,
    ids: str = "",
    search1: str = "",
    search2: str = "",
    search3: str = "",
    rendezes: str = "id",
    irany: str = "desc",
    db: Session = Depends(get_db),
    current_user: models.User = Depends(get_current_user)
):
    """Tömeges Smart QR / NFC matrica-nyomtatás - kizárólag Admin (céges vagy rendszeradmin)
    jogosultsággal. Vagy a kifejezetten kijelölt gépeket nyomtatja (ids), vagy -
    ha nincs ids megadva - a lista aktuális szűrésének TELJES eredményét (nem csak az aktuálisan
    lapozott oldalt), ugyanazzal a _gepek_szurt_lekerdezes szűrő/rendező logikával, mint a /lista."""
    if current_user.role not in ["Admin"]:
        return RedirectResponse(url="/lista")

    working_company_id = get_working_company_id(current_user, request)

    if not is_company_active(working_company_id, db):
        return RedirectResponse(url="/lista?inaktiv_ceg=1")

    gepek = _gepek_kivalasztott_lista(working_company_id, current_user, db, ids, search1, search2, search3, rendezes, irany)

    if not gepek:
        return RedirectResponse(url="/lista")

    azonositas_mod = get_azonositas_mod(working_company_id, db)
    uzemelteto_ceg = db.query(models.Company).filter(models.Company.id == working_company_id).first()
    uzemelteto_nev = uzemelteto_ceg.nev if uzemelteto_ceg else ""

    cimke_adatok = []
    for gep in gepek:
        if gep.berelt_eszkoz:
            tulajdonos_nev = gep.berbeado_neve or "Külsős bérbeadó (nincs megadva a neve)"
        elif gep.company_id != working_company_id:
            tulajdonos_nev = gep.ceg.nev if gep.ceg else None
        else:
            tulajdonos_nev = None

        cimke_adatok.append({
            "id": gep.id,
            "uuid": gep.uuid,
            "megnevezes": gep.megnevezes or "Ismeretlen gép",
            "gyari_szam": gep.gyari_szam,
            "leltari_szam": gep.leltari_szam,
            "tulajdonos_nev": tulajdonos_nev,
        })

    return templates.TemplateResponse(
        request=request,
        name="tomeges_matrica.html",
        context={
            "user": current_user,
            "azonositas_mod": azonositas_mod,
            "uzemelteto_nev_json": safe_json_for_script(uzemelteto_nev),
            "cimke_adatok_json": safe_json_for_script(cimke_adatok),
            "darab": len(cimke_adatok),
        }
    )


@router.get("/gepek/tomeges-cimke-csv")
def gepek_tomeges_cimke_csv(
    request: Request,
    ids: str = "",
    search1: str = "",
    search2: str = "",
    search3: str = "",
    rendezes: str = "id",
    irany: str = "desc",
    db: Session = Depends(get_db),
    current_user: models.User = Depends(get_current_user)
):
    """CSV export a Brady Workstation adatösszefésüléshez (data merge) - ugyanazt a szűrt/kijelölt
    gép-halmazt adja vissza, mint a /gepek/tomeges-matrica, csak a Brady saját szoftverébe
    importálható CSV formátumban a fizikai (szalagos) nyomtatáshoz."""
    if current_user.role not in ["Admin"]:
        return RedirectResponse(url="/lista")

    working_company_id = get_working_company_id(current_user, request)

    if not is_company_active(working_company_id, db):
        return RedirectResponse(url="/lista?inaktiv_ceg=1")

    gepek = _gepek_kivalasztott_lista(working_company_id, current_user, db, ids, search1, search2, search3, rendezes, irany)

    if not gepek:
        return RedirectResponse(url="/lista")

    uzemelteto_ceg = db.query(models.Company).filter(models.Company.id == working_company_id).first()
    uzemelteto_nev = uzemelteto_ceg.nev if uzemelteto_ceg else ""

    buffer = io.StringIO()
    writer = csv.writer(buffer, delimiter=";")
    writer.writerow(["Üzemeltető", "Gép megnevezése", "Gyári szám", "Leltári szám", "Tulajdonos", "QR URL"])
    for gep in gepek:
        if gep.berelt_eszkoz:
            tulajdonos_nev = gep.berbeado_neve or ""
        elif gep.company_id != working_company_id:
            tulajdonos_nev = gep.ceg.nev if gep.ceg else ""
        else:
            tulajdonos_nev = ""
        qr_url = f"{request.base_url}q/{gep.uuid}" if gep.uuid else ""
        writer.writerow([uzemelteto_nev, gep.megnevezes or "", gep.gyari_szam or "", gep.leltari_szam or "", tulajdonos_nev, qr_url])

    csv_bytes = b"\xef\xbb\xbf" + buffer.getvalue().encode("utf-8")
    return Response(
        content=csv_bytes,
        media_type="text/csv; charset=utf-8",
        headers={"Content-Disposition": 'attachment; filename="emelog_cimke_adatok.csv"'}
    )


# KARBANTARTÁS (2026-10-03-i biztonsági audit, 4. fázis): a gep.statusz mező eddig a
# formból érkező uj_statusz értéket validálatlanul fogadta - a lenti if-ágak csak NÉHÁNY
# konkrét értékre futtatnak mellékhatást (pl. bérlet lezárása, új gép létrehozása
# telephely-átszállításnál), minden más tetszőleges szöveg simán elmentődött volna a
# gep.statusz-ba, látható/szűrhető "state" rontva. A lista a templates/list.html
# uj_statusz_select mezőjének pontos option-értékeit tükrözi.
ENGEDELYEZETT_GEP_STATUSZOK = {
    "Aktív", "Kivonva (javításra vár)", "Kivonva (vizsgán nem megfelelés miatt)",
    "Végleg kivonva/Selejtezve", "Eladva", "Bérleti idő lejárt / Visszaadva",
    "Átszállítva másik telephelyre",
}


@router.post("/gep-statusz-valtas/{machine_id}")
def gep_statusz_valtas(
    request: Request,
    machine_id: int,
    uj_statusz: str = Form(...),
    indoklas: str = Form(...),
    uj_telephely_id: int = Form(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 is_company_active(working_company_id, db):
        return JSONResponse(
            status_code=403,
            content={"message": "Ez a cég inaktív státuszú, a gép státusza nem módosítható!"}
        )

    if current_user.csak_olvasas:
        return JSONResponse(
            status_code=403,
            content={"message": "Csak megtekintési jogosultsággal rendelkezel, szerkesztés nem lehetséges!"}
        )

    if current_user.role not in EMELOGEP_KEZELO_SZEREPKOROK:      # J-25 (v76): pozitív lista
        return JSONResponse(
            status_code=403,
            content={"message": "Nincs jogosultságod a gép státuszának mozgatásához!"}
        )

    gep = db.query(models.Machine).filter(
        models.Machine.id == machine_id,
        models.Machine.company_id == working_company_id
    ).first()

    if not gep or not is_machine_allowed(gep, current_user):
        return JSONResponse(
            status_code=404,
            content={"message": "Gép nem található vagy nincs hozzáférésed!"}
        )

    # "Lejárt vizsgálat" nem valódi, kézzel beállítható státusz - a lista automatikusan
    # jelzi vele az egyébként Aktív gépeket, amiknek lejárt/hiányzik a vizsgálati dátuma.
    if uj_statusz == "Lejárt vizsgálat":
        return JSONResponse(
            status_code=400,
            content={"message": "A 'Lejárt vizsgálat' automatikusan számított állapot, kézzel nem állítható be!"}
        )

    if uj_statusz not in ENGEDELYEZETT_GEP_STATUSZOK:
        return JSONResponse(status_code=400, content={"message": "Érvénytelen gép-státusz!"})

    if uj_statusz == "Aktív" and gep.statusz not in ["Kivonva (javításra vár)", "Kivonva (vizsgán nem megfelelés miatt)"]:
        return JSONResponse(
            status_code=400,
            content={"message": "Aktív státuszba visszaállítás kizárólag a javításra váró, vagy a vizsgán nem megfelelés miatt kivont gépnél lehetséges!"}
        )

    if uj_statusz == "Átszállítva másik telephelyre" and uj_telephely_id:
        # J-14 (v75): átszállítani csak Aktív státuszú gépet lehet - különben egy selejtezett / eladott / már átszállított
        # gépből is új, Aktív másolat készülne (és kétszeri beküldésnél két aktív másolat)
        if gep.statusz != "Aktív":
            return JSONResponse(status_code=400, content={"message": (
                f"Átszállítás kizárólag Aktív státuszú gépnél lehetséges! (A gép jelenlegi státusza: {gep.statusz})")})

        # ÚJ (2026-10-11-i user-jelzés): az átszállítás ÚJ gép-rekordot hoz létre, a régit inaktiválja -
        # ha a gépnek aktív (vagy jóváhagyásra váró) bérlete van, az a RÉGI, ezután inaktív gép-azonosítóra
        # maradna kötve: a bérlő a megszűnt rekordot látná tovább, az új (ténylegesen folytatódó) gépet
        # viszont nem érné el. Emellett amíg a gép ki van helyezve, a fizikai helye a bérlőnél van, nem a
        # bérbeadó saját telephelyei között mozog - a bérbeadó saját telephelyei közti "átszállítás" ilyenkor
        # fogalmilag sem értelmezhető.
        folyamatban_levo_berlet = aktiv_berlet(gep, db)
        if folyamatban_levo_berlet:
            berlo_nev = folyamatban_levo_berlet.berlo_ceg.nev if folyamatban_levo_berlet.berlo_ceg else (folyamatban_levo_berlet.berlo_nev_kulso or "egy másik cég")
            return JSONResponse(status_code=400, content={"message": (
                f"Ez a gép jelenleg ki van helyezve a(z) {berlo_nev} céghez, ezért nem szállítható át másik "
                f"telephelyre! Előbb zárd le a bérletet a gép szerkesztő oldalán (\"Bérlet lezárása\"), "
                f"utána végezd el az átszállítást.")})

        # J-14 (v75): az átszállítás új gép-rekordot hoz létre (a régi is megmarad), tehát ugyanúgy a licenc gépszám-limitjébe
        # számít, mint egy új gép felvitele
        atszallito_ceg = db.query(models.Company).filter(models.Company.id == gep.company_id).first()
        tullepne, jelenlegi, limit = licenc_tullepne_uj_gepnel(atszallito_ceg, db)
        if tullepne:
            return JSONResponse(status_code=403, content={"message": (
                f"Elérted a licenced szerinti maximális gépszámot ({jelenlegi}/{limit})! Az átszállítás új gép-rekordot hoz létre, "
                f"a bővítéshez keresd az üzemeltetőt.")})

        uj_th = db.query(models.Site).filter(
            models.Site.id == uj_telephely_id,
            models.Site.company_id == working_company_id
        ).first()
        if not uj_th:
            return JSONResponse(status_code=400, content={"message": "A kiválasztott céltelephely érvénytelen!"})

        if gep.telephely:
            regi_th_nev = gep.telephely.nev
        else:
            regi_th_nev = "Ismeretlen"

        gep.statusz = "Átszállítva másik telephelyre"
        gep.statusz_oka = f"Átszállítva ide: {uj_th.nev}. Indok: {indoklas}"

        kivonas_log = models.AuditLog(
            machine_id=gep.id,
            user_id=current_user.id,
            field_name="Státusz",
            old_value="Aktív",
            new_value=f"Inaktiválva - Átszállítva ide: {uj_th.nev}"
        )
        db.add(kivonas_log)

        megjegyzes_text = f"Átszállítva a(z) {regi_th_nev} telephelyről. "
        if gep.alapadat_megjegyzes:
            megjegyzes_text += gep.alapadat_megjegyzes

        uj_gep = models.Machine(
            company_id=gep.company_id,
            site_id=uj_th.id,
            megnevezes=gep.megnevezes,
            gyarto=gep.gyarto,
            tipus=gep.tipus,
            gyari_szam=gep.gyari_szam,
            leltari_szam=gep.leltari_szam,
            geptipus=gep.geptipus,
            teherbiras=gep.teherbiras,
            alapadat_megjegyzes=megjegyzes_text,
            gyartas_datum=gep.gyartas_datum,
            uzembe_helyezes_datum=gep.uzembe_helyezes_datum,
            uzemora=gep.uzemora,
            napi_atlag_uzemido=gep.napi_atlag_uzemido,
            matrix_kezdo_datum=gep.matrix_kezdo_datum,
            matrix_kezdo_uzemora=gep.matrix_kezdo_uzemora,
            uzemora_riasztas_szint=gep.uzemora_riasztas_szint,
            teher_class=gep.teher_class,
            veszelyes_kornyezet=gep.veszelyes_kornyezet,
            kezelo_egyutt_emelkedik=gep.kezelo_egyutt_emelkedik,
            kezeloi_munkahely_magassaga=gep.kezeloi_munkahely_magassaga,
            veszelyes_teher_mozgatas=gep.veszelyes_teher_mozgatas,
            calculated_m_fokozat=gep.calculated_m_fokozat,
            calculated_csoportszam=gep.calculated_csoportszam,
            kornyezet_megvaltozott=True,
            statusz="Aktív",
            emelesi_magassag=gep.emelesi_magassag,
            fesztav_gemhossz=gep.fesztav_gemhossz,
            meghajtas=gep.meghajtas,
            teljesitmeny=gep.teljesitmeny,
            egyedi_1=gep.egyedi_1,
            egyedi_2=gep.egyedi_2,
            egyedi_3=gep.egyedi_3,
        )
        db.add(uj_gep)
        db.flush()

        uj_gep_log = models.AuditLog(
            machine_id=uj_gep.id,
            user_id=current_user.id,
            field_name="ÚJ HELYSZÍN",
            old_value="-",
            new_value=f"Gép átvéve a(z) {regi_th_nev} telephelyről. Új vizsgálat szükséges!"
        )
        db.add(uj_gep_log)
        db.commit()

        return RedirectResponse(url="/lista", status_code=status.HTTP_303_SEE_OTHER)

    old_status = gep.statusz
    gep.statusz = uj_statusz
    gep.statusz_oka = indoklas

    status_log = models.AuditLog(
        machine_id=gep.id,
        user_id=current_user.id,
        field_name="Státusz",
        old_value=old_status,
        new_value=f"{uj_statusz} (Megjegyzés: {indoklas})"
    )
    db.add(status_log)

    # Ha a gép selejtezésre/eladásra kerül vagy a bérlet lejár, az esetleges AKTÍV bérleti
    # időszakot is le kell zárni - különben a bérlő oldalán örökre "folyamatban" maradna.
    if uj_statusz in ["Végleg kivonva/Selejtezve", "Eladva", "Bérleti idő lejárt / Visszaadva"]:
        folyamatban_levo_berlet = aktiv_berlet(gep, db)
        if folyamatban_levo_berlet:
            folyamatban_levo_berlet.vege = date.today()

    db.commit()

    if uj_statusz in ["Végleg kivonva/Selejtezve", "Eladva", "Bérleti idő lejárt / Visszaadva"]:
        return RedirectResponse(
            url=f"/lista?file_warning_for={gep.id}",
            status_code=status.HTTP_303_SEE_OTHER
        )

    return RedirectResponse(url="/lista", status_code=status.HTTP_303_SEE_OTHER)


# --- BÉRBEADÁS (KIHELYEZÉS) - a gép a bérbeadó nyilvántartásában marad, de a bérlő cég
# felhasználói is látják/kezelik, amíg a bérlet aktív. ---

@router.post("/gep/{uuid}/kihelyezes")
def gep_kihelyezese(
    uuid: str,
    request: Request,
    berlo_company_id: str = Form(""),
    berlo_nev_kulso: str = Form(""),
    berlo_cim_kulso: str = Form(""),
    berlo_elerhetoseg_kulso: str = Form(""),
    kezdete: str = Form(...),
    uzemeltetes_felelos: str = Form("Berbeado"),
    db: Session = Depends(get_db),
    current_user: models.User = Depends(get_current_user)
):
    if current_user.role not in ["Admin", "Emelőgép ügyintéző"]:
        return RedirectResponse(url="/lista", status_code=303)

    working_company_id = get_working_company_id(current_user, request)
    gep = db.query(models.Machine).filter(
        models.Machine.uuid == uuid, models.Machine.company_id == working_company_id
    ).first()
    if not gep:
        return RedirectResponse(url="/lista", status_code=303)

    if not is_company_active(working_company_id, db):
        return RedirectResponse(url="/lista?inaktiv_ceg=1", status_code=303)
    if current_user.csak_olvasas:
        return RedirectResponse(url="/lista?csak_olvasas=1", status_code=303)

    # A bérbeadás/kihelyezés cégenként engedélyezendő jog (rendszeradmin kapcsolja) -
    # ezt itt, a mentő route-ban is ellenőrizni kell, nem elég csak a gombot elrejteni.
    if not gep.ceg or not gep.ceg.berbeadhat:
        return RedirectResponse(url=f"/szerkesztes/{uuid}", status_code=303)

    if aktiv_berlet(gep, db):
        return RedirectResponse(url=f"/szerkesztes/{uuid}", status_code=303)

    if uzemeltetes_felelos not in ("Berbeado", "Berlo"):
        uzemeltetes_felelos = "Berbeado"

    try:
        kezdete_datum = datetime.strptime(kezdete, "%Y-%m-%d").date()
    except ValueError:
        kezdete_datum = date.today()

    # A bérlő lehet a rendszert használó, regisztrált cég (valódi hozzáférést kap -
    # berlo_company_id), VAGY egy szabad szöveggel rögzített külső fél (csak
    # nyilvántartási feljegyzés, nincs valódi hozzáférés-átadás - a berbeado_neve/
    # berbeado_elerhetoseg mintájára, csak fordított irányban).
    berlo_company_id_val = int(berlo_company_id) if berlo_company_id.strip().isdigit() else None
    if berlo_company_id_val is not None:
        # Feltétel az átkerülésre: 1) létező, 2) aktív cég legyen, 3) a másik fél (a bérlő cég
        # Admin/Emelőgép ügyintéző jogú usere) jóvá is hagyja - ezt a `jovahagyva=False` kezdőérték
        # és a külön jóváhagyó route biztosítja, itt csak az 1-2. feltételt (létezik+aktív+nem
        # saját cég) ellenőrizzük, nem lehet nem létező/törölt cég ID-jét beküldeni.
        celzott_ceg = db.query(models.Company).filter(
            models.Company.id == berlo_company_id_val,
            models.Company.aktiv == True,
            models.Company.id != working_company_id,
        ).first()
        if not celzott_ceg:
            return RedirectResponse(url=f"/szerkesztes/{uuid}", status_code=303)

        # ÚJ (2026-10-06): a cél cég ezen felül Partner (kódos meghívással összekapcsolt) is
        # kell legyen - ez itt, a mentő route-ban is kötelező, nem elég csak a legördülőt
        # szűkíteni, különben egy közvetlen POST kéréssel bármelyik (létező, aktív) céget meg
        # lehetne adni azonosítóként, függetlenül a partnerségtől.
        if not pcu.partnerek_e(db, working_company_id, berlo_company_id_val):
            return RedirectResponse(url=f"/szerkesztes/{uuid}", status_code=303)
    berlo_nev_kulso = berlo_nev_kulso.strip()
    if not berlo_company_id_val and not berlo_nev_kulso:
        return RedirectResponse(url=f"/szerkesztes/{uuid}", status_code=303)

    db.add(models.BerletiIdoszak(
        machine_id=gep.id,
        berlo_company_id=berlo_company_id_val,
        berlo_nev_kulso=berlo_nev_kulso or None,
        berlo_cim_kulso=berlo_cim_kulso.strip() or None,
        berlo_elerhetoseg_kulso=berlo_elerhetoseg_kulso.strip() or None,
        kezdete=kezdete_datum, uzemeltetes_felelos=uzemeltetes_felelos,
        # Regisztrált cégnél (valódi hozzáférés-átadás) jóváhagyásra vár; szabad szöveges,
        # külső félnél nincs mit jóváhagyni, rögtön aktív.
        jovahagyva=(berlo_company_id_val is None),
        letrehozo_user_id=current_user.id,
    ))
    db.commit()
    return RedirectResponse(url=f"/szerkesztes/{uuid}", status_code=303)


@router.post("/gep/{uuid}/berlet-lezarasa")
def berlet_lezarasa(
    uuid: str,
    request: Request,
    db: Session = Depends(get_db),
    current_user: models.User = Depends(get_current_user)
):
    if current_user.role not in ["Admin", "Emelőgép ügyintéző"]:
        return RedirectResponse(url="/lista", status_code=303)

    working_company_id = get_working_company_id(current_user, request)
    gep = db.query(models.Machine).filter(
        models.Machine.uuid == uuid, models.Machine.company_id == working_company_id
    ).first()
    if not gep:
        return RedirectResponse(url="/lista", status_code=303)

    # J-09 (v65): a csak_olvasas mellé a cég-aktív ellenőrzés is kell
    tiltas = irasi_tiltas_oka(current_user, working_company_id, db)
    if tiltas:
        return RedirectResponse(url=IRASI_TILTAS_LISTA_URL[tiltas], status_code=303)

    berlet = aktiv_berlet(gep, db)
    if berlet:
        berlet.vege = date.today()
        db.commit()

    return RedirectResponse(url=f"/szerkesztes/{uuid}", status_code=303)


@router.get("/berlet-fuggoben", response_class=HTMLResponse)
def berlet_fuggoben_lista(
    request: Request,
    db: Session = Depends(get_db),
    current_user: models.User = Depends(get_current_user)
):
    """A bérlő cég oldalán megjelenő, jóváhagyásra váró bérbevételi kérések listája - a bérbeadó
    nem kényszerítheti rá a hozzáférést, amíg ezen az oldalon valaki jóvá nem hagyja."""
    if current_user.role not in ["Admin", "Emelőgép ügyintéző"]:
        return RedirectResponse(url="/lista", status_code=303)

    working_company_id = get_working_company_id(current_user, request)
    fuggo_berletek = db.query(models.BerletiIdoszak).filter(
        models.BerletiIdoszak.berlo_company_id == working_company_id,
        models.BerletiIdoszak.vege == None,
        models.BerletiIdoszak.jovahagyva == False
    ).order_by(models.BerletiIdoszak.letrehozva.desc()).all()

    # ÚJ (2026-10-10-i user-jelzés): jóváhagyáskor a bérlő megadja, a SAJÁT telephelyei közül
    # melyiken és milyen "Készenléti helyen" (l. "eddigi_helyszinek" minta, Machine.megnevezes)
    # lesz a gép - a választó listához a bérlő saját telephelyei és korábbi helyszín-értékei.
    telephelyek = db.query(models.Site).filter(models.Site.company_id == working_company_id).all()
    eddigi_keszenleti_helyek_records = db.query(models.Machine.megnevezes).filter(
        models.Machine.company_id == working_company_id,
        models.Machine.megnevezes != None
    ).distinct().all()
    eddigi_keszenleti_helyek = []
    for r in eddigi_keszenleti_helyek_records:
        if r[0].strip() != "":
            eddigi_keszenleti_helyek.append(r[0].strip())

    return templates.TemplateResponse(
        request=request,
        name="berlet_fuggoben.html",
        context={
            "user": current_user,
            "fuggo_berletek": fuggo_berletek,
            "telephelyek": telephelyek,
            "eddigi_keszenleti_helyek": eddigi_keszenleti_helyek,
        }
    )


@router.post("/berlet/{berlet_id}/jovahagyas")
def berlet_jovahagyasa(
    berlet_id: int,
    request: Request,
    berlo_site_id: str = Form(""),
    berlo_keszenleti_hely: str = Form(""),
    db: Session = Depends(get_db),
    current_user: models.User = Depends(get_current_user)
):
    if current_user.role not in ["Admin", "Emelőgép ügyintéző"]:
        return RedirectResponse(url="/lista", status_code=303)

    working_company_id = get_working_company_id(current_user, request)
    # J-09 (v65): inaktív bérlő cégnél / csak_olvasas fiókkal nem hagyunk jóvá és nem utasítunk el
    tiltas = irasi_tiltas_oka(current_user, working_company_id, db)
    if tiltas:
        return RedirectResponse(url=IRASI_TILTAS_LISTA_URL[tiltas], status_code=303)

    berlet = db.query(models.BerletiIdoszak).filter(
        models.BerletiIdoszak.id == berlet_id,
        models.BerletiIdoszak.berlo_company_id == working_company_id,
        models.BerletiIdoszak.vege == None
    ).first()
    if not berlet:
        return RedirectResponse(url="/berlet-fuggoben", status_code=303)

    # ÚJ (2026-10-10-i user-jelzés): a gép eddig a bérbeadó saját telephelyét/"Készenléti hely"
    # adatát mutatta a bérlő listájában is - jóváhagyáskor ezért kötelező megadni, a bérlő SAJÁT
    # telephelyei közül melyiken és milyen készenléti helyen lesz a gép (csak megjelenítés,
    # l. models.BerletiIdoszak). A kliens-oldali `required` mellett itt is kikényszerítjük.
    telephely = None
    if berlo_site_id.strip().isdigit():
        telephely = db.query(models.Site).filter(
            models.Site.id == int(berlo_site_id),
            models.Site.company_id == working_company_id
        ).first()
    berlo_keszenleti_hely = berlo_keszenleti_hely.strip()
    if not telephely or not berlo_keszenleti_hely:
        return RedirectResponse(url="/berlet-fuggoben?hiba=hianyos_hely", status_code=303)

    berlet.jovahagyva = True
    berlet.berlo_site_id = telephely.id
    berlet.berlo_keszenleti_hely = berlo_keszenleti_hely
    db.commit()

    return RedirectResponse(url="/berlet-fuggoben", status_code=303)


@router.post("/berlet/{berlet_id}/elutasitas")
def berlet_elutasitasa(
    berlet_id: int,
    request: Request,
    db: Session = Depends(get_db),
    current_user: models.User = Depends(get_current_user)
):
    """A bérlő elutasítja a felkínált kihelyezést - lezárjuk (vege = ma), így a bérbeadó
    szabadon indíthat új kihelyezést (akár ugyanehhez, akár másik céghez)."""
    if current_user.role not in ["Admin", "Emelőgép ügyintéző"]:
        return RedirectResponse(url="/lista", status_code=303)

    working_company_id = get_working_company_id(current_user, request)
    # J-09 (v65): inaktív bérlő cégnél / csak_olvasas fiókkal nem hagyunk jóvá és nem utasítunk el
    tiltas = irasi_tiltas_oka(current_user, working_company_id, db)
    if tiltas:
        return RedirectResponse(url=IRASI_TILTAS_LISTA_URL[tiltas], status_code=303)

    berlet = db.query(models.BerletiIdoszak).filter(
        models.BerletiIdoszak.id == berlet_id,
        models.BerletiIdoszak.berlo_company_id == working_company_id,
        models.BerletiIdoszak.vege == None
    ).first()
    if berlet:
        berlet.vege = date.today()
        db.commit()

    return RedirectResponse(url="/berlet-fuggoben", status_code=303)


@router.get("/gep/{uuid}/berlet/{berlet_id}/alnaplo", response_class=HTMLResponse)
def berlet_alnaplo(
    uuid: str,
    berlet_id: int,
    request: Request,
    db: Session = Depends(get_db),
    current_user: models.User = Depends(get_current_user)
):
    """A bérleti időszak alatt keletkezett vizsgálati jegyzőkönyvek szűrt nézete (alnapló)."""
    working_company_id = get_working_company_id(current_user, request)
    berelt_gep_idk = berelt_gep_idk_a_ceghez(working_company_id, db)

    gep = db.query(models.Machine).filter(
        models.Machine.uuid == uuid,
        or_(models.Machine.company_id == working_company_id, models.Machine.id.in_(berelt_gep_idk))
    ).first()
    if not gep:
        return RedirectResponse(url="/lista", status_code=303)

    if not is_machine_allowed(gep, current_user) and not is_gep_allowed_berlo_szamara(gep, current_user, db):
        return RedirectResponse(url="/lista", status_code=303)

    berlet = db.query(models.BerletiIdoszak).filter(
        models.BerletiIdoszak.id == berlet_id, models.BerletiIdoszak.machine_id == gep.id
    ).first()
    if not berlet:
        return RedirectResponse(url=f"/szerkesztes/{uuid}", status_code=303)

    vizsgalatok = db.query(models.Inspection).filter(
        models.Inspection.berleti_idoszak_id == berlet_id
    ).order_by(models.Inspection.datum.desc()).all()

    return templates.TemplateResponse(
        request=request,
        name="berlet_alnaplo.html",
        context={
            "user": current_user, "gep": gep, "berlet": berlet, "vizsgalatok": vizsgalatok,
        }
    )
