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

use Psr\Http\Message\UploadedFileInterface;
use PhpOffice\PhpSpreadsheet;
use Incoviba\Common\Ideal\Cartola\Banco;

class Santander extends Banco
{
    use withSubBancos;

    protected function columnMap(): array
    {
        return [
            'Fecha' => 'fecha',
            'Descripción' => 'glosa',
            'Nº Docu' => 'documento',
            'Cheques y Otros Cargos' => 'cargo',
            'Cheques y Cargos' => 'cargo',
            'Depósitos y Abonos' => 'abono',
            'Saldo' => 'saldo',
            'Categoría' => 'categoria',
            'Centro costos' => 'centro_costo',
            'Detalle' => 'detalle',
            'Factura o Boleta' => 'identificador',
            'RUT' => 'rut',
            'Nombre' => 'nombres',
        ];
    }

    protected function getFilename(UploadedFileInterface $uploadedFile): string
    {
        $start = $uploadedFile->getStream()->read(10);
        if (str_starts_with($start, '<')) {
            return '/tmp/cartola.html';
        }
        return '/tmp/cartola.xlsx';
    }

    protected function parseFile(string $filename): array
    {
        if (str_ends_with($filename, 'xlsx')) {
            return $this->parseXlsx($filename);
        }
        return $this->parseHtml($filename);
    }
    protected function parseXlsx(string $filename): array
    {
        try {
            $reader = PhpSpreadsheet\IOFactory::createReader('Xlsx');
        } catch (PhpSpreadsheet\Reader\Exception $exception) {
            $this->logger->critical($exception, ['filename' => $filename]);
            return [];
        }
        $xlsx = $reader->load($filename);
        $sheet = $xlsx->getActiveSheet();

        $valueColumns = [
            'Cheques y Otros Cargos',
            'Cheques y Cargos',
            'Depósitos y Abonos',
            'Saldo'
        ];
        $found = false;
        $columns = [];
        $data = [];
        foreach ($sheet->getRowIterator() as $row) {
            if (!$found and $sheet->getCell("A{$row->getRowIndex()}")->getCalculatedValue() === 'Fecha') {
                $found = true;
                foreach ($row->getColumnIterator() as $column) {
                    if ($column->getValue() === null) {
                        break;
                    }
                    $columns[$column->getColumn()] = trim($column->getValue());
                }
                continue;
            }
            if (!$found) {
                continue;
            }
            if ($sheet->getCell("A{$row->getRowIndex()}")->getValue() === null) {
                break;
            }
            $rowData = [];
            foreach ($columns as $columnIndex => $column) {
                $value = $sheet->getCell("{$columnIndex}{$row->getRowIndex()}")->getCalculatedValue();
                $mapped = $this->columnMap()[$column] ?? $column;
                if ($mapped === 'fecha') {
                    $value = PhpSpreadsheet\Shared\Date::excelToDateTimeObject($value)->format('Y-m-d');
                }
                if (in_array($column, $valueColumns)) {
                    $value = (int) $value;
                }
                $rowData[$column] = $value;
            }
            $data []= $rowData;
        }

        return array_reverse($data);
    }
    protected function parseHtml(string $filename): array
    {
        $data = [];
        $lines = explode("\r\n", file_get_contents($filename));
        $columns = [];
        $found = false;
        for ($rowIndex = 0; $rowIndex < count($lines); $rowIndex ++) {
            if (!$found and str_contains($lines[$rowIndex], 'Cuenta Corriente: ')) {
                $found = true;
                $rowIndex += 2;
                $columns = $this->parseHtmlRow($lines, $rowIndex);
                continue;
            }
            if (!$found) {
                continue;
            }
            $row = $this->parseHtmlRow($lines, $rowIndex);
            if (str_contains($row[0], 'Saldo Contable')) {
                break;
            }
            $row = array_combine($columns, $row);
            $row['Fecha'] = implode('-', array_reverse(explode('-', $row['Fecha'])));
            foreach (['Cargo ($)', 'Abono ($)', 'Saldo Diario'] as $column) {
                $row[$column] = (int) str_replace('.', '', $row[$column]);
            }
            $row['N° DOCUMENTO'] = '';
            $data []= $row;
        }

        return array_reverse($data);
    }
    protected function parseHtmlRow(array $lines, int &$rowIndex): array
    {
        if (!str_contains($lines[$rowIndex ++], '<tr>')) {
            return [];
        }
        $data = [];
        while (!str_contains($lines[$rowIndex], '</tr>')) {
            $tags = substr_count($lines[$rowIndex], '<') - substr_count($lines[$rowIndex], '</');
            $ini = 0;
            for ($t = 0; $t < $tags; $t ++) {
                $ini = strpos($lines[$rowIndex], '>', $ini) + 1;
            }
            $end = strpos($lines[$rowIndex], '<', $ini + 1);
            $cell = str_replace(' ', '', substr($lines[$rowIndex], $ini, $end - $ini));
            $encoding = mb_detect_encoding($cell, ['Windows-1252', 'UTF-8']);
            if ($encoding !== 'UTF-8') {
                $cell = mb_convert_encoding($cell, $encoding, 'UTF-8');
                $cell = str_replace('?', '', $cell);
            }
            $data []= $cell;
            $rowIndex ++;
        }
        return $data;
    }
}
