"""Teste US-007 (PRD 5.4): erori de import pe 3 niveluri in interfata web.

Verifica ca fragmentele HTML intoarse de rutele web /_import/* contin
textele structurate (problema + fix) din catalog pentru erorile de upload
si de mapare coloane.

Rutele testate sunt WEB (HTML), nu API JSON — raspunsul este HTML fragment.
"""

from __future__ import annotations

import io
import os
import tempfile

import openpyxl
import pytest
from fastapi.testclient import TestClient


# --------------------------------------------------------------------------- #
# Fixture client cu WEB_AUTH_REQUIRED=false (dev mode, cont 1 implicit)       #
# --------------------------------------------------------------------------- #

@pytest.fixture()
def client(monkeypatch):
    """Client FastAPI cu DB temporara izolata, auth web dezactivat (dev mode)."""
    tmp = tempfile.mkdtemp()
    monkeypatch.setenv("AUTOPASS_DB_PATH", os.path.join(tmp, "erori3n.db"))
    monkeypatch.setenv("AUTOPASS_WEB_AUTH_REQUIRED", "false")
    from app.config import get_settings
    get_settings.cache_clear()
    from app.crypto import reset_cache
    reset_cache()
    from app.main import app
    with TestClient(app) as c:
        yield c
    get_settings.cache_clear()
    reset_cache()


# --------------------------------------------------------------------------- #
# Helpere                                                                      #
# --------------------------------------------------------------------------- #

def _make_xlsx_prea_mare(n_randuri: int = 5001) -> bytes:
    """Xlsx cu mai mult de 5000 de randuri de date (declanseaza FileTooLarge)."""
    wb = openpyxl.Workbook()
    ws = wb.active
    ws.append(["VIN", "Nr inmatriculare", "Data prestatie", "Odometru final", "Operatie"])
    for i in range(n_randuri):
        ws.append([
            f"WVWZZZ1KZA{i:07d}",
            f"B{i:04d}TST",
            "2026-06-15",
            str(100000 + i),
            "Revizie",
        ])
    buf = io.BytesIO()
    wb.save(buf)
    return buf.getvalue()


def _upload_web(client: TestClient, data: bytes, filename: str = "test.xlsx") -> object:
    """POST pe ruta web de upload (intoarce HTML fragment)."""
    return client.post(
        "/_import/upload",
        files={"file": (filename, io.BytesIO(data), "application/octet-stream")},
    )


# --------------------------------------------------------------------------- #
# 1. Upload fisier prea mare → fragment cu fix din IMPORT_FISIER_PREA_MARE     #
# --------------------------------------------------------------------------- #

def test_upload_fisier_prea_mare_3niveluri(client):
    """Upload xlsx >5000 randuri → fragment HTML contine textul fix din catalog.

    Textul asteptat din CATALOG['IMPORT_FISIER_PREA_MARE']['fix']:
    'Imparte fisierul in bucati de maxim 5000 de randuri si incarca-le pe rand.'
    """
    from app.errors import CATALOG
    fix_asteptat = CATALOG["IMPORT_FISIER_PREA_MARE"]["fix"]

    data = _make_xlsx_prea_mare(5001)
    r = _upload_web(client, data, "mare.xlsx")

    assert r.status_code == 200, f"Asteptat 200, primit {r.status_code}: {r.text[:300]}"
    html = r.text
    assert fix_asteptat in html, (
        f"Textul fix din IMPORT_FISIER_PREA_MARE nu apare in fragmentul HTML.\n"
        f"Asteptat: {fix_asteptat!r}\n"
        f"Fragment (primii 800 chars): {html[:800]}"
    )


# --------------------------------------------------------------------------- #
# 2. Upload fisier nerecunoscut → fragment cu fix din IMPORT_FISIER_NERECUNOSCUT
# --------------------------------------------------------------------------- #

