"""
Generación de CSV de errores a partir del JSONL persistido por el worker.
"""

import csv
import io
import json
import os
from typing import Any, Dict, Iterable, List

from fastapi import HTTPException
from fastapi.responses import StreamingResponse

from . import storage as common_storage


def _iter_jsonl_rows(error_path: str) -> Iterable[Dict[str, Any]]:
    """
    Itera sobre errores normalizados desde un .jsonl.

    El worker suele escribir:
    - dict por línea, o
    - lista de dicts por línea.
    """
    if not os.path.exists(error_path):
        return []

    with open(error_path, "r", encoding="utf-8") as f:
        for line in f:
            if not line.strip():
                continue
            try:
                payload = json.loads(line)
            except Exception:
                continue

            items: List[Any] = payload if isinstance(payload, list) else [payload]
            for err in items:
                if isinstance(err, dict):
                    yield err


def download_scan_errors_csv_stream(job_type: str, job_id: str, *, filename_prefix: str = "errores") -> StreamingResponse:
    """
    Devuelve un StreamingResponse con cabecera:
    `linea, columna, mensaje, solucion`.
    """
    error_path = common_storage.error_path_for_job(job_type, job_id)
    if not os.path.exists(error_path):
        raise HTTPException(
            status_code=404,
            detail="Archivo de errores no encontrado. Vuelve a escanear o intenta más tarde.",
        )

    headers = {
        "Content-Disposition": f'attachment; filename="{filename_prefix}_{job_id}.csv"',
    }

    def row_iter():
        buffer = io.StringIO()
        writer = csv.writer(buffer)
        writer.writerow(["linea", "columna", "mensaje", "solucion"])
        yield buffer.getvalue()
        buffer.seek(0)
        buffer.truncate(0)

        for err in _iter_jsonl_rows(error_path):
            buffer.seek(0)
            buffer.truncate(0)
            writer.writerow(
                [
                    err.get("line", ""),
                    err.get("col", ""),
                    err.get("msg", ""),
                    err.get("solution", ""),
                ]
            )
            yield buffer.getvalue()

    return StreamingResponse(row_iter(), media_type="text/csv; charset=utf-8", headers=headers)

