<?php

class GeneradorXMLEcuador21
{
    /**
     * Genera el XML de NOTA DE DÉBITO SRI Ecuador (codDoc = 05, versión 1.0.0)
     *
     * @param string $ruta   Ruta donde se guardará el XML
     * @param array  $emisor Datos del emisor (infoTributaria)
     * @param array  $cliente Datos del comprador
     * @param array  $infoND Datos de infoNotaDebito (fecha, totales, doc modificado, etc.)
     * @param array  $detalles No se usan directamente en la ND (los totales ya vienen calculados en $infoND),
     *                         pero se deja el parámetro para mantener la misma firma que en otros métodos.
     */
    public function crearXMLNotaDebito(string $ruta, array $emisor, array $cliente, array $infoND, array $detalles): void
    {
        $doc = new DOMDocument('1.0', 'UTF-8');
        $doc->formatOutput = true;
        $doc->preserveWhiteSpace = false;

        // <notaDebito>
        $nota = $doc->createElement('notaDebito');
        $nota->setAttribute('id', 'comprobante');
        $nota->setAttribute('version', '1.0.0'); // versión oficial ND SRI
        $doc->appendChild($nota);

        /* =========================================
           <infoTributaria>
           ========================================= */
        $infoTributaria = $nota->appendChild($doc->createElement('infoTributaria'));
        $camposTrib = [
            'ambiente', 'tipoEmision', 'razonSocial', 'nombreComercial',
            'ruc', 'claveAcceso', 'codDoc', 'estab', 'ptoEmi',
            'secuencial', 'dirMatriz'
        ];

        foreach ($camposTrib as $campo) {
            if (isset($emisor[$campo]) && $emisor[$campo] !== '') {
                $infoTributaria->appendChild($doc->createElement($campo, $emisor[$campo]));
            }
        }

        /* =========================================
           <infoNotaDebito>  (orden según XSD SRI)
           ========================================= */
        $info = $nota->appendChild($doc->createElement('infoNotaDebito'));

        // 1) fechaEmision
        $this->appendIfSet($doc, $info, 'fechaEmision', $infoND);
        // 2) dirEstablecimiento
        $this->appendIfSet($doc, $info, 'dirEstablecimiento', $infoND);
        // 3) tipoIdentificacionComprador
        $this->appendIfSet($doc, $info, 'tipoIdentificacionComprador', $infoND);
        // 4) razonSocialComprador
        $this->appendIfSet($doc, $info, 'razonSocialComprador', $infoND);
        // 5) identificacionComprador
        $this->appendIfSet($doc, $info, 'identificacionComprador', $infoND);
        // 6) obligadoContabilidad (del emisor)
        if (!empty($emisor['obligadoContabilidad'])) {
            $info->appendChild($doc->createElement('obligadoContabilidad', $emisor['obligadoContabilidad']));
        }
        // 7) rise (opcional)
        if (!empty($emisor['rise'])) {
            $info->appendChild($doc->createElement('rise', $emisor['rise']));
        }
        // 8) codDocModificado
        $this->appendIfSet($doc, $info, 'codDocModificado', $infoND);
        // 9) numDocModificado
        $this->appendIfSet($doc, $info, 'numDocModificado', $infoND);
        // 10) fechaEmisionDocSustento (dd/mm/aaaa con año 20xx)
        $this->appendIfSet($doc, $info, 'fechaEmisionDocSustento', $infoND);
        // 11) totalSinImpuestos
        $this->appendIfSet($doc, $info, 'totalSinImpuestos', $infoND);

        // 12) <impuestos>
        $impuestosNode = $info->appendChild($doc->createElement('impuestos'));

        if (!empty($infoND['totalConImpuestos']) && is_array($infoND['totalConImpuestos'])) {
            foreach ($infoND['totalConImpuestos'] as $imp) {
                $impuesto = $impuestosNode->appendChild($doc->createElement('impuesto'));

                $codigo           = $imp['codigo'] ?? '2';
                $codigoPorcentaje = $imp['codigoPorcentaje'] ?? '2';
                $baseImponible    = isset($imp['baseImponible']) ? (float)$imp['baseImponible'] : 0.0;
                $valor            = isset($imp['valor']) ? (float)$imp['valor'] : 0.0;

                // tarifa = (valor/baseImponible)*100 cuando baseImponible > 0
                $tarifa = $baseImponible > 0 ? ($valor * 100 / $baseImponible) : 0.0;

                $impuesto->appendChild($doc->createElement('codigo', $codigo));
                $impuesto->appendChild($doc->createElement('codigoPorcentaje', $codigoPorcentaje));
                $impuesto->appendChild($doc->createElement('tarifa', number_format($tarifa, 2, '.', '')));
                $impuesto->appendChild($doc->createElement('baseImponible', number_format($baseImponible, 2, '.', '')));
                $impuesto->appendChild($doc->createElement('valor', number_format($valor, 2, '.', '')));
            }
        }

        // 13) valorTotal
        $this->appendIfSet($doc, $info, 'valorTotal', $infoND);

        // *** NO va <moneda> en Nota de Débito SRI ***

        // 14) <pagos> (obligatorio en ND)
        $pagos = $info->appendChild($doc->createElement('pagos'));
        $pago  = $pagos->appendChild($doc->createElement('pago'));

        $formaPago    = $infoND['formaPago']    ?? '01';       // 01 = sin utilización del sistema financiero
        $totalPago    = $infoND['valorTotal']   ?? '0.00';
        $plazo        = $infoND['plazo']        ?? '0';
        $unidadTiempo = $infoND['unidadTiempo'] ?? 'dias';

        $pago->appendChild($doc->createElement('formaPago', $formaPago));
        $pago->appendChild($doc->createElement('total', $totalPago));
        $pago->appendChild($doc->createElement('plazo', $plazo));
        $pago->appendChild($doc->createElement('unidadTiempo', $unidadTiempo));

        /* =========================================
           <motivos>
           ========================================= */
        $motivos    = $nota->appendChild($doc->createElement('motivos'));
        $motivoNode = $motivos->appendChild($doc->createElement('motivo'));

        $razonMotivo = $infoND['motivo'] ?? 'Motivo de la nota de débito';
        $valorMotivo = $infoND['totalSinImpuestos'] ?? '0.00';

        $motivoNode->appendChild($doc->createElement('razon', $razonMotivo));
        $motivoNode->appendChild($doc->createElement('valor', $valorMotivo));

        /* =========================================
           <infoAdicional>
           ========================================= */
        $infoAdicional = $nota->appendChild($doc->createElement('infoAdicional'));

        if (!empty($cliente['direccion'])) {
            $campo = $doc->createElement('campoAdicional', htmlspecialchars($cliente['direccion']));
            $campo->setAttribute('nombre', 'Dirección');
            $infoAdicional->appendChild($campo);
        }

        if (!empty($cliente['email'])) {
            $campo = $doc->createElement('campoAdicional', htmlspecialchars($cliente['email']));
            $campo->setAttribute('nombre', 'Email');
            $infoAdicional->appendChild($campo);
        }

        // Guardar archivo XML
        $doc->save($ruta);
    }

    /**
     * Helper para agregar un nodo solo si existe en el array fuente
     */
    private function appendIfSet(DOMDocument $doc, DOMElement $parent, string $key, array $source): void
    {
        if (isset($source[$key]) && $source[$key] !== '') {
            $parent->appendChild($doc->createElement($key, $source[$key]));
        }
    }
}

