from __future__ import annotations

from dataclasses import dataclass
from datetime import datetime
from pathlib import Path

from pygui.backend.data.data_records import (
    is_official_csv,
    read_data_records,
    read_official_csv,
)
from pygui.backend.models.frame_player import frames_from_wafer_data
from pygui.backend.visualization.wafer_map_item import WaferMapItem
from pygui.backend.wafer.zwafer_parser import ZWaferParser

_EXPORT_SIZE = 600


@dataclass
class BatchExportResult:
    file_path: str
    output_path: str
    success: bool
    error: str = ""


def export_batch(
    file_paths: list[str], output_dir: str, timestamp: str | None = None
) -> list[BatchExportResult]:
    """Render the last frame of each file to a PNG in output_dir.

    Skips files that fail to parse or render, continuing with the rest.
    """
    ts = timestamp or datetime.now().strftime("%Y%m%d_%H%M%S")
    results = []
    for file_path in file_paths:
        results.append(_export_one(file_path, output_dir, ts))
    return results


def _export_one(file_path: str, output_dir: str, ts: str) -> BatchExportResult:
    base_name = Path(file_path).stem
    output_path = str(Path(output_dir) / f"{base_name}_{ts}.png")
    try:
        if is_official_csv(file_path):
            sensors, records = read_official_csv(file_path)
        else:
            data, _ = ZWaferParser().parse(file_path)
            if data is None or not data.sensors:
                return BatchExportResult(file_path, output_path, False, "Invalid layout or missing sensors")
            sensors = data.sensors
            records = read_data_records(file_path)

        frames = frames_from_wafer_data(None, records)
        if not sensors or not frames:
            return BatchExportResult(file_path, output_path, False, "No sensors or frames found")

        item = WaferMapItem()
        item.setWidth(_EXPORT_SIZE)
        item.setHeight(_EXPORT_SIZE)
        item.sensors = [{"label": s.label, "x": s.x, "y": s.y} for s in sensors]  # type: ignore[method-assign]
        item.values = frames[-1].values  # type: ignore[method-assign]

        if not item.export_image(output_path):
            return BatchExportResult(file_path, output_path, False, "Export render failed")
        return BatchExportResult(file_path, output_path, True)
    except Exception as exc:
        return BatchExportResult(file_path, output_path, False, str(exc))
