import csv
from abc import ABC, abstractmethod
from csv import Dialect
from typing import Literal, Iterable

from pydantic import BaseModel


class JaggedCsvRow(BaseModel, ABC):
    """
    Represents a jagged (varying column count) row that can be emitted to a CSV row by handling its own per-field
    rendering.
    """

    @abstractmethod
    def as_iterable(self) -> Iterable[str]:
        """
        Convert this model into an Iterable of strings suitable for writing to a CSV file.
        """
        raise NotImplementedError()


class JaggedCsvWriter:
    # Can't really typehint these because of the way that the standard library implements them, but its signature should
    # roughly match csv.writer()
    def __init__(
            self,
            fileobj,
            /,
            dialect: str | Dialect | Dialect | type[Dialect | Dialect] = "excel",
            *,
            delimiter: str = ",",
            quotechar: str | None = "\"",
            escapechar: str | None = None,
            doublequote: bool = True,
            skipinitialspace: bool = False,
            lineterminator: str = "\r\n",
            quoting: Literal[0, 1, 2, 3] = 0,
            strict: bool = False
    ):
        self.writer = csv.writer(
            fileobj,
            dialect=dialect,
            delimiter=delimiter,
            quotechar=quotechar,
            escapechar=escapechar,
            doublequote=doublequote,
            skipinitialspace=skipinitialspace,
            lineterminator=lineterminator,
            quoting=quoting,
            strict=strict
        )

    def write_jagged_row(self, row: JaggedCsvRow):
        self.writer.writerow(row.as_iterable())
