<?php

declare(strict_types=1);

namespace PpPhp\Core\DataOps\Readers;

use PpPhp\Core\DataOps\ImportReader;

/**
 * Delimited text — CSV, TSV, semicolon/pipe separated, and anything pasted
 * straight out of Excel (which puts TABs on the clipboard). The delimiter is
 * either chosen explicitly or sniffed from the first line.
 */
final class DelimitedReader implements ImportReader
{
    public const DELIMITERS = ['comma' => ',', 'semicolon' => ';', 'tab' => "\t", 'pipe' => '|'];

    public static function id(): string { return 'csv'; }
    public static function label(): string { return 'Delimited text (CSV, TSV, TXT)'; }
    public static function extensions(): array { return ['csv', 'tsv', 'txt']; }
    public static function supportsPaste(): bool { return true; }

    /** Resolve a delimiter choice ('auto' sniffs the first line by frequency). */
    public static function resolveDelimiter(string $choice, string $path): string
    {
        if (isset(self::DELIMITERS[$choice])) return self::DELIMITERS[$choice];
        $line = '';
        if (($fh = @fopen($path, 'r')) !== false) { $line = (string) fgets($fh); fclose($fh); }
        $best = ','; $n = -1;
        foreach (self::DELIMITERS as $d) {
            $c = substr_count($line, $d);
            if ($c > $n) { $n = $c; $best = $d; }
        }
        return $best;
    }

    public function read(string $path, array $opts): array
    {
        $delim = (string) ($opts['delimiter'] ?? ',');
        if ($delim === '' || isset(self::DELIMITERS[$delim]) || $delim === 'auto') {
            $delim = self::resolveDelimiter($delim ?: 'auto', $path);
        }
        $rows = [];
        if (($fh = @fopen($path, 'r')) !== false) {
            while (($r = fgetcsv($fh, 0, $delim, '"', '\\')) !== false) {
                if (count($r) === 1 && trim((string) $r[0]) === '') continue;
                $rows[] = array_map(static fn($c) => (string) $c, $r);
            }
            fclose($fh);
        }
        $header = [];
        if (!empty($opts['hasHeader']) && $rows) {
            $header = array_map(static fn($c) => trim((string) $c), array_shift($rows));
        } elseif ($rows) {
            $header = array_map(static fn($i) => 'Column ' . ($i + 1), array_keys($rows[0]));
        }
        return [$header, $rows];
    }
}
