"""Teste US-001 (PRD 3.1): coloana accounts.active + helper-e cont in app/accounts.py."""

from __future__ import annotations

import os
import tempfile

import pytest


@pytest.fixture()
def conn(monkeypatch):
    tmp = tempfile.mkdtemp()
    monkeypatch.setenv("AUTOPASS_DB_PATH", os.path.join(tmp, "test_accounts.db"))
    from app.config import get_settings
    get_settings.cache_clear()
    from app.db import get_connection, init_db
    init_db()
    c = get_connection()
    yield c
    c.close()
    get_settings.cache_clear()


def test_create_account_returneaza_id(conn):
    from app.accounts import create_account
    acct_id = create_account(conn, "Service X")
    assert isinstance(acct_id, int)
    # AUTOINCREMENT peste default id=1 -> primul cont creat are id>=2 (nu atinge default).
    assert acct_id >= 2


def test_create_account_activ_implicit(conn):
    from app.accounts import create_account
    acct_id = create_account(conn, "Service X")
    row = conn.execute("SELECT active FROM accounts WHERE id=?", (acct_id,)).fetchone()
    assert row["active"] == 1


def test_create_account_inactiv(conn):
    from app.accounts import create_account
    acct_id = create_account(conn, "Service X", active=False)
    row = conn.execute("SELECT active FROM accounts WHERE id=?", (acct_id,)).fetchone()
    assert row["active"] == 0


def test_create_account_name_gol_ridica_eroare(conn):
    from app.accounts import create_account
    with pytest.raises(ValueError):
        create_account(conn, "   ")
    # nu a inserat nimic peste default
    n = conn.execute("SELECT COUNT(*) AS n FROM accounts").fetchone()["n"]
    assert n == 1


def test_create_account_cui_duplicat_respins(conn):
    from app.accounts import create_account
    first = create_account(conn, "Service A", cui="RO123")
    with pytest.raises(ValueError) as exc:
        create_account(conn, "Service B", cui="RO123")
    # mesaj cu cauza + fix care numeste contul existent (A4)
    msg = str(exc.value)
    assert "RO123" in msg
    assert str(first) in msg


def test_create_cui_null_multiplu_permis(conn):
    from app.accounts import create_account
    a = create_account(conn, "Fara CUI 1")
    b = create_account(conn, "Fara CUI 2")
    assert a != b


def test_create_cui_normalizat(conn):
    from app.accounts import create_account
    create_account(conn, "Service A", cui=" ro123 ")
    # normalizat la RO123 -> duplicat respins indiferent de spatii/caz
    with pytest.raises(ValueError):
        create_account(conn, "Service B", cui="RO123")
    row = conn.execute("SELECT cui FROM accounts WHERE name='Service A'").fetchone()
    assert row["cui"] == "RO123"


def test_set_active_comuta(conn):
    from app.accounts import create_account, set_active
    acct_id = create_account(conn, "Service X")
    set_active(conn, acct_id, False)
    assert conn.execute("SELECT active FROM accounts WHERE id=?", (acct_id,)).fetchone()["active"] == 0
    set_active(conn, acct_id, True)
    assert conn.execute("SELECT active FROM accounts WHERE id=?", (acct_id,)).fetchone()["active"] == 1


def test_set_active_idempotent(conn):
    from app.accounts import create_account, set_active
    acct_id = create_account(conn, "Service X")  # deja activ
    set_active(conn, acct_id, True)  # nu trebuie sa arunce
    assert conn.execute("SELECT active FROM accounts WHERE id=?", (acct_id,)).fetchone()["active"] == 1


def test_set_active_inexistent_ridica(conn):
    from app.accounts import set_active
    with pytest.raises(ValueError):
        set_active(conn, 9999, True)


