"""Rendszeradmin: az e-mail küldés (SMTP) beállítása a felületről (2026-10-04).

OLDAL:  GET  /rendszeradmin/email-beallitasok          - a beállító űrlap
MENTÉS: POST /rendszeradmin/email-beallitasok          - az SMTP-adatok mentése
TESZT:  POST /rendszeradmin/email-beallitasok/teszt    - teszt-levél küldése a MENTETT beállítással

B SZELET (2026-10-04) - kimenő levelek sora:
SOR:    GET  /rendszeradmin/email-sor                  - áttekintés: állapot, korlátok, utolsó levelek
KORLÁT: POST /rendszeradmin/email-korlatok             - óránkénti/napi levélkorlát + emlékeztetési idő mentése
ÚJRA:   POST /rendszeradmin/email-sor/ujraprobal       - a "hibás" levelek újra sorba állítása

JOGOSULTSÁG: kizárólag a valódi rendszeradminisztrátor (security.is_rendszeradminisztrator: Admin
szerepkör ÉS company_id == 1). Egy céges Admin NEM férhet hozzá - az SMTP-fiók az egész
rendszeré, nem egy cégé. A jogosultságot MINDEN végpont külön ellenőrzi (nem elég az oldal
elrejtése).

BIZTONSÁGI DÖNTÉSEK (részletek: docs/EMAIL_RENDSZER.md):
    - Minden módosító művelet POST (nem GET): a SameSite=Lax cookie miatt egy külső oldalról
      indított top-level GET navigációval állapotot módosítani lehetne (l. a 2026-09-24-i és
      2026-10-03-i auditok CSRF-javításait) - POST-ot a böngésző cross-site nem küldi el a cookie-val.
    - A jelszót az oldal SOHA nem küldi vissza a böngészőnek (nincs value="..." az input-mezőn);
      csak azt jelzi, hogy van-e megadva. Üresen hagyott jelszó-mező = "ne módosítsd".
    - A mentés a Jogosultsági naplóba (AuditLog) kerül - a módosított MEZŐK nevével, de a
      jelszó értéke nélkül.
    - A teszt-levél a MENTETT beállítást használja (nem az űrlap aktuális, el nem mentett
      tartalmát), így a teszt pontosan azt igazolja, amit a rendszer éles küldéskor használni fog.
"""
import re
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText

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

import models
import email_beallitasok
import email_sor
from database import get_db
from security import get_current_user, is_rendszeradminisztrator
from routers.rendszeradmin_mfa import _idegen_eredet           # ugyanaz a Sec-Fetch-Site CSRF-védelem, mint a többi RA műveletnél
from templates_env import templates

router = APIRouter()

_EMAIL_MINTA = re.compile(r"^[^@\s<>\"'\\]+@[^@\s<>\"'\\]+\.[^@\s<>\"'\\]+$")


def _kontextus(db: Session, current_user, **tovabbi):
    """A sablonnak átadott közös adatok: az aktuális (feloldott) beállítás + az utolsó módosítás
    adatai. A jelszó SOHA nem kerül bele - csak a 'jelszo_megadva' / 'jelszo_visszafejtheto' jelzők."""
    beall = email_beallitasok.betolt(db)

    utolso = db.query(models.RendszerBeallitas).filter(
        models.RendszerBeallitas.kulcs.in_(email_beallitasok.BEALLITAS_KULCSOK)
    ).order_by(models.RendszerBeallitas.modositva_at.desc()).first()

    kontextus = {
        "user": current_user,
        "beall": beall,
        "utolso_modositas": utolso.modositva_at if utolso else None,
        "utolso_modosito": (utolso.modosito.username if utolso and utolso.modosito else None),
        "mentve": False,
        "hibak": [],
        "teszt_eredmeny": None,
        "teszt_cimzett": current_user.email or "",
        # Az űrlap mezői: alapból az aktuális beállítás; hibás mentés után a beküldött értékek
        "urlap": {
            "szerver": beall.szerver,
            "port": str(beall.port),
            "felhasznalo": beall.felhasznalo,
            "biztonsag": beall.biztonsag,
            "felado_cim": beall.felado_cim,
            "tls_ellenorzes": "1" if beall.tls_ellenorzes else "0",
            "alkalmazas_url": beall.alkalmazas_url,
        },
    }
    kontextus.update(tovabbi)
    return kontextus


