<?php
/**
 * SriGateway.php
 * 
 * MOTOR DE CONEXIÓN REAL CON EL SRI
 * Diseñado para evitar falsos positivos y asegurar que la factura 
 * llegue realmente al portal del SRI.
 */

require_once __DIR__ . '/XmlSigner.php';
require_once __DIR__ . '/SriLogger.php';

class SriGateway
{
    private $ambiente; // 1: Pruebas, 2: Producción
    private $urls = [
        '1' => [
            'recepcion' => 'https://celcer.sri.gob.ec/comprobantes-electronicos-ws/RecepcionComprobantesOffline?wsdl',
            'autorizacion' => 'https://celcer.sri.gob.ec/comprobantes-electronicos-ws/AutorizacionComprobantesOffline?wsdl'
        ],
        '2' => [
            'recepcion' => 'https://cel.sri.gob.ec/comprobantes-electronicos-ws/RecepcionComprobantesOffline?wsdl',
            'autorizacion' => 'https://cel.sri.gob.ec/comprobantes-electronicos-ws/AutorizacionComprobantesOffline?wsdl'
        ]
    ];
    
    private $logger;

    public function __construct($ambiente = '2')
    {
        $this->ambiente = $ambiente;
        $this->logger = new SriLogger();
    }

    /**
     * Proceso completo: Firmar -> Recibir -> Autorizar
     * RETORNA Solo éxito si el SRI AUTORIZA realmente.
     */
    public function procesarComprobante($xmlFirmado, $claveAcceso)
    {
        // 1. RECEPCIÓN
        $resRecepcion = $this->enviarARecepcion($xmlFirmado);
        
        if (!$resRecepcion['success']) {
            return $resRecepcion; // Error en recepción (ej: RUC inválido, Clave duplicada, etc)
        }

        // 2. AUTORIZACIÓN (Polling con seguridad)
        $intentos = 0;
        $maxIntentos = 10;
        $pausa = 2; // segundos entre intentos

        while ($intentos < $maxIntentos) {
            sleep($pausa);
            $resAutorizacion = $this->consultarAutorizacion($claveAcceso);
            
            if ($resAutorizacion['success'] && $resAutorizacion['estado'] === 'AUTORIZADO') {
                return $resAutorizacion; // ÉXITO REAL
            }

            // Si el SRI ya rechazó definitivamente (NO AUTORIZADO)
            if ($resAutorizacion['estado'] === 'NO AUTORIZADO') {
                return $resAutorizacion;
            }

            $intentos++;
        }

        return [
            'success' => false,
            'estado' => 'TIEMPO_EXCEDIDO',
            'message' => 'El SRI recibió exitosamente su factura, se mostrara autorizada en el portal en 24 horas , revise su Ride en Historial.',
            'claveAcceso' => $claveAcceso
        ];
    }

    public function enviarARecepcion($xmlString)
    {
        try {
            $client = $this->getSoapClient($this->urls[$this->ambiente]['recepcion']);
            $params = ['xml' => $xmlString];
            $result = $client->validarComprobante($params);

            $this->logger->log('DEBUG_RECEPCION', "Respuesta SRI:", $result);

            // La respuesta del SRI viene envuelta en RespuestaRecepcionComprobante
            $resp = isset($result->RespuestaRecepcionComprobante) ? $result->RespuestaRecepcionComprobante : $result;
            $estado = isset($resp->estado) ? $resp->estado : '';

            if ($estado === 'RECIBIDA') {
                return ['success' => true, 'estado' => 'RECIBIDA'];
            } else {
                // Analizar por qué fue devuelta
                $mensajes = [];
                if (isset($resp->comprobantes->comprobante->mensajes->mensaje)) {
                    $msgs = $resp->comprobantes->comprobante->mensajes->mensaje;
                    // Si hay varios mensajes, viene como array. Si hay uno, como objeto.
                    $arrayMsgs = is_array($msgs) ? $msgs : [$msgs];
                    
                    foreach ($arrayMsgs as $m) {
                        $txt = isset($m->mensaje) ? $m->mensaje : 'Error desconocido';
                        $info = isset($m->informacionAdicional) ? " (" . $m->informacionAdicional . ")" : '';
                        $mensajes[] = $txt . $info;
                    }
                }

                // Caso especial: Ya está registrada o en proceso (Error 43 o 70)
                $rawResponse = json_encode($result);
                if (strpos($rawResponse, '"43"') !== false || strpos($rawResponse, '"70"') !== false) {
                    return ['success' => true, 'estado' => 'RECIBIDA', 'info' => 'Ya registrada previamente'];
                }

                $msgFinal = count($mensajes) > 0 ? implode(" | ", $mensajes) : 'El SRI no proporcionó detalles (Estructura XML posiblemente muy dañada)';

                return [
                    'success' => false,
                    'estado' => 'DEVUELTA',
                    'message' => 'El SRI devolvió el documento: ' . $msgFinal,
                    'detalle' => $result
                ];
            }
        } catch (Exception $e) {
            return ['success' => false, 'message' => 'Error de conexión con recepción SRI: ' . $e->getMessage()];
        }
    }

    public function consultarAutorizacion($claveAcceso)
    {
        try {
            $client = $this->getSoapClient($this->urls[$this->ambiente]['autorizacion']);
            $params = ['claveAccesoComprobante' => $claveAcceso];
            $result = $client->autorizacionComprobante($params);

            $this->logger->log('DEBUG_AUTH', "Consulta Clave: $claveAcceso", $result);

            if (!isset($result->autorizaciones->autorizacion)) {
                return ['success' => false, 'estado' => 'PROCESANDO', 'message' => 'Aún no aparece en el sistema de autorización.'];
            }

            $autorizaciones = $result->autorizaciones->autorizacion;
            if (is_array($autorizaciones)) {
                // Buscar la que diga AUTORIZADO
                $finalAuth = end($autorizaciones);
                foreach ($autorizaciones as $auth) {
                    if ($auth->estado === 'AUTORIZADO') {
                        $finalAuth = $auth;
                        break;
                    }
                }
                $autorizaciones = $finalAuth;
            }

            if ($autorizaciones->estado === 'AUTORIZADO') {
                return [
                    'success' => true,
                    'estado' => 'AUTORIZADO',
                    'numeroAutorizacion' => $autorizaciones->numeroAutorizacion,
                    'fechaAutorizacion' => $autorizaciones->fechaAutorizacion,
                    'xml' => $autorizaciones->comprobante
                ];
            } else {
                $mensajes = [];
                if (isset($autorizaciones->mensajes->mensaje)) {
                    $msgs = $autorizaciones->mensajes->mensaje;
                    if (is_array($msgs)) {
                        foreach ($msgs as $m) $mensajes[] = $m->mensaje . " - " . (isset($m->informacionAdicional) ? $m->informacionAdicional : '');
                    } else {
                        $mensajes[] = $msgs->mensaje;
                    }
                }
                return [
                    'success' => false,
                    'estado' => 'NO AUTORIZADO',
                    'message' => 'Rechazado por SRI: ' . implode(" | ", $mensajes)
                ];
            }
        } catch (Exception $e) {
            return ['success' => false, 'message' => 'Error de conexión con autorización SRI: ' . $e->getMessage()];
        }
    }

    private function getSoapClient($wsdl)
    {
        return new SoapClient($wsdl, [
            'trace' => 1,
            'exceptions' => true,
            'connection_timeout' => 10,
            'stream_context' => stream_context_create([
                'ssl' => [
                    'verify_peer' => false,
                    'verify_peer_name' => false,
                    'allow_self_signed' => true
                ]
            ])
        ]);
    }
}
