"""Jelszó-házirend beállító oldala (v36) - a cég Admin-jának (és a rendszeradminnak a kiválasztott cég munkakörnyezetében). Leírás: docs/JELSZO_HAZIREND.md

    GET  /jelszo-hazirend   - az oldal: kötelező jelszócsere, bonyolultság, előzmény; gyengeség-figyelmeztetések; a felhasználók lejáratai
    POST /jelszo-hazirend   - mentés (`muvelet`=mentes) vagy csak a figyelmeztetések ellenőrzése mentés nélkül (`muvelet`=ellenorzes)

A logika a jelszo_hazirend.py-ban van; itt a jogosultság (csak Admin), a bevitel ellenőrzése és az űrlapkezelés. A mentés POST (a GET nem ír),
idegen eredetű (cross-site) kérés nem ír, a csak megtekintési fiók és az inaktív cég nem módosíthat. A módosítás a Jogosultsági naplóba kerül.
"""
from typing import Optional

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

import jelszo_hazirend as jh
import models
from database import get_db
from routers import mfa as mfa_router
from security import get_current_user, get_working_company_id, is_company_active
from templates_env import templates

router = APIRouter()


def _urlapbol(urlap):
    """(Szabalyok, hiba) a beküldött űrlapból. Érvénytelen érték -> hiba (nem mentünk)."""
    try:
        nap = None
        if urlap.get("lejarat_be") == "on":
            try:
                nap = int(str(urlap.get("ervenyesseg_nap", "")).strip())
            except ValueError:
                return None, f"Az érvényesség napokban értendő egész szám ({jh.ERVENYESSEG_MIN_NAP}-{jh.ERVENYESSEG_MAX_NAP})."
            if not jh.ERVENYESSEG_MIN_NAP <= nap <= jh.ERVENYESSEG_MAX_NAP:
                return None, f"A jelszó érvényessége legalább {jh.ERVENYESSEG_MIN_NAP}, legfeljebb {jh.ERVENYESSEG_MAX_NAP} nap (fél év) lehet."
        try:
            min_hossz = int(str(urlap.get("min_hossz", jh.ALAP_MIN_HOSSZ)).strip())
        except ValueError:
            return None, "A minimum hossz egész szám."
        if not jh.ALAP_MIN_HOSSZ <= min_hossz <= jh.MAX_MIN_HOSSZ:
            return None, f"A minimum hossz {jh.ALAP_MIN_HOSSZ} és {jh.MAX_MIN_HOSSZ} karakter között lehet."
        try:
            elozmeny = int(str(urlap.get("elozmeny_db", 0)).strip() or 0)
        except ValueError:
            return None, "Az előzmény darabszáma egész szám."
        if not 0 <= elozmeny <= jh.ELOZMENY_MAX:
            return None, f"Az előzmény 0 (kikapcsolva) és {jh.ELOZMENY_MAX} között lehet."
    except Exception:
        return None, "Érvénytelen beküldött adat."
    return jh.Szabalyok(ervenyesseg_nap=nap, min_hossz=min_hossz, kisbetu=urlap.get("kisbetu") == "on", nagybetu=urlap.get("nagybetu") == "on",
                        szam=urlap.get("szam") == "on", specialis=urlap.get("specialis") == "on", elozmeny_db=elozmeny), None


def _felhasznalok_lejarata(db: Session, ceg_id: int):
    """A cég felhasználói a lejárat szerint (csak akinek van): [(felhasználó, lejárat szövege, hátralévő nap, lejárt?)]. Csak megjelenítéshez."""
    most = jh._utc_most()
    sorok = []
    for u in db.query(models.User).filter(models.User.company_id == ceg_id, models.User.jelszo_lejarat_at.isnot(None)).order_by(models.User.jelszo_lejarat_at).all():
        sorok.append({"nev": u.username, "email": u.email, "lejarat": jh._helyi_datum(u.jelszo_lejarat_at),
                      "nap": (u.jelszo_lejarat_at - most).days, "lejart": u.jelszo_lejarat_at <= most})
    return sorok


