"""Append live frames"""

from __future__ import annotations

from datetime import datetime
from pathlib import Path
from typing import Optional, TextIO

from pygui.backend.models.frame import Frame
from pygui.backend.wafer.zwafer_models import Sensor


class CsvRecorder:
    def __init__(self) -> None:
        self._file_handle: Optional[TextIO] = None
        self._path: Optional[str] = None

    @property
    def is_recording(self) -> bool:
        return self._file_handle is not None

    def start(self, path: str, sensors: list[Sensor], serial: str = "") -> None:
        Path(path).parent.mkdir(parents=True, exist_ok=True)
        file_handle = open(path, "w", encoding="utf-8", newline="")
        file_handle.write(f"Wafer ID={serial}\n")
        file_handle.write(f"Acquisition Date={datetime.now():%m/%d/%Y}\n")
        file_handle.write("Label," + ",".join(s.label for s in sensors) + "\n")
        file_handle.write("X (mm)," + ",".join(str(s.x) for s in sensors) + "\n")
        file_handle.write("Y (mm)," + ",".join(str(s.y) for s in sensors) + "\n")
        file_handle.write("data\n")
        file_handle.flush()
        self._file_handle, self._path = file_handle, path

    def write(self, frame: Frame) -> None:
        if self._file_handle is None:
            return
        row = [f"{frame.time:.3f}"] + [f"{v:.3f}" for v in frame.values]
        self._file_handle.write(",".join(row) + "\n")
        self._file_handle.flush()

    def stop(self) -> Optional[str]:
        if self._file_handle is None:
            return None
        self._file_handle.close()
        path, self._file_handle, self._path = self._path, None, None
        return path

    @staticmethod
    def write_segment(file_path: str, source_path: str, start_frame: int, end_frame: int) -> bool:
        """Copy a range of frames from source CSV into a new file.

        Preserves the source's header structure so the segment re-imports
        through FileBrowser unchanged: official CSVs keep their sensor-name
        row, Z-wafer CSVs keep every metadata line through the "data"
        sentinel. Frame indices count only valid data rows, matching how
        the readers in data_records.py number frames.

        Args:
            file_path: Output CSV path.
            source_path: Source CSV path with full wafer data
            start_frame: First frame index (inclusive).
            end_frame: Last frame index (inclusive)

        Returns:
            True on success (at least one frame written).
        """
        from pygui.backend.data.data_records import is_data_row, is_official_csv

        if start_frame < 0 or end_frame < start_frame:
            return False

        with open(source_path, "r", encoding="utf-8") as f:
            lines = f.readlines()

        out: list[str] = []
        written = 0
        frame_idx = -1
        in_data = is_official_csv(source_path)

        for i, line in enumerate(lines):
            stripped = line.rstrip().rstrip(",").strip()
            if not in_data:
                out.append(line)
                if stripped and stripped.split(",")[0].lower() == "data":
                    in_data = True
                continue
            if i == 0:
                # official format: row 0 is the sensor-name header
                out.append(line)
                continue
            if not stripped or not is_data_row(stripped):
                continue
            frame_idx += 1
            if start_frame <= frame_idx <= end_frame:
                out.append(line if line.endswith("\n") else line + "\n")
                written += 1

        if written == 0:
            return False
        Path(file_path).parent.mkdir(parents=True, exist_ok=True)
        with open(file_path, "w", encoding="utf-8", newline="") as f:
            f.writelines(out)
        return True
