<?php

declare(strict_types=1);

namespace App\Framework\Filesystem\Serializers;

use App\Framework\Filesystem\Serializer;

/**
 * CSV-Serializer für tabellarische Daten
 */
final readonly class CsvSerializer implements Serializer
{
    public function __construct(
        private string $delimiter = ',',
        private string $enclosure = '"',
        private string $escape = '\\'
    ) {
    }

    public function serialize(mixed $data): string
    {
        if (! is_array($data)) {
            throw new \InvalidArgumentException('CSV serializer requires array data');
        }

        if (empty($data)) {
            return '';
        }

        $output = fopen('php://temp', 'r+');

        // Wenn es ein assoziatives Array ist, Header schreiben
        if (is_array($data[0] ?? null)) {
            $headers = array_keys($data[0]);
            fputcsv($output, $headers, $this->delimiter, $this->enclosure, $this->escape);
        }

        foreach ($data as $row) {
            if (is_array($row)) {
                fputcsv($output, $row, $this->delimiter, $this->enclosure, $this->escape);
            } else {
                fputcsv($output, [$row], $this->delimiter, $this->enclosure, $this->escape);
            }
        }

        rewind($output);
        $csv = stream_get_contents($output);
        fclose($output);

        return $csv;
    }

    public function deserialize(string $data): mixed
    {
        if (empty($data)) {
            return [];
        }

        $lines = str_getcsv($data, "\n");
        $result = [];
        $headers = null;

        foreach ($lines as $line) {
            if (empty(trim($line))) {
                continue;
            }

            $row = str_getcsv($line, $this->delimiter, $this->enclosure, $this->escape);

            if ($headers === null) {
                $headers = $row;

                continue;
            }

            if (count($row) === count($headers)) {
                $result[] = array_combine($headers, $row);
            } else {
                $result[] = $row;
            }
        }

        return $result;
    }

    public function getMimeType(): string
    {
        return 'text/csv';
    }

    public function getFileExtension(): string
    {
        return 'csv';
    }
}
