<?php

declare(strict_types=1);

namespace App\Administration\Application\Service\Import;

use App\Administration\Domain\Exception\FichierImportInvalideException;
use PhpOffice\PhpSpreadsheet\IOFactory;
use PhpOffice\PhpSpreadsheet\Reader\Exception as SpreadsheetException;

/**
 * Service de parsing de fichiers XLSX (Excel) via PhpSpreadsheet.
 */
final readonly class XlsxParser
{
    public function parse(string $filePath): FileParseResult
    {
        try {
            $spreadsheet = IOFactory::load($filePath);
        } catch (SpreadsheetException $e) {
            throw FichierImportInvalideException::formatInvalide($filePath, $e->getMessage());
        }

        $sheet = $spreadsheet->getActiveSheet();
        $data = $sheet->toArray('', true, true, false);

        if ($data === []) {
            throw FichierImportInvalideException::fichierVide();
        }

        /** @var list<string|int|float|bool|null> $headerRow */
        $headerRow = array_shift($data);
        $columns = array_values(array_map(static fn (string|int|float|bool|null $v): string => (string) $v, $headerRow));

        $rows = [];
        foreach ($data as $line) {
            /** @var list<mixed> $cells */
            $cells = $line;
            if ($this->isEmptyLine($cells)) {
                continue;
            }

            $row = [];
            foreach ($columns as $index => $column) {
                /** @var string|int|float|bool|null $cellValue */
                $cellValue = $cells[$index] ?? '';
                $row[$column] = (string) $cellValue;
            }
            $rows[] = $row;
        }

        return new FileParseResult($columns, $rows);
    }

    /**
     * @param list<mixed> $line
     */
    private function isEmptyLine(array $line): bool
    {
        foreach ($line as $cell) {
            if ($cell !== null && $cell !== '') {
                return false;
            }
        }

        return true;
    }
}