def test_list_accounts_ordonat_fara_creds(conn):
    from app.accounts import create_account, list_accounts
    create_account(conn, "Service B")
    create_account(conn, "Service A")
    rows = list_accounts(conn)
    ids = [r["id"] for r in rows]
    assert ids == sorted(ids)
    for r in rows:
        assert "rar_creds_enc" not in r
        assert set(r.keys()) == {
            "id", "name", "cui", "email", "active", "status", "created_at",
            "tier", "trial_until", "requested_plan", "consent_at",
        }


# ---------------------------------------------------------------------------
# US-001 (PRD 5.12): accounts.email + validari companie/email/CUI
# ---------------------------------------------------------------------------

def test_create_account_fara_email_ridica(conn):
    """create_account cu email="" ridica ValueError (email gol nu e acceptat)."""
    from app.accounts import create_account
    with pytest.raises(ValueError, match="email"):
        create_account(conn, "Service X", cui="RO100", email="")


def test_create_account_fara_cui_ridica(conn):
    """create_account cu cui="" ridica ValueError (CUI gol nu e acceptat)."""
    from app.accounts import create_account
    with pytest.raises(ValueError, match="[Cc][Uu][Ii]|cod unic"):
        create_account(conn, "Service X", cui="", email="test@test.com")


def test_email_normalizat_lowercase_trim(conn):
    """email e normalizat: trim + lower."""
    from app.accounts import create_account
    acct_id = create_account(conn, "Service X", cui="RO200", email="  Test@EXAMPLE.Com  ")
    row = conn.execute("SELECT email FROM accounts WHERE id=?", (acct_id,)).fetchone()
    assert row["email"] == "test@example.com"


def test_migrare_adauga_coloana_email_idempotent(conn):
    """_migrate e idempotent: ruleaza de doua ori fara eroare si coloana email exista."""
    from app.db import _migrate
    _migrate(conn)  # a doua rulare (prima e in init_db)
    cols = {r["name"] for r in conn.execute("PRAGMA table_info(accounts)").fetchall()}
    assert "email" in cols


def test_account_is_complete_false_pe_legacy_incomplet(conn):
    """account_is_complete() returneaza False pe cont fara email sau fara CUI."""
    from app.accounts import create_account, account_is_complete
    # cont fara email si fara CUI
    acct_id = create_account(conn, "Service Legacy")
    row = conn.execute("SELECT * FROM accounts WHERE id=?", (acct_id,)).fetchone()
    assert account_is_complete(row) is False

    # cont fara email, cu CUI
    acct_id2 = create_account(conn, "Service Cu CUI", cui="RO300")
    row2 = conn.execute("SELECT * FROM accounts WHERE id=?", (acct_id2,)).fetchone()
    assert account_is_complete(row2) is False

    # cont complet (cu email si CUI si name)
    acct_id3 = create_account(conn, "Service Complet", cui="RO301", email="x@y.com")
    row3 = conn.execute("SELECT * FROM accounts WHERE id=?", (acct_id3,)).fetchone()
    assert account_is_complete(row3) is True

    # contul sistem id=1 e EXCEPTAT (returneaza True indiferent)
    row_sys = conn.execute("SELECT * FROM accounts WHERE id=1").fetchone()
    assert account_is_complete(row_sys) is True


# ---------------------------------------------------------------------------
# 5.17 US-001/US-008: schema tier + trial_until + set_tier + CLI set-tier
# ---------------------------------------------------------------------------

def test_migrare_tier_trial_defensiva(conn):
    """_migrate adauga tier + trial_until pe conturi existente, e idempotenta."""
    from app.db import _migrate
    cols_before = {r["name"] for r in conn.execute("PRAGMA table_info(accounts)").fetchall()}
    assert "tier" in cols_before
    assert "trial_until" in cols_before

    # a doua rulare: idempotenta (nu arunca)
    _migrate(conn)
    cols_after = {r["name"] for r in conn.execute("PRAGMA table_info(accounts)").fetchall()}
    assert "tier" in cols_after
    assert "trial_until" in cols_after