def kontextus(request: Request, db: Session, user: models.User, szab=None, mentve: Optional[int] = None, hiba: Optional[str] = None,
              elonezet: bool = False, n: Optional[int] = None, vissza_beallitasok: bool = False) -> dict:
    """A jelszó-házirend tartalmának (templates/_jelszo_hazirend_tartalom.html) bemenete: EGY `jh` szótár. A /jelszo-hazirend oldal és a Beállítások
    "Jelszó-házirend" füle (routers/settings.py) is ezt használja. `vissza_beallitasok`: a Beállítások fülről jövő űrlap (a mentés után oda térünk vissza)."""
    ceg_id = get_working_company_id(user, request)
    ceg = db.get(models.Company, ceg_id) if ceg_id else None
    tarolt = jh.szabalyok(ceg)
    szab = szab or tarolt
    return {
        "ceg": ceg, "szab": szab, "tarolt": tarolt,
        "figyelmeztetesek": jh.gyengesegek(szab), "becsult_bit": int(jh.becsult_bit(szab)),
        "felhasznalok": _felhasznalok_lejarata(db, ceg.id) if ceg else [],
        "inaktiv_ceg": ceg is None or ceg.aktiv is False, "csak_olvasas": bool(user.csak_olvasas),
        "mentve": mentve, "hiba": hiba, "elonezet": elonezet, "erintett": n,
        "min_nap": jh.ERVENYESSEG_MIN_NAP, "max_nap": jh.ERVENYESSEG_MAX_NAP, "max_hossz": jh.MAX_MIN_HOSSZ, "alap_hossz": jh.ALAP_MIN_HOSSZ,
        "elozmeny_max": jh.ELOZMENY_MAX, "emlekezteto_nap": jh.EMLEKEZTETO_NAP, "turelmi_nap": jh.TURELMI_NAP,
        "vissza_beallitasok": vissza_beallitasok,
    }


def _oldal(request: Request, db: Session, user: models.User, szab=None, mentve: Optional[int] = None, hiba: Optional[str] = None,
           elonezet: bool = False, n: Optional[int] = None, status_code: int = 200, vissza_beallitasok: bool = False):
    """A válasz: a /jelszo-hazirend oldal; ha az űrlap a Beállítások fülről jött (`vissza_beallitasok`), akkor a Beállítások oldal a "Jelszó-házirend" fülön
    (hibával / előnézettel együtt is) - így a felhasználó nem kerül ki a Beállításokból."""
    jhk = kontextus(request, db, user, szab=szab, mentve=mentve, hiba=hiba, elonezet=elonezet, n=n, vissza_beallitasok=vissza_beallitasok)
    if vissza_beallitasok:
        from routers import settings as settings_router          # késői import: a settings a kontextus()-t használja (körkörös import ellen)
        return settings_router.beallitasok_valasz(request, db, user, jh_kontextus=jhk, status_code=status_code)
    return templates.TemplateResponse(
        request=request,
        name="jelszo_hazirend.html",
        status_code=status_code,
        context={"user": user, "ceg": jhk["ceg"], "jh": jhk},
        headers={"Cache-Control": "no-store"},
    )


@router.get("/jelszo-hazirend", response_class=HTMLResponse)
def hazirend_oldal(request: Request, mentve: Optional[int] = None, n: Optional[int] = None,
                   db: Session = Depends(get_db), current_user: models.User = Depends(get_current_user)):
    """Csak megjelenít (nem ír)."""
    if current_user.role != "Admin":
        return RedirectResponse(url="/valassz-modult", status_code=303)
    return _oldal(request, db, current_user, mentve=mentve, n=n)


