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

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

class OfficeBanking extends Banco
{
    use isExcel;

    public function is(string $filename): bool
    {
        if (!str_ends_with($filename, 'xlsx')) {
            return false;
        }
        try {
            $reader = PhpSpreadsheet\IOFactory::createReader('Xlsx');
        } catch (PhpSpreadsheet\Reader\Exception) {
            return false;
        }
        $xlsx = $reader->load($filename);
        $sheet = $xlsx->getActiveSheet();
        $subtitle = $sheet->getCell('A1')->getCalculatedValue();
        $valid = [
            'Consulta de movimientos de Cuentas Corrientes',
            'Cartolas históricas de Cuentas Corrientes'
        ];
        if ($subtitle !== null and in_array(trim($subtitle), $valid)) {
            return true;
        }
        $subtitle = $sheet->getCell('A2')->getCalculatedValue();
        return $subtitle !== null and in_array(trim($subtitle), $valid);
    }

    protected function columnMap(): array
    {
        return [
            'cargo' => 'cargo',
            'abono' => 'abono',
            'DESCRIPCIÓN MOVIMIENTO' => 'glosa',
            'FECHA' => 'fecha',
            'N° DOCUMENTO' => 'documento',
            'SALDO' => 'saldo',
            'Fecha' => 'fecha',
            'Cargo ($)' => 'cargo',
            'Abono ($)' => 'abono',
            'Descripcin' => 'glosa',
            'Saldo Diario' => 'saldo',
            'Categoría' => 'categoria',
            'Centro costos' => 'centro_costo',
            'Detalle' => 'detalle',
            'Factura Boleta' => 'identificador',
            'RUT' => 'rut',
            'Nombres' => 'nombres',
            'Depto' => 'identificador'
        ];
    }
    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();

        $found = false;
        $columns = [];
        $data = [];
        $titleValueMap = [
            'MONTO' => 'int'
        ];
        $rowIterator = $sheet->getRowIterator();
        while ($rowIterator->valid()) {
            $row = $rowIterator->current();
            $first = $sheet->getCell("A{$row->getRowIndex()}")->getCalculatedValue();
            if ($first !== null) {
                $first = trim($first);
            }
            if (!$found and $first === 'MONTO') {
                $found = true;
                $columns = $this->grabTitlesRow($row);
                $rowIterator->next();
                continue;
            }
            if (!$found) {
                $rowIterator->next();
                continue;
            }
            if ($first === 'Resumen comisiones' or $first === null) {
                break;
            }
            $rowData = $this->grabRow($row, $columns, process: true, titleValueMap: $titleValueMap);
            $fecha = explode('/', $rowData['FECHA']);
            $rowData['FECHA'] = $fecha[2] . '-' . $fecha[1] . '-' . $fecha[0];
            switch ($rowData['CARGO/ABONO']) {
                case 'C':
                    $rowData['abono'] = 0;
                    $rowData['cargo'] = -$rowData['MONTO'];
                    break;
                default:
                    $rowData['abono'] = $rowData['MONTO'];
                    $rowData['cargo'] = 0;
                    break;
            }
            $data[] = $rowData;
            $rowIterator->next();
        }

        return $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;
    }
}