@router.get("/rendszeradmin/email-beallitasok", response_class=HTMLResponse)
def email_beallitasok_oldal(
    request: Request,
    mentve: int = 0,
    db: Session = Depends(get_db),
    current_user: models.User = Depends(get_current_user)
):
    if not is_rendszeradminisztrator(current_user):
        return RedirectResponse(url="/valassz-modult", status_code=303)

    return templates.TemplateResponse(
        request=request,
        name="rendszeradmin_email.html",
        context=_kontextus(db, current_user, mentve=bool(mentve))
    )


@router.post("/rendszeradmin/email-beallitasok")
def email_beallitasok_mentese(
    request: Request,
    szerver: str = Form(""),
    port: str = Form("465"),
    felhasznalo: str = Form(""),
    jelszo: str = Form(""),
    biztonsag: str = Form("SSL"),
    felado_cim: str = Form(""),
    tls_ellenorzes: str = Form("1"),
    alkalmazas_url: str = Form(""),
    db: Session = Depends(get_db),
    current_user: models.User = Depends(get_current_user)
):
    if not is_rendszeradminisztrator(current_user):
        return JSONResponse(status_code=403, content={"message": "Csak a rendszeradminisztrátor!"})
    if current_user.csak_olvasas:
        return JSONResponse(status_code=403, content={"message": "Csak megtekintési jogosultsággal rendelkezel, szerkesztés nem lehetséges!"})

    nyers = {
        "szerver": szerver, "port": port, "felhasznalo": felhasznalo, "jelszo": jelszo,
        "biztonsag": biztonsag, "felado_cim": felado_cim, "tls_ellenorzes": tls_ellenorzes,
        "alkalmazas_url": alkalmazas_url,
    }
    tiszta, hibak = email_beallitasok.ellenoriz(nyers)

    if hibak:
        # Nem mentünk semmit; az űrlapot a beküldött (tisztított) értékekkel újra megjelenítjük,
        # a jelszó kivételével (azt sosem küldjük vissza a böngészőnek).
        urlap = {k: tiszta[k] for k in ("szerver", "port", "felhasznalo", "biztonsag", "felado_cim", "tls_ellenorzes", "alkalmazas_url")}
        return templates.TemplateResponse(
            request=request,
            name="rendszeradmin_email.html",
            context=_kontextus(db, current_user, hibak=hibak, urlap=urlap),
            status_code=400
        )

    valtozott = email_beallitasok.ment(db, tiszta, current_user.id)

    if valtozott:
        # A naplóbejegyzés és a beállítás EGY tranzakcióban kerül mentésre. A jelszó értéke nem naplózott.
        db.add(models.AuditLog(
            company_id=current_user.company_id,
            user_id=current_user.id,
            field_name="E-mail beállítás módosítva",
            old_value="-",
            new_value="Módosított mezők: " + ", ".join(valtozott) + " (a jelszó értéke nem naplózott)"
        ))
    db.commit()

    return RedirectResponse(url="/rendszeradmin/email-beallitasok?mentve=1", status_code=303)