def _valtozasok(regi: "jh.Szabalyok", uj: "jh.Szabalyok") -> str:
    def f(s):
        return (f"lejárat: {s.ervenyesseg_nap if s.ervenyesseg_nap else 'nincs'} nap; min. hossz: {s.min_hossz}; "
                f"kisbetű: {'igen' if s.kisbetu else 'nem'}; nagybetű: {'igen' if s.nagybetu else 'nem'}; szám: {'igen' if s.szam else 'nem'}; "
                f"speciális: {'igen' if s.specialis else 'nem'}; előzmény: {s.elozmeny_db}")
    return f(regi), f(uj)


@router.post("/jelszo-hazirend")
async def hazirend_mentese(request: Request, db: Session = Depends(get_db), current_user: models.User = Depends(get_current_user)):
    if current_user.role != "Admin":
        return RedirectResponse(url="/valassz-modult", status_code=303)
    urlap = await request.form()
    # v41: a Beállítások "Jelszó-házirend" füléről érkező űrlap rejtett `vissza=beallitasok` mezővel jön; csak ez az egy érték számít (nincs szabad átirányítás)
    vb = urlap.get("vissza") == "beallitasok"
    if mfa_router._idegen_eredet(request):
        return _oldal(request, db, current_user, hiba="A kérés nem erről az oldalról érkezett.", status_code=403, vissza_beallitasok=vb)
    ceg_id = get_working_company_id(current_user, request)
    if not ceg_id or not is_company_active(ceg_id, db):
        return _oldal(request, db, current_user, hiba="Ez a cég inaktív, a házirend nem módosítható.", status_code=403, vissza_beallitasok=vb)
    if current_user.csak_olvasas:
        return _oldal(request, db, current_user, hiba="Csak megtekintési jogosultsággal nem módosítható a házirend.", status_code=403, vissza_beallitasok=vb)

    szab, hiba = _urlapbol(urlap)
    if hiba:
        return _oldal(request, db, current_user, hiba=hiba, status_code=400, vissza_beallitasok=vb)
    if urlap.get("muvelet") == "ellenorzes":
        return _oldal(request, db, current_user, szab=szab, elonezet=True, vissza_beallitasok=vb)   # nem mentünk: csak a figyelmeztetések az új értékekre

    ceg = db.get(models.Company, ceg_id)
    regi = jh.szabalyok(ceg)
    try:
        ceg.jelszo_ervenyesseg_nap = szab.ervenyesseg_nap
        ceg.jelszo_min_hossz = szab.min_hossz if szab.min_hossz > jh.ALAP_MIN_HOSSZ else None
        ceg.jelszo_kell_kisbetu = szab.kisbetu
        ceg.jelszo_kell_nagybetu = szab.nagybetu
        ceg.jelszo_kell_szam = szab.szam
        ceg.jelszo_kell_specialis = szab.specialis
        ceg.jelszo_elozmeny_db = szab.elozmeny_db or None
        ceg.jelszo_hazirend_valtozott_at = jh._utc_most()
        erintett = None
        if regi.ervenyesseg_nap != szab.ervenyesseg_nap:
            erintett = jh.alkalmaz(db, ceg)                                         # a lejáratok újraszámolása (türelmi idővel), ha az érvényesség változott
        if regi != szab:
            r, u = _valtozasok(regi, szab)
            db.add(models.AuditLog(company_id=ceg.id, user_id=current_user.id, field_name="Jelszó-házirend", old_value=r, new_value=u))
        db.commit()
    except Exception as ex:
        db.rollback()
        print(f"❌ A jelszó-házirend mentése sikertelen (cég #{ceg_id}): {type(ex).__name__}: {ex}")
        return _oldal(request, db, db.get(models.User, current_user.id), hiba="A mentés nem sikerült, próbáld újra.", status_code=500, vissza_beallitasok=vb)
    if vb:
        return RedirectResponse(url="/beallitasok?uzenet=jelszo_hazirend_mentve" + (f"&n={erintett}" if erintett is not None else "") + "#tab-jelszo-hazirend", status_code=303)
    url = "/jelszo-hazirend?mentve=1" + (f"&n={erintett}" if erintett is not None else "")
    return RedirectResponse(url=url, status_code=303)
