<?php

declare(strict_types=1);

namespace App\Services\Supplier;

use Illuminate\Support\Facades\Log;

/**
 * Streaming-парсер CSV-отчёта «Запрос номеров» supplier-портала crm.bp-gr.ru.
 *
 * Spec: docs/superpowers/specs/2026-05-18-supplier-csv-reconcile-channel-design.md §4.1
 * Столбцы: Name;Tag;Phone — 3 колонки. vid и время в этом отчёте отсутствуют.
 *
 * Возвращает Generator. BOM + CRLF поддерживаются. Malformed rows skip + log.
 */
final class SupplierCsvParser
{
    private const EXPECTED_COLUMNS = 3;

    /**
     * @return iterable<int, array{project: string, tag: string, phone: string}>
     */
    public function parse(string $rawCsv): iterable
    {
        if ($rawCsv === '') {
            return;
        }

        // Убираем UTF-8 BOM (EF BB BF)
        if (str_starts_with($rawCsv, "\xEF\xBB\xBF")) {
            $rawCsv = substr($rawCsv, 3);
        }

        // Нормализуем CRLF → LF
        $rawCsv = str_replace("\r\n", "\n", $rawCsv);

        $lines = explode("\n", $rawCsv);
        $headerSkipped = false;
        $lineNo = 0;

        foreach ($lines as $line) {
            $lineNo++;
            if ($line === '') {
                continue;
            }
            if (! $headerSkipped) {
                $headerSkipped = true;

                continue;
            }

            $cols = str_getcsv($line, separator: ';');
            if (count($cols) < self::EXPECTED_COLUMNS) {
                Log::warning('supplier_csv_parser.malformed_row', [
                    'line_no' => $lineNo,
                    'columns_found' => count($cols),
                    'expected' => self::EXPECTED_COLUMNS,
                    'sample' => substr($line, 0, 100),
                ]);

                continue;
            }

            yield [
                'project' => (string) $cols[0],
                'tag' => (string) $cols[1],
                'phone' => (string) $cols[2],
            ];
        }
    }
}