@router.post("/rendszeradmin/email-beallitasok/teszt", response_class=HTMLResponse)
def teszt_level_kuldese(
    request: Request,
    cimzett: str = Form(""),
    db: Session = Depends(get_db),
    current_user: models.User = Depends(get_current_user)
):
    if not is_rendszeradminisztrator(current_user):
        return JSONResponse(status_code=403, content={"message": "Csak a rendszeradminisztrátor!"})
    # J-09 (v65): a teszt-levél KÜLSŐ hatású (e-mailt küld) - a csak_olvasas RA-fiók nem indíthatja; a testvér-route-ok
    # (beállítások/korlátok mentése, újrapróbálás) ezt már így csinálják. Cég-aktív ellenőrzés itt nem értelmezett.
    if current_user.csak_olvasas:
        return JSONResponse(status_code=403, content={"message": "Csak megtekintési jogosultsággal rendelkezel, szerkesztés nem lehetséges!"})

    cimzett = (cimzett or "").strip()
    if not _EMAIL_MINTA.match(cimzett) or len(cimzett) > 255:
        eredmeny = {"ok": False, "uzenet": "A teszt-levél címzettje nem érvényes e-mail cím."}
        return templates.TemplateResponse(
            request=request,
            name="rendszeradmin_email.html",
            context=_kontextus(db, current_user, teszt_eredmeny=eredmeny, teszt_cimzett=cimzett),
            status_code=400
        )

    beall = email_beallitasok.betolt(db)

    if not beall.konfiguralt:
        eredmeny = {"ok": False, "uzenet": "Nincs SMTP-szerver és felhasználó beállítva (sem az adatbázisban, sem a .env-ben) - előbb mentsd el a beállítást."}
    elif not beall.jelszo_visszafejtheto:
        eredmeny = {"ok": False, "uzenet": "A mentett jelszó nem fejthető vissza (valószínűleg megváltozott a titkosítási kulcs / SECRET_KEY) - írd be újra a jelszót és mentsd el."}
    else:
        try:
            msg = MIMEMultipart("alternative")
            msg["Subject"] = "EmeLOG - teszt e-mail"
            msg["From"] = beall.felado_fejlec
            msg["To"] = cimzett
            msg.attach(MIMEText(
                "Ez egy automatikus teszt-levél az EmeLOG rendszeradmin felületéről. "
                "Ha ezt olvasod, az e-mail küldés beállítása működik.",
                "plain", "utf-8"
            ))
            email_beallitasok.kuld(msg, beall)
            eredmeny = {"ok": True, "uzenet": f"A teszt-levél elküldve ({beall.szerver}:{beall.port}, {beall.biztonsag})."}
        except Exception as e:
            # A teljes kivételt a szerver naplójába írjuk; a (kizárólag rendszeradminnak látható)
            # oldalra a típus és egy rövidített szöveg kerül - az smtplib hibaüzenetei a szerver
            # válaszát tartalmazzák, jelszót nem.
            print(f"❌ Hiba a teszt-levél küldésekor: {type(e).__name__}: {e}")
            eredmeny = {"ok": False, "uzenet": f"A küldés sikertelen: {type(e).__name__}: {str(e)[:300]}"}

    return templates.TemplateResponse(
        request=request,
        name="rendszeradmin_email.html",
        context=_kontextus(db, current_user, teszt_eredmeny=eredmeny, teszt_cimzett=cimzett)
    )


# =============================================================================================
# B SZELET (2026-10-04): kimenő levelek sora, sebességkorlát, ismétlődő hibák szűrése
# A jogosultsági és CSRF-szabályok ugyanazok, mint fent: csak a rendszeradmin, módosító művelet POST.
# =============================================================================================
def _sor_kontextus(db: Session, current_user, **tovabbi):
    korlat = email_sor.korlatok_betolt(db)
    beall = email_beallitasok.betolt(db)
    kontextus = {
        "user": current_user,
        "beall": beall,
        "korlat": korlat,
        "stat": email_sor.statisztika(db),
        "levelek": email_sor.legutobbi_levelek(db, 50),
        "tick_max": email_sor.TICK_MAX,
        "max_probalkozas": email_sor.MAX_PROBALKOZAS,
        "szimultan_ertesites": email_sor.szimultan_ertesites_be_van(db),
        "mentve": False,
        "ujra_db": None,
        "hibak": [],
        # az űrlap mezői: alapból az aktuális értékek; hibás mentés után a beküldöttek
        "urlap": {"oraban": str(korlat.oraban), "naponta": str(korlat.naponta), "ismetles_nap": str(korlat.ismetles_nap)},
    }
    kontextus.update(tovabbi)
    return kontextus


@router.get("/rendszeradmin/email-sor", response_class=HTMLResponse)
def email_sor_oldal(
    request: Request,
    mentve: int = 0,
    ujra: int = -1,
    db: Session = Depends(get_db),
    current_user: models.User = Depends(get_current_user)
):
    if not is_rendszeradminisztrator(current_user):
        return RedirectResponse(url="/valassz-modult", status_code=303)

    return templates.TemplateResponse(
        request=request,
        name="rendszeradmin_email_sor.html",
        context=_sor_kontextus(db, current_user, mentve=bool(mentve), ujra_db=(ujra if ujra >= 0 else None))
    )


