"""TDD pentru L14-S3 — shared_store: SILVER (mapping_suggestions) + GOLD partajat (shared_mappings).

Scenarii acoperite:
- seed_suggestions: idempotent (INSERT OR IGNORE, nu clobberuie randuri existente)
- seed_suggestions: NUL marcat -> cod_prestatie NULL, is_nul=1 (supresie, #4)
- lookup_suggestion: cauta pe denumire_normalizata
- lookup_shared_gold: cauta pe denumire_normalizata
- record_human_validation: insert nou + increment confirmations la al doilea apel
- provenance/source/confidence pastrate (#5)
"""

from __future__ import annotations

import os
import tempfile

import pytest


# --------------------------------------------------------------------------- #
# Fixtures                                                                    #
# --------------------------------------------------------------------------- #

@pytest.fixture()
def env(monkeypatch):
    """DB temporara cu schema initiata."""
    tmp = tempfile.mkdtemp()
    monkeypatch.setenv("AUTOPASS_DB_PATH", os.path.join(tmp, "shared_store_test.db"))
    from app.config import get_settings
    get_settings.cache_clear()
    from app.db import init_db
    init_db()
    yield monkeypatch
    get_settings.cache_clear()


@pytest.fixture()
def conn(env):
    from app.db import get_connection
    c = get_connection()
    yield c
    c.close()


# --------------------------------------------------------------------------- #
# seed_suggestions — strat SILVER                                             #
# --------------------------------------------------------------------------- #

def test_seed_suggestions_inserteaza(conn):
    """seed_suggestions insereaza un rand si returneaza 1 (numarul de randuri inserate)."""
    from app.shared_store import seed_suggestions, lookup_suggestion

    n = seed_suggestions(conn, [
        {"denumire": "Schimb ulei motor", "cod_prestatie": "OE-3", "source": "llm", "confidence": 0.9},
    ])
    conn.commit()

    assert n == 1
    row = lookup_suggestion(conn, "Schimb ulei motor")
    assert row is not None
    assert row["cod_prestatie"] == "OE-3"
    assert row["source"] == "llm"
    assert abs(row["confidence"] - 0.9) < 0.001
    assert row["is_nul"] == 0


def test_seed_suggestions_idempotent(conn):
    """seed_suggestions de doua ori cu acelasi item -> al doilea INSERT OR IGNORE, n=0 la re-seed."""
    from app.shared_store import seed_suggestions, lookup_suggestion

    n1 = seed_suggestions(conn, [
        {"denumire": "Verificare faruri", "cod_prestatie": "OE-2", "source": "llm", "confidence": 0.8},
    ])
    conn.commit()
    n2 = seed_suggestions(conn, [
        {"denumire": "Verificare faruri", "cod_prestatie": "OE-2", "source": "llm", "confidence": 0.8},
    ])
    conn.commit()

    assert n1 == 1
    assert n2 == 0  # INSERT OR IGNORE: randul deja exista

    row = lookup_suggestion(conn, "Verificare faruri")
    assert row is not None
    assert row["cod_prestatie"] == "OE-2"


def test_seed_suggestions_nu_clobberuie_randul_existent(conn):
    """Re-seed cu cod diferit -> INSERT OR IGNORE pastreaza valoarea veche (#2)."""
    from app.shared_store import seed_suggestions, lookup_suggestion

    seed_suggestions(conn, [
        {"denumire": "Reparatie motor", "cod_prestatie": "OE-1", "source": "llm", "confidence": 0.85},
    ])
    conn.commit()

    # Al doilea seed cu alt cod: trebuie ignorat (nu suprascrie)
    seed_suggestions(conn, [
        {"denumire": "Reparatie motor", "cod_prestatie": "OE-2", "source": "llm", "confidence": 0.5},
    ])
    conn.commit()

    row = lookup_suggestion(conn, "Reparatie motor")
    assert row is not None
    assert row["cod_prestatie"] == "OE-1"  # valoarea veche pastrata


