"""Teste PRD 5.19 US-002 — snapshot `held` la ingestie din comutatorul de cont.

Acopera TOATE situ-rile care scriu `status='queued'` prin ingestie (chokepoint
`held_for_account`): enqueue API, reactivare error->queued, dedup echo, commit import,
reresolve `needs_mapping`. `held` NU intra in idempotency_key.

Contul default id=1 e fortat pe Auto ON de fixtura autouse din conftest; testele care
vor Auto OFF il pun explicit pe 0 (`_set_auto_send(client, False)`).
"""

from __future__ import annotations

import io
import os
import tempfile

import openpyxl
import pytest
from fastapi.testclient import TestClient


@pytest.fixture()
def client(monkeypatch):
    tmp = tempfile.mkdtemp()
    monkeypatch.setenv("AUTOPASS_DB_PATH", os.path.join(tmp, "held.db"))
    monkeypatch.setenv("AUTOPASS_LOG_DIR", os.path.join(tmp, "logs"))
    monkeypatch.setenv("AUTOPASS_REQUIRE_API_KEY", "false")
    from app.config import get_settings
    get_settings.cache_clear()
    from app.main import app
    with TestClient(app) as c:
        yield c
    get_settings.cache_clear()


def _set_auto_send(enabled: bool, account_id: int = 1) -> None:
    from app.db import get_connection
    conn = get_connection()
    try:
        conn.execute(
            "UPDATE accounts SET auto_send_enabled=? WHERE id=?",
            (1 if enabled else 0, account_id),
        )
        conn.commit()
    finally:
        conn.close()


def _row(sid: int) -> dict:
    from app.db import get_connection
    conn = get_connection()
    try:
        r = conn.execute("SELECT * FROM submissions WHERE id=?", (sid,)).fetchone()
        return dict(r) if r else {}
    finally:
        conn.close()


def _force_status(sid: int, status: str) -> None:
    from app.db import get_connection
    conn = get_connection()
    try:
        conn.execute("UPDATE submissions SET status=? WHERE id=?", (status, sid))
        conn.commit()
    finally:
        conn.close()


def _body(**over) -> dict:
    prez = {
        "vin": "WVWZZZ1KZAW000123",
        "nr_inmatriculare": "B999TST",
        "data_prestatie": "2026-06-15",
        "odometru_final": "123456",
        "prestatii": [{"cod_prestatie": "OE-1"}],
    }
    prez.update(over)
    return {"prezentari": [prez]}


# --------------------------------------------------------------------------- #
# Enqueue API                                                                 #
# --------------------------------------------------------------------------- #

def test_auto_off_ingestie_held(client):
    """Cont Auto OFF -> POST valid -> rand queued, held=1; raspuns held=true + motiv non-null."""
    _set_auto_send(False)
    r = client.post("/v1/prezentari", json=_body())
    assert r.status_code == 200, r.text
    res = r.json()["results"][0]
    assert res["status"] == "queued"
    assert res["held"] is True
    assert res["motiv"], "motiv trebuie sa fie non-null cand randul e tinut"
    assert _row(res["submission_id"])["held"] == 1


def test_auto_on_ingestie_not_held(client):
    """Cont Auto ON -> POST valid -> rand queued, held=0; raspuns held=false, motiv None."""
    _set_auto_send(True)
    r = client.post("/v1/prezentari", json=_body())
    assert r.status_code == 200, r.text
    res = r.json()["results"][0]
    assert res["status"] == "queued"
    assert res["held"] is False
    assert res["motiv"] is None
    assert _row(res["submission_id"])["held"] == 0


# --------------------------------------------------------------------------- #
# Reactivare error->queued (bug de bypass Eng Finding A)                       #
# --------------------------------------------------------------------------- #

def test_reactivare_respecta_auto_off(client):
    """Un rand `error` re-POST-at pe cont Auto OFF re-intra queued CU held=1 (nu pastreaza vechiul)."""
    _set_auto_send(True)
    r = client.post("/v1/prezentari", json=_body())
    sid = r.json()["results"][0]["submission_id"]
    assert _row(sid)["held"] == 0
    # Contul trece pe OFF si randul cade in error; re-POST-ul trebuie sa-l tina.
    _set_auto_send(False)
    _force_status(sid, "error")
    r2 = client.post("/v1/prezentari", json=_body())
    res = r2.json()["results"][0]
    assert res["submission_id"] == sid
    assert res["reactivated"] is True
    assert res["held"] is True
    assert res["motiv"]
    assert _row(sid)["held"] == 1


# --------------------------------------------------------------------------- #
# Dedup echo                                                                   #
# --------------------------------------------------------------------------- #

def test_dedup_echo_held(client):
    """Re-POST acelasi continut (Auto OFF) -> deduped, dar held propagat corect (nu queued curat fals)."""
    _set_auto_send(False)
    r1 = client.post("/v1/prezentari", json=_body())
    sid = r1.json()["results"][0]["submission_id"]
    r2 = client.post("/v1/prezentari", json=_body())
    res = r2.json()["results"][0]
    assert res["submission_id"] == sid
    assert res["deduped"] is True
    assert res["held"] is True
    assert res["motiv"]


