<?php
namespace Incoviba\Service\Contabilidad\Cartola;

use PhpOffice\PhpSpreadsheet;

trait isExcel
{
    /**
     * @throws PhpSpreadsheet\Exception
     * @throws PhpSpreadsheet\Calculation\Exception
     */
    protected function findTitlesRow(PhpSpreadsheet\Worksheet\RowIterator $rowIterator, string $firstTitle, int $columnOffset = 1, bool $caseInsensitive = false): ?PhpSpreadsheet\Worksheet\Row
    {
        if ($caseInsensitive) {
            $firstTitle = strtolower($firstTitle);
        }
        foreach ($rowIterator as $row) {
            $cellIterator = $row->getCellIterator();
            if ($columnOffset > 1) {
                $cellIterator->seek($columnOffset);
            }
            $value = ($cellIterator->current()->getCalculatedValue());
            if ($value === null) {
                continue;
            }
            if ($caseInsensitive) {
                $value = strtolower($value);
            }
            $value = trim($value, '  ');
            if ($value === $firstTitle) {
                return $row;
            }
        }
        throw new PhpSpreadsheet\Exception('No se encontró la fila de títulos');
    }
    /**
     * @throws PhpSpreadsheet\Exception
     * @throws PhpSpreadsheet\Calculation\Exception
     */
    protected function grabTitlesRow(PhpSpreadsheet\Worksheet\Row $row, int $columnOffset = 1, bool $toLower = false): array
    {
        $titles = [];
        $cellIterator = $row->getCellIterator();
        if ($columnOffset > 1) {
            $cellIterator->seek($columnOffset);
        }
        while ($cellIterator->valid()) {
            $title = trim($cellIterator->current()->getCalculatedValue(), '  ');
            if ($toLower) {
                $title = strtolower($title);
            }
            $titles[$cellIterator->current()->getColumn()] = $title;
            $cellIterator->next();
            if ($cellIterator->current()->getCalculatedValue() === null) {
                break;
            }
        }

        return $titles;
    }
    protected function grabRow(PhpSpreadsheet\Worksheet\Row $row, array $titles, int $columnOffset = 1, bool $process = false, ?array $titleValueMap = null): array
    {
        $data = [];
        $cellIterator = $row->getCellIterator();
        if ($columnOffset > 1) {
            $cellIterator->seek($columnOffset);
        }
        while ($cellIterator->valid()) {
            $col = $cellIterator->current()->getColumn();
            $colIndex = PhpSpreadsheet\Cell\Coordinate::columnIndexFromString($col);
            if (count($titles) + $columnOffset < $colIndex or ($colIndex >= $columnOffset and !key_exists($col, $titles))) {
                break;
            }
            $title = $titles[$col];
            $value = $cellIterator->current()->getCalculatedValue();
            if ($process) {
                $value = $this->processValue($titleValueMap, $title, $value);
            }
            $data[$title] = $value;
            $cellIterator->next();
        }
        return $data;
    }
    protected function processValue(array $titleValueMap, string $title, mixed $value): mixed
    {
        if (!key_exists($title, $titleValueMap)) {
            return $value;
        }
        return match (strtolower($titleValueMap[$title])) {
            'fecha' => (int) $value != $value
                ? implode('-', array_reverse(explode('-', $value)))
                : PhpSpreadsheet\Shared\Date::excelToDateTimeObject($value, 'America/Santiago')->format('Y-m-d'),
            'int' => (int) $value,
            default => $value,
        };
    }
    protected function isExitValue(PhpSpreadsheet\Worksheet\Row $row, array $exitValues, int $columnOffset = 1): bool
    {
        $cellIterator = $row->getCellIterator();
        if ($columnOffset > 1) {
            $cellIterator->seek($columnOffset);
        }
        return in_array($cellIterator->current()->getCalculatedValue(), $exitValues, true);
    }
}