def test_cont_nou_tier_free_si_trial_30z(conn):
    """create_account seteaza tier='free' si trial_until = acum + ~30 zile."""
    from datetime import datetime, timezone, timedelta
    from app.accounts import create_account

    before = datetime.now(timezone.utc)
    acct_id = create_account(conn, "Service Trial", cui="RO_T1")
    after = datetime.now(timezone.utc)

    row = conn.execute("SELECT tier, trial_until FROM accounts WHERE id=?", (acct_id,)).fetchone()
    assert row["tier"] == "free"
    assert row["trial_until"] is not None

    tu = datetime.fromisoformat(row["trial_until"].replace(" ", "T"))
    if tu.tzinfo is None:
        tu = tu.replace(tzinfo=timezone.utc)

    # trial_until trebuie sa fie intre now+29z si now+31z
    assert tu >= before + timedelta(days=29)
    assert tu <= after + timedelta(days=31)


def test_cont_nou_effective_tier_pro_in_trial(conn):
    """Cont nou are effective_tier='pro' (trial activ)."""
    from datetime import datetime, timezone
    from app.accounts import create_account
    from app.plans import effective_tier

    acct_id = create_account(conn, "Service Pro Trial", cui="RO_T2")
    row = conn.execute("SELECT * FROM accounts WHERE id=?", (acct_id,)).fetchone()

    now = datetime.now(timezone.utc)
    assert effective_tier(row, now) == "pro"


def test_set_tier_valid(conn):
    """set_tier seteaza tier-ul corect."""
    from app.accounts import create_account, set_tier

    acct_id = create_account(conn, "Service Tier", cui="RO_T3")
    set_tier(conn, acct_id, "pro")

    row = conn.execute("SELECT tier FROM accounts WHERE id=?", (acct_id,)).fetchone()
    assert row["tier"] == "pro"


def test_set_tier_cu_trial(conn):
    """set_tier cu trial_until seteaza ambele campuri."""
    from app.accounts import create_account, set_tier

    acct_id = create_account(conn, "Service Tier Trial", cui="RO_T4")
    set_tier(conn, acct_id, "standard", trial_until="2026-12-31 00:00:00")

    row = conn.execute("SELECT tier, trial_until FROM accounts WHERE id=?", (acct_id,)).fetchone()
    assert row["tier"] == "standard"
    assert row["trial_until"] == "2026-12-31 00:00:00"


def test_set_tier_no_trial_sterge_trial_until(conn):
    """set_tier cu trial_until=None sterge trial-ul existent."""
    from app.accounts import create_account, set_tier

    acct_id = create_account(conn, "Service No Trial", cui="RO_T5")
    # mai intai setam un trial
    set_tier(conn, acct_id, "pro", trial_until="2026-12-31 00:00:00")
    # acum stergem trial-ul
    set_tier(conn, acct_id, "pro", trial_until=None)

    row = conn.execute("SELECT tier, trial_until FROM accounts WHERE id=?", (acct_id,)).fetchone()
    assert row["tier"] == "pro"
    assert row["trial_until"] is None


def test_set_tier_invalid_respins(conn):
    """set_tier cu tier invalid ridica ValueError cu mesaj clar."""
    from app.accounts import create_account, set_tier

    acct_id = create_account(conn, "Service Tier Invalid", cui="RO_T6")
    with pytest.raises(ValueError, match="tier invalid"):
        set_tier(conn, acct_id, "gold")


def test_set_tier_protejeaza_id1(conn):
    """set_tier pe contul de sistem id=1 ridica ValueError (protejat)."""
    from app.accounts import set_tier

    with pytest.raises(ValueError):
        set_tier(conn, 1, "pro")


def test_set_tier_cont_inexistent_ridica(conn):
    """set_tier pe cont inexistent ridica ValueError."""
    from app.accounts import set_tier

    with pytest.raises(ValueError, match="inexistent"):
        set_tier(conn, 9999, "pro")