def test_upload_fisier_nerecunoscut_3niveluri(client):
    """Upload bytes invalizi (nu e xlsx/csv valid) → fragment HTML cu fix din catalog.

    Textul asteptat din CATALOG['IMPORT_FISIER_NERECUNOSCUT']['fix']:
    'Incarca un fisier .xlsx sau .csv valid.'
    """
    from app.errors import CATALOG
    fix_asteptat = CATALOG["IMPORT_FISIER_NERECUNOSCUT"]["fix"]
    problema_asteptata = CATALOG["IMPORT_FISIER_NERECUNOSCUT"]["problema"]

    # Bytes invalizi: nu este un zip/xlsx, nu este text CSV
    date_invalide = b"\x00\x01\x02\x03\x04\x05binar_junk_non_xlsx"
    r = _upload_web(client, date_invalide, "test.xlsx")

    assert r.status_code == 200, f"Asteptat 200, primit {r.status_code}: {r.text[:300]}"
    html = r.text
    assert fix_asteptat in html, (
        f"Textul fix din IMPORT_FISIER_NERECUNOSCUT nu apare in fragmentul HTML.\n"
        f"Asteptat: {fix_asteptat!r}\n"
        f"Fragment (primii 800 chars): {html[:800]}"
    )


# --------------------------------------------------------------------------- #
# 3. Mapare coloane cu JSON invalid → fragment cu fix din COLOANE_FORMAT_JSON  #
# --------------------------------------------------------------------------- #

def test_mapcoloane_format_json_3niveluri(client):
    """POST direct pe ruta de mapare coloane cu corp JSON invalid → fragment cu fix din catalog.

    Textul asteptat din CATALOG['COLOANE_FORMAT_JSON']['fix']:
    'Verifica sintaxa JSON a maparii de coloane (ghilimele duble, acolade inchise corect).'

    Ruta /_import/{id}/mapare-coloane accepta form data. Codul de test simuleaza
    un batch_id invalid (0) pentru a forta ramura de eroare, sau injecteaza direct
    un batch_id valid cu JSON invalid in campul de mapare. Deoarece ruta nu primeste
    JSON direct, testam ramura din routes.py unde se face json.dumps si se valideaza
    manual, sau modificam testul sa plaseze un batch valid si sa trimita date malformate.

    Strategia: upload un fisier valid, obtine import_id, trimite un form cu valoare
    json invalida in campul coloane (via Content-Type: application/json intentionat gresit
    sau via parametru form malformat). In implementarea din routes.py, eroarea
    COLOANE_FORMAT_JSON este randata cand json.loads esueaza pe un camp special.
    """
    from app.errors import CATALOG
    fix_asteptat = CATALOG["COLOANE_FORMAT_JSON"]["fix"]

    # Primul pas: upload un fisier valid pentru a obtine un import_id real
    wb = openpyxl.Workbook()
    ws = wb.active
    ws.append(["VIN", "Nr", "Data", "KM", "Op"])
    ws.append(["WVWZZZ1KZAW000123", "B001TST", "2026-06-15", "100000", "Revizie"])
    buf = io.BytesIO()
    wb.save(buf)
    xlsx_data = buf.getvalue()

    r_upload = _upload_web(client, xlsx_data, "test.xlsx")
    assert r_upload.status_code == 200, r_upload.text[:300]

    # Extrage import_id din raspuns
    import re
    m = re.search(r"/_import/(\d+)/mapare-coloane", r_upload.text)
    assert m, f"Nu s-a gasit import_id in raspuns: {r_upload.text[:500]}"
    import_id = int(m.group(1))

    # Trimite un request pe ruta de mapare coloane cu Content-Type: application/json
    # si corp JSON invalid → ruta ar trebui sa intoarca eroarea COLOANE_FORMAT_JSON
    r = client.post(
        f"/_import/{import_id}/mapare-coloane",
        content=b"{invalid json}",
        headers={"Content-Type": "application/json"},
    )

    assert r.status_code == 200, f"Asteptat 200, primit {r.status_code}: {r.text[:300]}"
    html = r.text
    assert fix_asteptat in html, (
        f"Textul fix din COLOANE_FORMAT_JSON nu apare in fragmentul HTML.\n"
        f"Asteptat: {fix_asteptat!r}\n"
        f"Fragment (primii 800 chars): {html[:800]}"
    )