def test_seed_suggestions_nul_marcat_fara_cod(conn):
    """is_nul=True -> cod_prestatie NULL, is_nul=1 in DB (supresie, #4)."""
    from app.shared_store import seed_suggestions, lookup_suggestion

    seed_suggestions(conn, [
        {"denumire": "ITP CT 12 ABC", "is_nul": True, "source": "llm", "confidence": 0.95},
    ])
    conn.commit()

    row = lookup_suggestion(conn, "ITP CT 12 ABC")
    assert row is not None
    assert row["is_nul"] == 1
    assert row["cod_prestatie"] is None  # NUL nu se promoveaza la cod (#4)


def test_seed_suggestions_nul_cu_cod_explicit_tot_nul(conn):
    """Daca is_nul=True, cod_prestatie e ignorat si stocat NULL (supresie stricta, #4)."""
    from app.shared_store import seed_suggestions, lookup_suggestion

    seed_suggestions(conn, [
        {
            "denumire": "DISCOUNT MATERIALE 5%",
            "cod_prestatie": "OE-1",  # ignorat cand is_nul=True
            "is_nul": True,
            "source": "llm",
            "confidence": 0.99,
        },
    ])
    conn.commit()

    row = lookup_suggestion(conn, "DISCOUNT MATERIALE 5%")
    assert row is not None
    assert row["is_nul"] == 1
    assert row["cod_prestatie"] is None  # cod explicit ignorat cand is_nul


def test_seed_suggestions_cod_whitespace_devine_null(conn):
    """Rand non-NUL cu cod whitespace-only ('   ') -> cod_prestatie NULL, NU '' (corectitudine)."""
    from app.shared_store import seed_suggestions, lookup_suggestion

    seed_suggestions(conn, [
        {"denumire": "OPERATIE CU COD GOL", "cod_prestatie": "   ", "source": "llm", "confidence": 0.5},
    ])
    conn.commit()

    row = lookup_suggestion(conn, "OPERATIE CU COD GOL")
    assert row is not None
    assert row["is_nul"] == 0  # nu e marcat NUL
    assert row["cod_prestatie"] is None  # whitespace -> NULL, nu '' (rand non-NUL fara cod gol)


def test_seed_suggestions_normalizare_diacritice(conn):
    """Lookup pe forma cu diacritice gaseste randul seedat fara diacritice (normalize_for_match)."""
    from app.shared_store import seed_suggestions, lookup_suggestion

    seed_suggestions(conn, [
        {"denumire": "Înlocuit filtru aer", "cod_prestatie": "OE-3", "source": "llm", "confidence": 0.7},
    ])
    conn.commit()

    # Lookup cu accentele, fara accente, uppercase — trebuie sa gaseasca acelasi rand
    row1 = lookup_suggestion(conn, "Înlocuit filtru aer")
    row2 = lookup_suggestion(conn, "Inlocuit filtru aer")
    row3 = lookup_suggestion(conn, "INLOCUIT FILTRU AER")

    assert row1 is not None and row1["cod_prestatie"] == "OE-3"
    assert row2 is not None and row2["cod_prestatie"] == "OE-3"
    assert row3 is not None and row3["cod_prestatie"] == "OE-3"


def test_lookup_suggestion_lipseste_returneaza_none(conn):
    """lookup_suggestion pe o denumire care nu exista -> None."""
    from app.shared_store import lookup_suggestion

    row = lookup_suggestion(conn, "Denumire inexistenta")
    assert row is None


# --------------------------------------------------------------------------- #
# record_human_validation + lookup_shared_gold — strat GOLD partajat         #
# --------------------------------------------------------------------------- #

def test_record_human_validation_insert(conn):
    """Prima confirmare umana creeaza un rand nou in shared_mappings."""
    from app.shared_store import record_human_validation, lookup_shared_gold

    record_human_validation(
        conn,
        denumire="Schimb ulei",
        cod_prestatie="oe-3",  # se normalizeaza la OE-3
        source="human",
        provenance="cont_2/user@test.com",
        confidence=1.0,
    )
    conn.commit()

    row = lookup_shared_gold(conn, "Schimb ulei")
    assert row is not None
    assert row["cod_prestatie"] == "OE-3"  # normalizat uppercase
    assert row["source"] == "human"
    assert row["provenance"] == "cont_2/user@test.com"
    assert abs(row["confidence"] - 1.0) < 0.001
    assert row["confirmations"] == 1


