<?php
namespace Gestoreasy\Core\Fiscal\Sped\Blocks;

use PDO;
use Gestoreasy\Core\Fiscal\Sped\BlockInterface;
use Gestoreasy\Core\Fiscal\Sped\Period;

class BlockD implements BlockInterface {
    public function id(): string { return 'D'; }

    public function generate(PDO $pdo, Period $period, array $options = []): array {
        $lines = [];

        // Movimento quando há documentos de transporte fornecidos via payload opcional
        $docs = is_array($options['d100_docs'] ?? null) ? $options['d100_docs'] : [];
        $hasMovement = !empty($docs);

        // D001 - Abertura do Bloco D
        $lines[] = sprintf('|D001|%d|', $hasMovement ? 0 : 1);

        // D100/D190 conforme dados de serviços de transporte (quando fornecidos)
        foreach ($this->generateD100D190($pdo, $period, $docs) as $ln) { $lines[] = $ln; }

        // D990 - Encerramento do Bloco D
        $qtd_lin_d = count($lines) + 1;
        $lines[] = sprintf('|D990|%d|', $qtd_lin_d);
        return $lines;
    }

    /**
     * Geração de D100/D190 a partir de payload opcional.
     * Retorna array de linhas quando houver documentos de transporte (CT-e/serviços).
     */
    private function generateD100D190(PDO $pdo, Period $period, array $docs): array {
        $out = [];
        foreach ($docs as $d) {
            // Campos mínimos e formatos seguros
            $ind_oper = (int)($d['ind_oper'] ?? 1); // 0=entrada, 1=saída
            $ind_emit = (int)($d['ind_emit'] ?? 0); // 0=emissão própria
            $cod_mod  = (string)($d['cod_mod'] ?? '57'); // CT-e
            $cod_sit  = (string)($d['cod_sit'] ?? '00');
            $ser      = (string)($d['serie'] ?? '');
            $num_doc  = (string)($d['num_doc'] ?? '');
            $chv_cte  = (string)($d['chv_cte'] ?? '');
            $dt_doc   = $this->ymd((string)($d['dt_doc'] ?? $period->startDate()));
            $dt_a_p   = $this->ymd((string)($d['dt_apur'] ?? $period->endDate()));
            $vl_doc   = (float)($d['vl_doc'] ?? 0);
            $vl_desc  = (float)($d['vl_desc'] ?? 0);
            $vl_serv  = (float)($d['vl_serv'] ?? $vl_doc);
            $vl_bc_icms   = (float)($d['vl_bc_icms'] ?? 0);
            $vl_icms      = (float)($d['vl_icms'] ?? 0);
            $vl_bc_icms_st= (float)($d['vl_bc_icms_st'] ?? 0);
            $vl_icms_st   = (float)($d['vl_icms_st'] ?? 0);
            $vl_red_bc    = (float)($d['vl_red_bc'] ?? 0);
            $vl_pis       = (float)($d['vl_pis'] ?? 0);
            $vl_cofins    = (float)($d['vl_cofins'] ?? 0);
            $cod_cta      = (string)($d['cod_cta'] ?? '');

            // |D100|IND_OPER|IND_EMIT|COD_MOD|COD_SIT|SER|NUM_DOC|CHV_CTE|DT_DOC|DT_A_P|VL_DOC|VL_DESC|VL_SERV|VL_BC_ICMS|VL_ICMS|VL_BC_ICMS_ST|VL_ICMS_ST|VL_RED_BC|VL_PIS|VL_COFINS|COD_CTA|
            $out[] = sprintf(
                '|D100|%d|%d|%s|%s|%s|%s|%s|%s|%s|%.2f|%.2f|%.2f|%.2f|%.2f|%.2f|%.2f|%.2f|%.2f|%s|',
                $ind_oper, $ind_emit, $cod_mod, $cod_sit, $ser, $num_doc, $chv_cte, $dt_doc, $dt_a_p,
                $vl_doc, $vl_desc, $vl_serv, $vl_bc_icms, $vl_icms, $vl_bc_icms_st, $vl_icms_st, $vl_red_bc, $vl_pis, $vl_cofins, $cod_cta
            );

            // Itens/D190 por documento (se houver)
            $items = is_array($d['itens'] ?? null) ? $d['itens'] : [];
            foreach ($items as $it) {
                $cst   = (string)($it['cst'] ?? '00');
                $cfop  = (string)($it['cfop'] ?? '5353');
                $aliq  = (float)($it['aliq_icms'] ?? 0); // percent
                $vl_opr = (float)($it['vl_opr'] ?? 0);
                $vl_bc  = (float)($it['vl_bc_icms'] ?? 0);
                $vl_icm = (float)($it['vl_icms'] ?? 0);
                $vl_bc_st = (float)($it['vl_bc_icms_st'] ?? 0);
                $vl_icm_st= (float)($it['vl_icms_st'] ?? 0);
                $vl_red   = (float)($it['vl_red_bc'] ?? 0);
                $vl_pis_i = (float)($it['vl_pis'] ?? 0);
                $vl_cof_i = (float)($it['vl_cofins'] ?? 0);
                $cod_obs  = (string)($it['cod_obs'] ?? '');
                // Se a alíquota não vier, derive de VL_BC_ICMS e VL_ICMS
                if (($aliq <= 0) && ($vl_bc > 0) && ($vl_icm > 0)) {
                    $aliq = round(($vl_icm / $vl_bc) * 100, 2);
                }
                // |D190|CST|CFOP|ALIQ_ICMS|VL_OPR|VL_BC_ICMS|VL_ICMS|VL_BC_ICMS_ST|VL_ICMS_ST|VL_RED_BC|VL_PIS|VL_COFINS|COD_OBS|
                $out[] = sprintf(
                    '|D190|%s|%s|%.2f|%.2f|%.2f|%.2f|%.2f|%.2f|%.2f|%.2f|%.2f|%s|',
                    $cst, $cfop, $aliq, $vl_opr, $vl_bc, $vl_icm, $vl_bc_st, $vl_icm_st, $vl_red, $vl_pis_i, $vl_cof_i, $cod_obs
                );
            }
        }
        return $out;
    }

    private function ymd(string $d): string {
        $t = strtotime($d ?: '');
        if ($t === false) return str_replace('-', '', date('Y-m-d'));
        return str_replace('-', '', date('Y-m-d', $t));
    }
}