@router.post("/rendszeradmin/email-korlatok")
def email_korlatok_mentese(
    request: Request,
    oraban: str = Form(""),
    naponta: str = Form(""),
    ismetles_nap: str = Form(""),
    db: Session = Depends(get_db),
    current_user: models.User = Depends(get_current_user)
):
    if not is_rendszeradminisztrator(current_user):
        return JSONResponse(status_code=403, content={"message": "Csak a rendszeradminisztrátor!"})
    if current_user.csak_olvasas:
        return JSONResponse(status_code=403, content={"message": "Csak megtekintési jogosultsággal rendelkezel, szerkesztés nem lehetséges!"})

    tiszta, hibak = email_sor.korlatok_ellenoriz({"oraban": oraban, "naponta": naponta, "ismetles_nap": ismetles_nap})
    if hibak:
        return templates.TemplateResponse(
            request=request,
            name="rendszeradmin_email_sor.html",
            context=_sor_kontextus(db, current_user, hibak=hibak, urlap=tiszta),
            status_code=400
        )

    regi = email_sor.korlatok_betolt(db)
    valtozott = email_sor.korlatok_ment(db, tiszta, current_user.id)
    if valtozott:
        db.add(models.AuditLog(
            company_id=current_user.company_id,
            user_id=current_user.id,
            field_name="E-mail korlát módosítva",
            old_value=f"óra: {regi.oraban}, nap: {regi.naponta}, emlékeztetés: {regi.ismetles_nap} nap",
            new_value=f"óra: {tiszta['oraban']}, nap: {tiszta['naponta']}, emlékeztetés: {tiszta['ismetles_nap']} nap"
        ))
    db.commit()
    return RedirectResponse(url="/rendszeradmin/email-sor?mentve=1", status_code=303)


@router.post("/rendszeradmin/email-sor/szimultan-ertesites")
def szimultan_ertesites_kapcsolasa(
    request: Request,
    aktiv: str = Form(""),
    db: Session = Depends(get_db),
    current_user: models.User = Depends(get_current_user)
):
    """A szimultán belépés (E-LIC-01) értesítő levelének ki/be kapcsolása (aktiv=true|false). A common.js `toggle-post` kapcsolója hívja,
    ezért JSON-t ad. A Jogosultsági naplóba a szimultán belépés a kapcsolótól függetlenül mindig bekerül; ez csak a rendszeradmin LEVELÉT szabályozza."""
    if not is_rendszeradminisztrator(current_user):
        return JSONResponse(status_code=403, content={"message": "Csak a rendszeradminisztrátor!"})
    if _idegen_eredet(request):
        return JSONResponse(status_code=403, content={"message": "A kérés nem erről az oldalról érkezett."})
    if current_user.csak_olvasas:
        return JSONResponse(status_code=403, content={"message": "Csak megtekintési jogosultsággal rendelkezel, szerkesztés nem lehetséges!"})
    if aktiv.strip().lower() not in ("true", "false"):
        return JSONResponse(status_code=400, content={"message": "Érvénytelen érték."})

    be = aktiv.strip().lower() == "true"
    regi = email_sor.szimultan_ertesites_be_van(db)
    if email_sor.szimultan_ertesites_beallitasa(db, be, current_user.id):
        db.add(models.AuditLog(
            company_id=current_user.company_id,
            user_id=current_user.id,
            field_name="Szimultán belépés értesítő levele",
            old_value="bekapcsolva" if regi else "kikapcsolva",
            new_value="bekapcsolva" if be else "kikapcsolva"
        ))
    db.commit()
    return JSONResponse(status_code=200, content={"message": "Mentve.", "aktiv": be})


@router.post("/rendszeradmin/email-sor/ujraprobal")
def email_sor_hibasak_ujraprobalasa(
    db: Session = Depends(get_db),
    current_user: models.User = Depends(get_current_user)
):
    if not is_rendszeradminisztrator(current_user):
        return JSONResponse(status_code=403, content={"message": "Csak a rendszeradminisztrátor!"})
    if current_user.csak_olvasas:
        return JSONResponse(status_code=403, content={"message": "Csak megtekintési jogosultsággal rendelkezel, szerkesztés nem lehetséges!"})

    darab = email_sor.hibasak_ujrasorba_allitasa(db)
    if darab:
        db.add(models.AuditLog(
            company_id=current_user.company_id,
            user_id=current_user.id,
            field_name="Hibás e-mailek újra sorba állítva",
            old_value="-",
            new_value=f"{darab} levél"
        ))
    db.commit()
    return RedirectResponse(url=f"/rendszeradmin/email-sor?ujra={darab}", status_code=303)
