from __future__ import annotations

import csv
import json
import pickle
from pathlib import Path
from typing import Iterable

import pandas as pd


def ensure_parent_directory(path: Path) -> None:
    path.parent.mkdir(parents=True, exist_ok=True)


def read_csv(path: Path, **kwargs) -> pd.DataFrame:
    if not path.exists():
        raise FileNotFoundError(path)
    return pd.read_csv(path, **kwargs)


def load_csv_optional(path: Path, **kwargs) -> pd.DataFrame:
    if not path.exists():
        return pd.DataFrame()
    return pd.read_csv(path, **kwargs)


def write_csv(
    dataframe: pd.DataFrame,
    path: Path,
    *compatibility_paths: Path,
    quoting: int = csv.QUOTE_ALL,
) -> None:
    targets = [path, *compatibility_paths]
    for target in targets:
        ensure_parent_directory(target)
        dataframe.to_csv(target, index=False, quoting=quoting)


def load_pickle(path: Path):
    if not path.exists():
        raise FileNotFoundError(path)
    with open(path, "rb") as infile:
        return pickle.load(infile)


def dump_pickle(value, path: Path, *compatibility_paths: Path) -> None:
    targets = [path, *compatibility_paths]
    for target in targets:
        ensure_parent_directory(target)
        with open(target, "wb") as outfile:
            pickle.dump(value, outfile)


def read_lines(path: Path) -> list[str]:
    if not path.exists():
        return []
    with open(path, "r", encoding="utf-8") as infile:
        return [line.strip() for line in infile if line.strip()]


def write_lines(lines: Iterable[str], path: Path) -> None:
    ensure_parent_directory(path)
    with open(path, "w", encoding="utf-8") as outfile:
        for line in lines:
            outfile.write(f"{line}\n")


def write_json(payload: dict, path: Path) -> None:
    ensure_parent_directory(path)
    with open(path, "w", encoding="utf-8") as outfile:
        json.dump(payload, outfile, indent=2, sort_keys=True)
