"""VÉSZFELOLDÁS a szerverről: kétlépcsős hitelesítés (2FA) kikapcsolása / visszaállítása parancssorból.

MIKOR KELL? A rendszeradmin (szuperadmin) NEM zárhatja ki magát. Normál esetben a 2FA kapcsolóját és a
felhasználók beállításait a felületről kezeli a rendszeradmin (a kapcsolót a /rendszeradmin/ketlepcsos, a felhasználók elveszett telefonját a jelszó-visszaállítás kezeli). De ha a felület nem érhető el - pl.
a rendszeradmin elvesztette a telefonját, vagy a SECRET_KEY megváltozása miatt a titkok nem olvashatók, vagy
a rendszeradmin saját cégére kötelezővé tették a 2FA-t, és senki nem tud belépni -, a szerveren (SSH) ez a szkript
mindig megoldja. A szerverhez hozzáférő amúgy is eléri az adatbázist, ezért ez nem gyengíti a védelmet.

HASZNÁLAT (az alkalmazás könyvtárában, a virtuális környezettel):

    cd /var/www/emelog
    source venv/bin/activate
    python mfa_felold.py                         # állapot: hol kötelező a 2FA, kinek mi a helyzete
    python mfa_felold.py ceg <id> ki             # egy cég kötelező-kapcsolójának KIKAPCSOLÁSA
    python mfa_felold.py --mind-ki               # MINDEN cég kötelező-kapcsolójának kikapcsolása
    python mfa_felold.py felhasznalo <e-mail>    # egy felhasználó 2FA-beállításának törlése + minden munkamenetének
                                                 # érvénytelenítése (elveszett telefon)

MI TÖRTÉNIK?
  * A kapcsoló kikapcsolása után a belépéskor senkinek nem kell kódot beírnia (a kikapcsolás a futó
    szerverfolyamatokon legfeljebb 15 mp alatt érvényesül, újraindítás nem kell).
  * A felhasználó-visszaállítás törli a titkát, és a meglévő munkameneteit megszünteti. Ha a cégénél a 2FA kötelező
    marad, a felhasználó a következő belépéskor a QR-beállító oldalra kerül (3. fázis), és új titkot állít be.
    FIGYELEM: a jelszót a visszaállítás NEM érinti. Ha a jelszó kiszivároghatott, azt is cserélni kell (különben a jelszót
    ismerő támadó állíthatja be újra az első faktort). A SZERVERRŐL ez az egyetlen út egy RENDSZERADMIN elveszett telefonjához (a felületről a
    rendszeradmin 2FA-ja szándékosan nem törölhető - docs/KETLEPCSOS_HITELESITES.md, 5e.2); a többi felhasználónál a rendszergazdai jelszócsere elég (5e).
  * Bekapcsolni a szkripttel NEM lehet (szándékosan: ez kizárólag mentőeszköz).
  * Minden művelet bekerül a Jogosultsági naplóba ("szerver-parancssor (2FA vészfeloldás)").

Részletek: docs/KETLEPCSOS_HITELESITES.md
"""
import sys

import models
import mfa_utils
from database import SessionLocal

NAPLO_MEZO = "2FA vészfeloldás"
NAPLO_FORRAS = "szerver-parancssor (2FA vészfeloldás)"


def _naplo(db, company_id, user_id, regi, uj):
    db.add(models.AuditLog(company_id=company_id, user_id=user_id, field_name=NAPLO_MEZO,
                           old_value=regi, new_value=f"{uj} - {NAPLO_FORRAS}"))


