"""Teste TDD pentru POST /v1/prezentari/valideaza (dry-run, PRD 5.2 US-001)."""

from __future__ import annotations

import os
import tempfile

import pytest
from fastapi.testclient import TestClient


@pytest.fixture()
def client(monkeypatch):
    tmp = tempfile.mkdtemp()
    monkeypatch.setenv("AUTOPASS_DB_PATH", os.path.join(tmp, "t.db"))
    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()


# --- helpere ---

def _prez(**over):
    """Prezentare valida implicita."""
    p = {
        "vin": "WVWZZZ1KZAW000123",
        "nr_inmatriculare": "B999TST",
        "data_prestatie": "2026-06-15",
        "odometru_final": "123456",
        "prestatii": [{"cod_prestatie": "OE-1"}],
    }
    p.update(over)
    return p


def _body_v(prezentari=None, **over):
    """Body pentru /valideaza — rar_credentials optional."""
    if prezentari is None:
        prezentari = [_prez(**over)]
    return {"prezentari": prezentari}


# --- teste ---

def test_payload_valid_returneaza_queued(client):
    r = client.post("/v1/prezentari/valideaza", json=_body_v())
    assert r.status_code == 200
    res = r.json()["results"][0]
    assert res["valid"] is True
    assert res["status_estimat"] == "queued"
    assert res["erori"] == []
    assert res["index"] == 0


def test_vin_invalid_returneaza_needs_data(client):
    # VIN cu O/I/Q interzisi
    r = client.post("/v1/prezentari/valideaza", json=_body_v(vin="WVWZZZ1OZIQ45678"))
    assert r.status_code == 200
    res = r.json()["results"][0]
    assert res["status_estimat"] == "needs_data"
    assert res["valid"] is False
    fields = [e["field"] for e in res["erori"]]
    assert "vin" in fields


def test_data_viitoare_needs_data(client):
    r = client.post("/v1/prezentari/valideaza", json=_body_v(data_prestatie="2099-01-01"))
    assert r.status_code == 200
    res = r.json()["results"][0]
    assert res["status_estimat"] == "needs_data"
    assert res["valid"] is False
    fields = [e["field"] for e in res["erori"]]
    assert "data_prestatie" in fields


def test_cod_op_nemapat_returneaza_needs_mapping(client):
    prez = _prez()
    prez["prestatii"] = [{"cod_op_service": "REP_MOTOR_NECUNOSCUT", "denumire": "Reparatie motor"}]
    r = client.post("/v1/prezentari/valideaza", json={"prezentari": [prez]})
    assert r.status_code == 200
    res = r.json()["results"][0]
    assert res["status_estimat"] == "needs_mapping"
    assert res["valid"] is False
    assert len(res["nemapate"]) == 1
    assert res["nemapate"][0]["cod_op_service"] == "REP_MOTOR_NECUNOSCUT"


def test_mapare_existenta_rezolva_codul(client):
    # Salveaza mapare op->cod
    r_map = client.post("/v1/mapari", json={
        "cod_op_service": "REP_MOTOR",
        "cod_prestatie": "OE-1",
        "auto_send": True,
    })
    assert r_map.status_code == 200

    prez = _prez()
    prez["prestatii"] = [{"cod_op_service": "REP_MOTOR", "denumire": "Reparatie motor"}]
    r = client.post("/v1/prezentari/valideaza", json={"prezentari": [prez]})
    assert r.status_code == 200
    res = r.json()["results"][0]
    assert res["status_estimat"] == "queued"
    assert res["valid"] is True
    assert len(res["prestatii_rezolvate"]) == 1
    assert res["prestatii_rezolvate"][0]["cod_prestatie"] == "OE-1"


def test_fara_creds_merge(client):
    # rar_credentials absent -> 200 (optional in schema)
    r = client.post("/v1/prezentari/valideaza", json=_body_v())
    assert r.status_code == 200


def test_nu_scrie_in_coada(client):
    # Verifica zero efecte secundare: COUNT(*) neschimbat
    r_before = client.get("/v1/prezentari")
    assert r_before.status_code == 200
    nr_before = len(r_before.json()["submissions"])

    client.post("/v1/prezentari/valideaza", json=_body_v())

    r_after = client.get("/v1/prezentari")
    assert r_after.status_code == 200
    nr_after = len(r_after.json()["submissions"])

    assert nr_after == nr_before


def test_multi_prezentari_rezultate_per_index(client):
    prezentari = [
        _prez(),  # valid -> queued
        _prez(vin="WVWZZZ1OZIQ45678"),  # VIN invalid -> needs_data
    ]
    r = client.post("/v1/prezentari/valideaza", json={"prezentari": prezentari})
    assert r.status_code == 200
    results = r.json()["results"]
    assert len(results) == 2
    # index corect per pozitie
    assert results[0]["index"] == 0
    assert results[1]["index"] == 1
    # statusuri diferite
    assert results[0]["status_estimat"] == "queued"
    assert results[1]["status_estimat"] == "needs_data"


def test_shape_invalid_422(client):
    # PrestatieItem fara cod_prestatie si fara cod_op_service -> 422 de shape Pydantic
    prez = _prez()
    prez["prestatii"] = [{"denumire": "ceva"}]  # lipseste cod_prestatie si cod_op_service
    r = client.post("/v1/prezentari/valideaza", json={"prezentari": [prez]})
    assert r.status_code == 422
    # Handlerul global dropeaza input/ctx — fara echo parola (desi creds lipseste, testam structura)
    body = r.json()
    for err in body.get("detail", []):
        assert "input" not in err
        assert "ctx" not in err


# --------------------------------------------------------------------------- #
# US-003: 3 niveluri in raspunsul /valideaza                                  #
# --------------------------------------------------------------------------- #

def test_erori_au_3niveluri(client):
    """/valideaza cu VIN invalid -> erori[i] au cod/problema/cauza/fix (pass-through US-002)."""
    r = client.post("/v1/prezentari/valideaza", json=_body_v(vin="WVWZZZ1OZIQ45678"))
    assert r.status_code == 200
    res = r.json()["results"][0]
    assert res["status_estimat"] == "needs_data"
    erori = res["erori"]
    assert len(erori) >= 1
    for e in erori:
        assert "cod" in e, f"lipseste 'cod' in {e}"
        assert "problema" in e, f"lipseste 'problema' in {e}"
        assert "cauza" in e, f"lipseste 'cauza' in {e}"
        assert "fix" in e, f"lipseste 'fix' in {e}"


def test_nemapate_au_3niveluri(client):
    """/valideaza cu cod_op nemapat -> nemapate[i] au cod_op_service+denumire PASTRATE
    + cod==COD_NEMAPAT + cele 3 niveluri."""
    prez = _prez()
    prez["prestatii"] = [{"cod_op_service": "OP_TEST_NEMAPAT", "denumire": "Operatie test"}]
    r = client.post("/v1/prezentari/valideaza", json={"prezentari": [prez]})
    assert r.status_code == 200
    res = r.json()["results"][0]
    assert res["status_estimat"] == "needs_mapping"
    nemapate = res["nemapate"]
    assert len(nemapate) == 1
    n = nemapate[0]
    # Campuri originale pastrate
    assert n["cod_op_service"] == "OP_TEST_NEMAPAT"
    assert n["denumire"] == "Operatie test"
    # 3 niveluri adaugate
    assert n["cod"] == "COD_NEMAPAT"
    assert n["problema"]
    assert n["cauza"]
    assert n["fix"]