def test_list_accounts_include_tier_trial(conn):
    """list_accounts include coloanele tier si trial_until."""
    from app.accounts import create_account, list_accounts

    create_account(conn, "Service List", cui="RO_L1")
    rows = list_accounts(conn)
    for r in rows:
        assert "tier" in r
        assert "trial_until" in r


def test_default_account_tier_free_fara_trial(conn):
    """Contul implicit id=1 (creat de schema) are tier='free' si trial_until=NULL."""
    row = conn.execute("SELECT tier, trial_until FROM accounts WHERE id=1").fetchone()
    assert row["tier"] == "free"
    assert row["trial_until"] is None


def test_cli_set_tier(monkeypatch):
    """CLI set-tier seteaza tier-ul unui cont (--no-trial)."""
    tmp = tempfile.mkdtemp()
    monkeypatch.setenv("AUTOPASS_DB_PATH", os.path.join(tmp, "test_cli_tier.db"))
    from app.config import get_settings
    get_settings.cache_clear()

    from tools.account import main
    from app.db import init_db, get_connection
    from app.accounts import create_account

    init_db()
    conn_tmp = get_connection()
    acct_id = create_account(conn_tmp, "CLI Test", cui="RO_CLI1")
    conn_tmp.close()

    rc = main(["set-tier", "--account", str(acct_id), "--tier", "pro", "--no-trial"])
    assert rc == 0

    conn_tmp2 = get_connection()
    row = conn_tmp2.execute("SELECT tier, trial_until FROM accounts WHERE id=?", (acct_id,)).fetchone()
    conn_tmp2.close()
    assert row["tier"] == "pro"
    assert row["trial_until"] is None

    get_settings.cache_clear()


def test_cli_set_tier_cu_trial_days(monkeypatch):
    """CLI set-tier cu --trial-days 14 seteaza trial_until = acum + 14z."""
    from datetime import datetime, timezone, timedelta
    tmp = tempfile.mkdtemp()
    monkeypatch.setenv("AUTOPASS_DB_PATH", os.path.join(tmp, "test_cli_tier2.db"))
    from app.config import get_settings
    get_settings.cache_clear()

    from tools.account import main
    from app.db import init_db, get_connection
    from app.accounts import create_account

    init_db()
    conn_tmp = get_connection()
    acct_id = create_account(conn_tmp, "CLI Trial", cui="RO_CLI2")
    conn_tmp.close()

    before = datetime.now(timezone.utc)
    rc = main(["set-tier", "--account", str(acct_id), "--tier", "pro", "--trial-days", "14"])
    assert rc == 0
    after = datetime.now(timezone.utc)

    conn_tmp2 = get_connection()
    row = conn_tmp2.execute("SELECT tier, trial_until FROM accounts WHERE id=?", (acct_id,)).fetchone()
    conn_tmp2.close()
    assert row["tier"] == "pro"
    assert row["trial_until"] is not None
    tu = datetime.fromisoformat(row["trial_until"].replace(" ", "T")).replace(tzinfo=timezone.utc)
    assert tu >= before + timedelta(days=13)
    assert tu <= after + timedelta(days=15)

    get_settings.cache_clear()


def test_cli_set_tier_invalid(monkeypatch):
    """CLI set-tier cu tier invalid: exit code != 0."""
    tmp = tempfile.mkdtemp()
    monkeypatch.setenv("AUTOPASS_DB_PATH", os.path.join(tmp, "test_cli_tier3.db"))
    from app.config import get_settings
    get_settings.cache_clear()

    from tools.account import main
    from app.db import init_db, get_connection
    from app.accounts import create_account

    init_db()
    conn_tmp = get_connection()
    acct_id = create_account(conn_tmp, "CLI Invalid", cui="RO_CLI3")
    conn_tmp.close()

    rc = main(["set-tier", "--account", str(acct_id), "--tier", "diamond"])
    assert rc != 0

    get_settings.cache_clear()