def allapot_kiirasa(db) -> None:
    kotelezo = mfa_utils.kotelezo_ceg_idk(db)
    print("=== Cégek, ahol a kétlépcsős hitelesítés KÖTELEZŐ ===")
    if not kotelezo:
        print("  (nincs ilyen cég - mindenki jelszóval lép be)")
    for ceg in db.query(models.Company).filter(models.Company.id.in_(kotelezo or [0])).order_by(models.Company.id):
        print(f"  #{ceg.id}  {ceg.nev}")

    print("\n=== Rendszeradminok (Admin, 1-es cég) ===")
    for u in db.query(models.User).filter(models.User.role == "Admin", models.User.company_id == 1).order_by(models.User.id):
        print(f"  #{u.id}  {u.email}  [{'aktív' if u.aktiv else 'inaktív'}]  2FA: {mfa_utils.allapot(db, u)}")

    if kotelezo:
        print("\n=== Érintett felhasználók, akik még nem 'kesz' állapotúak (nem tudnak belépni) ===")
        szam = 0
        for u in db.query(models.User).order_by(models.User.id):
            if u.company_id == 1 and u.role == "Admin":
                continue
            all_ = mfa_utils.allapot(db, u)
            if all_ in (mfa_utils.ALLAPOT_BEALLITANDO, mfa_utils.ALLAPOT_HELYREALLITANDO):
                szam += 1
                print(f"  #{u.id}  {u.email}  (cég #{u.company_id})  2FA: {all_}")
        if not szam:
            print("  (nincs)")
    print("\nSúgó: python mfa_felold.py ceg <id> ki | --mind-ki | felhasznalo <e-mail>")


def ceg_kikapcsolasa(db, ceg_id: int) -> int:
    ceg = db.get(models.Company, ceg_id)
    if not ceg:
        print(f"Nincs ilyen cég: #{ceg_id}")
        return 1
    if not mfa_utils.ceg_kapcsolo_beallitasa(db, ceg, False):
        print(f"A(z) #{ceg.id} {ceg.nev} cégnél nincs bekapcsolva a kétlépcsős hitelesítés - nincs teendő.")
        return 0
    _naplo(db, ceg.id, None, "kötelező", "kikapcsolva")
    db.commit()
    print(f"Kikapcsolva: #{ceg.id} {ceg.nev}. (A futó szerverfolyamatokon legfeljebb {mfa_utils.GYORSITOTAR_MASODPERC} mp alatt érvényesül.)")
    return 0


def mind_kikapcsolasa(db) -> int:
    ceg_ek = db.query(models.Company).filter(models.Company.ketlepcsos_hitelesites_kotelezo.is_(True)).all()
    if not ceg_ek:
        print("Egy cégnél sincs bekapcsolva - nincs teendő.")
        return 0
    for ceg in ceg_ek:
        mfa_utils.ceg_kapcsolo_beallitasa(db, ceg, False)
        _naplo(db, ceg.id, None, "kötelező", "kikapcsolva (összes cég)")
        print(f"Kikapcsolva: #{ceg.id} {ceg.nev}")
    db.commit()
    return 0


def felhasznalo_visszaallitasa(db, email: str) -> int:
    u = db.query(models.User).filter(models.User.email == email).first()
    if not u:
        print(f"Nincs ilyen felhasználó: {email}")
        return 1
    elozo = mfa_utils.allapot(db, u)
    mfa_utils.felhasznalo_visszaallitasa(u)
    _naplo(db, u.company_id, u.id, f"állapot: {elozo}", "2FA-beállítás törölve, munkamenetek érvénytelenítve")
    db.commit()
    print(f"Visszaállítva: {u.email} (volt: {elozo}). A meglévő munkamenetei megszűntek.")
    return 0


def main(argv) -> int:
    db = SessionLocal()
    try:
        if len(argv) < 2:
            allapot_kiirasa(db)
            return 0
        parancs = argv[1]
        if parancs == "--mind-ki":
            return mind_kikapcsolasa(db)
        if parancs == "ceg" and len(argv) == 4 and argv[3] == "ki" and argv[2].isascii() and argv[2].isdecimal():
            return ceg_kikapcsolasa(db, int(argv[2]))
        if parancs == "felhasznalo" and len(argv) == 3:
            return felhasznalo_visszaallitasa(db, argv[2])
        print("Ismeretlen parancs. Súgó: python mfa_felold.py (paraméter nélkül)")
        return 2
    finally:
        db.close()


if __name__ == "__main__":
    sys.exit(main(sys.argv))