# --------------------------------------------------------------------------- #
# Idempotenta: held nu schimba cheia                                           #
# --------------------------------------------------------------------------- #

def test_held_nu_schimba_idempotency_key(client):
    """Acelasi continut Auto ON vs OFF -> aceeasi idempotency_key (held e pur coada)."""
    _set_auto_send(True)
    sid_on = client.post("/v1/prezentari", json=_body()).json()["results"][0]["submission_id"]
    key_on = _row(sid_on)["idempotency_key"]
    # Simulam un al doilea DB logic: acelasi continut, cont OFF -> dedup pe aceeasi cheie.
    _set_auto_send(False)
    r2 = client.post("/v1/prezentari", json=_body())
    res2 = r2.json()["results"][0]
    assert res2["deduped"] is True
    assert res2["submission_id"] == sid_on
    assert _row(res2["submission_id"])["idempotency_key"] == key_on


# --------------------------------------------------------------------------- #
# Reresolve needs_mapping -> queued                                           #
# --------------------------------------------------------------------------- #

def test_reresolve_held(client):
    """Cont Auto OFF, submission needs_mapping -> reresolve dupa mapare -> queued cu held=1."""
    _set_auto_send(False)
    # Cod intern necunoscut -> needs_mapping (nu se trimite).
    body = _body(prestatii=[{"cod_op_service": "REV-INTERN", "denumire": "Revizie interna"}])
    r = client.post("/v1/prezentari", json=body)
    res = r.json()["results"][0]
    sid = res["submission_id"]
    assert _row(sid)["status"] == "needs_mapping"
    # Salvare mapare -> reresolve automat (POST /v1/mapari cheama reresolve_account).
    rc = client.post("/v1/mapari", json={
        "cod_op_service": "REV-INTERN", "cod_prestatie": "OE-1", "auto_send": True,
    })
    assert rc.status_code == 200, rc.text
    row = _row(sid)
    assert row["status"] == "queued"
    assert row["held"] == 1


def test_reresolve_held_auto_on(client):
    """Cont Auto ON, reresolve -> queued cu held=0."""
    _set_auto_send(True)
    body = _body(prestatii=[{"cod_op_service": "REV-INTERN", "denumire": "Revizie interna"}])
    sid = client.post("/v1/prezentari", json=body).json()["results"][0]["submission_id"]
    assert _row(sid)["status"] == "needs_mapping"
    client.post("/v1/mapari", json={
        "cod_op_service": "REV-INTERN", "cod_prestatie": "OE-1", "auto_send": True,
    })
    row = _row(sid)
    assert row["status"] == "queued"
    assert row["held"] == 0


# --------------------------------------------------------------------------- #
# Commit import                                                                #
# --------------------------------------------------------------------------- #

_HEADER = ["VIN", "Nr inmatriculare", "Data prestatie", "Odometru final", "Operatie"]
_ROW = ["WVWZZZ1KZAW001111", "B100TST", "2026-06-15", "123456", "Revizie"]
_COLMAP = {
    "VIN": "vin", "Nr inmatriculare": "nr_inmatriculare",
    "Data prestatie": "data_prestatie", "Odometru final": "odometru_final",
    "Operatie": "operatie",
}


def _make_xlsx(rows: list[list]) -> bytes:
    wb = openpyxl.Workbook()
    ws = wb.active
    ws.title = "Sheet1"
    for row in rows:
        ws.append(row)
    buf = io.BytesIO()
    wb.save(buf)
    return buf.getvalue()


def _commit_import(client) -> int:
    data = _make_xlsx([_HEADER, _ROW])
    import_id = client.post(
        "/v1/import",
        files={"file": ("t.xlsx", io.BytesIO(data), "application/octet-stream")},
    ).json()["import_id"]
    client.post(f"/v1/import/{import_id}/column-mapping", json={"json_mapare": _COLMAP})
    client.post("/v1/mapari", json={"cod_op_service": "Revizie", "cod_prestatie": "OE-1", "auto_send": True})
    rp = client.get(f"/v1/import/{import_id}/preview")
    assert rp.status_code == 200 and rp.json()["summary"].get("ok", 0) == 1, rp.text
    rc = client.post(f"/v1/import/{import_id}/commit", json={
        "n_confirmat": 1, "reviewed_rows": [], "confirmed_by": "t@e2e.ro",
    })
    assert rc.status_code == 200, rc.text
    return rc.json()["submissions"][0]["submission_id"]


def test_import_commit_held_auto_off(client):
    """Commit import pe cont Auto OFF -> rand queued cu held=1."""
    _set_auto_send(False)
    sid = _commit_import(client)
    row = _row(sid)
    assert row["status"] == "queued"
    assert row["held"] == 1


def test_import_commit_not_held_auto_on(client):
    """Commit import pe cont Auto ON -> rand queued cu held=0."""
    _set_auto_send(True)
    sid = _commit_import(client)
    row = _row(sid)
    assert row["status"] == "queued"
    assert row["held"] == 0