def test_record_human_validation_increment_confirmations(conn):
    """A doua confirmare umana pe aceeasi denumire -> confirmations += 1."""
    from app.shared_store import record_human_validation, lookup_shared_gold

    record_human_validation(conn, "Revizie anuala", "OE-3")
    conn.commit()
    record_human_validation(conn, "Revizie anuala", "OE-3")
    conn.commit()

    row = lookup_shared_gold(conn, "Revizie anuala")
    assert row is not None
    assert row["confirmations"] == 2


def test_record_human_validation_normalizare(conn):
    """Lookup pe diacritice sau uppercase gaseste acelasi rand GOLD."""
    from app.shared_store import record_human_validation, lookup_shared_gold

    record_human_validation(conn, "Înlocuit garnitura chiulasa", "OE-1")
    conn.commit()

    row1 = lookup_shared_gold(conn, "Înlocuit garnitura chiulasa")
    row2 = lookup_shared_gold(conn, "Inlocuit garnitura chiulasa")
    row3 = lookup_shared_gold(conn, "INLOCUIT GARNITURA CHIULASA")

    assert row1 is not None and row1["cod_prestatie"] == "OE-1"
    assert row2 is not None
    assert row3 is not None


def test_lookup_shared_gold_lipseste_returneaza_none(conn):
    """lookup_shared_gold pe denumire inexistenta -> None."""
    from app.shared_store import lookup_shared_gold

    row = lookup_shared_gold(conn, "Operatie fara GOLD")
    assert row is None


def test_provenance_source_confidence_pastrate(conn):
    """source, provenance, confidence sunt stocate si returnate corect (#5)."""
    from app.shared_store import seed_suggestions, lookup_suggestion

    seed_suggestions(conn, [
        {
            "denumire": "Reglat directie",
            "cod_prestatie": "OE-2",
            "source": "embedding",
            "confidence": 0.73,
        },
    ])
    conn.commit()

    row = lookup_suggestion(conn, "Reglat directie")
    assert row is not None
    assert row["source"] == "embedding"
    assert abs(row["confidence"] - 0.73) < 0.001


# --------------------------------------------------------------------------- #
# Separare structurala (#13): tabelele noi NU sunt citite de resolve_prestatii#
# --------------------------------------------------------------------------- #

def test_mapping_suggestions_nu_e_folosita_de_resolve_prestatii():
    """resolve_prestatii NU citeste din mapping_suggestions — separare structurala (#13).

    Daca un cod e in SILVER dar nu in operations_mapping, resolve_prestatii
    NU il gaseste -> submission ramane needs_mapping (om in bucla).
    """
    from app.mapping import resolve_prestatii

    # Apelam resolve_prestatii fara niciun mapping -> operatia e nemapata
    resolved, unmapped = resolve_prestatii(
        [{"cod_op_service": "OP_SILVER", "denumire": "Reglat faruri"}],
        {},  # operations_mapping gol
    )
    assert resolved[0]["cod_prestatie"] is None
    assert len(unmapped) == 1
    # Nu exista cale prin care SILVER sa ajunga in resolve fara wiring explicit (L14-S6)


def test_shared_mappings_nu_e_folosita_de_resolve_prestatii():
    """resolve_prestatii NU citeste din shared_mappings — separare structurala (#13).

    Chiar daca GOLD partajat exista, resolve_prestatii nu il vede fara wiring explicit.
    """
    from app.mapping import resolve_prestatii

    resolved, unmapped = resolve_prestatii(
        [{"cod_op_service": "OP_GOLD", "denumire": "Revizie periodica"}],
        {},  # operations_mapping gol
    )
    assert resolved[0]["cod_prestatie"] is None
    assert len(unmapped) == 1
