<?php
// ajax/firmar_receta.php

// 1. MANEJO DE ERRORES GLOBAL PARA EVITAR RESPUESTAS 500 Y HTML ROTO
error_reporting(E_ALL);
ini_set('display_errors', 0); // Ocultar errores normales al output
header('Content-Type: application/json');

function fatal_error_handler()
{
    $error = error_get_last();
    if ($error !== NULL && in_array($error['type'], [E_ERROR, E_PARSE, E_CORE_ERROR, E_COMPILE_ERROR])) {
        ob_clean(); // Limpiar cualquier salida previa corrupta
        echo json_encode([
            'success' => false,
            'message' => 'Error FATAL del servidor: ' . $error['message'] . ' en ' . basename($error['file']) . ':' . $error['line'],
            'type' => 'FATAL'
        ]);
        exit;
    }
}
register_shutdown_function('fatal_error_handler');

// BUFFER PARA ATRAPAR WARNINGS/NOTICES ACCIDENTALES
ob_start();

try {
    session_start();

    require_once "../modelos/FirmaEC.php";
    require_once "../modelos/FirmadorPDF.php";

    // VERIFICAR QUE EL ARCHIVO DE REPORTE EXISTE ANTES DE INCLUIRLO
    if (!file_exists("../reportes/generar_pdf_receta.php")) {
        throw new Exception("Falta archivo crítico: reportes/generar_pdf_receta.php");
    }
    require_once "../reportes/generar_pdf_receta.php";

    require_once "../config/Conexion.php";

    define('FIRMAEC_TOKEN', 'TU_TOKEN_AQUI');
    define('FIRMAEC_ENVIRONMENT', 'pruebas');

    // Helper local: verificar si una tabla existe en la BD del tenant.
    // Algunos tenants ya migraron y no tienen la tabla legacy `receta`.
    if (!function_exists('_firmaRecetaTablaExiste')) {
        function _firmaRecetaTablaExiste($nombreTabla) {
            global $conexion;
            $nombreTabla = preg_replace('/[^a-zA-Z0-9_]/', '', $nombreTabla);
            if ($nombreTabla === '') return false;
            $res = @$conexion->query("SHOW TABLES LIKE '$nombreTabla'");
            return $res && $res->num_rows > 0;
        }
    }

    if (!isset($_GET["op"])) {
        throw new Exception("Operación no definida");
    }

    switch ($_GET["op"]) {

        case 'firmar':
            $idatencion = isset($_POST['idatencion']) ? limpiarCadena($_POST['idatencion']) : '';
            $idempleado = isset($_POST['idempleado']) ? limpiarCadena($_POST['idempleado']) : '';
            $password = isset($_POST['password']) ? $_POST['password'] : '';

            if (empty($idatencion) || empty($idempleado) || empty($password)) {
                throw new Exception('Faltan parámetros (ID o Contraseña)');
            }

            // 1. Verificar si ya está firmada
            //    Consultamos primero atencion_formatos (fuente moderna). Si la tabla
            //    legacy `receta` existe, tambien la usamos como respaldo.
            $resultado = null;
            $sqlFmt = "SELECT 1 AS firmado, ruta_pdf AS ruta_pdf_firmado
                       FROM atencion_formatos
                       WHERE idatencion = '$idatencion' AND tipo_formato = 'RECETA' AND ruta_pdf IS NOT NULL
                       ORDER BY id_atencion_formato DESC LIMIT 1";
            $resultado = ejecutarConsultaSimpleFila($sqlFmt);

            if (!$resultado && _firmaRecetaTablaExiste('receta')) {
                $sql = "SELECT firmado, ruta_pdf_firmado FROM receta WHERE idatencion = '$idatencion'";
                $resultado = ejecutarConsultaSimpleFila($sql);
            }

            if ($resultado && isset($resultado['firmado']) && $resultado['firmado'] == 1) {
                // Ya firmada, devolver éxito
                ob_clean();
                echo json_encode([
                    'success' => true, // Cambiamos a true para que refresque la página
                    'message' => 'Esta receta ya fue firmada anteriormente.',
                    // Enviamos URL si quieren abrirla
                    'url' => isset($resultado['ruta_pdf_firmado']) ? $resultado['ruta_pdf_firmado'] : ''
                ]);
                exit;
            }

            // 2. BUSQUEDA DE CERTIFICADO (Lógica Robusta v3.0)
            $sqlCert = "SELECT ruta_certificado, idempleado FROM certificados_medicos WHERE idempleado='$idempleado' AND estado='activo' LIMIT 1";
            $certData = ejecutarConsultaSimpleFila($sqlCert);

            if (!$certData) {
                $idusuario_alt = isset($_SESSION['idusuario']) ? $_SESSION['idusuario'] : null;
                if ($idusuario_alt && $idusuario_alt != $idempleado) {
                    $sqlCert2 = "SELECT ruta_certificado, idempleado FROM certificados_medicos WHERE idempleado='$idusuario_alt' AND estado='activo' LIMIT 1";
                    $certData = ejecutarConsultaSimpleFila($sqlCert2);
                }
            }

            if (!$certData) {
                throw new Exception('No tiene un certificado digital activo. Vaya a Firma Digital y súbalo.');
            }

            // === LÓGICA DE RECUPERACIÓN NUCLEAR DE RUTA ===
            $rutaBD = $certData['ruta_certificado'];
            $rutaCertEncriptadoAbs = '';

            // A) Intento Base (BD)
            if (strpos($rutaBD, '../') === 0 || strpos($rutaBD, './') === 0) {
                $rutaCertEncriptadoAbs = realpath(__DIR__ . '/' . $rutaBD);
            } elseif (substr($rutaBD, 0, 1) == '/' || preg_match('/^[a-zA-Z]:/', $rutaBD)) {
                // Ruta absoluta
                $rutaCertEncriptadoAbs = $rutaBD;
            } else {
                // Relativa simple
                $rutaCertEncriptadoAbs = realpath(__DIR__ . '/../' . $rutaBD);
            }

            // B) Fallback: Construcción manual segura
            if (!$rutaCertEncriptadoAbs || !file_exists($rutaCertEncriptadoAbs)) {
                $baseDir = dirname(__DIR__);
                $cleanPath = str_replace('../', '', $rutaBD);
                if (substr($cleanPath, 0, 1) == '/')
                    $cleanPath = substr($cleanPath, 1);
                $rutaCertEncriptadoAbs = $baseDir . '/' . $cleanPath;
            }

            // C) Fallback: Por Nombre en carpeta estándar
            if (!file_exists($rutaCertEncriptadoAbs)) {
                $nombreSolo = basename($rutaBD);
                $rutaCertEncriptadoAbs = dirname(__DIR__) . '/files/certificados_encriptados/' . $nombreSolo;
            }

            // D) NUCLEAR: Glob Search (Busca CUALQUIER archivo del usuario)
            if (!file_exists($rutaCertEncriptadoAbs)) {
                $patron = dirname(__DIR__) . '/files/certificados_encriptados/cert_' . $idempleado . '_*.p12.enc';
                $archivos = glob($patron);
                if ($archivos && count($archivos) > 0) {
                    // Usar el más reciente
                    usort($archivos, function ($a, $b) {
                        return filemtime($b) - filemtime($a);
                    });
                    $rutaCertEncriptadoAbs = $archivos[0];
                }
            }
            // ============================================

            if (!file_exists($rutaCertEncriptadoAbs)) {
                throw new Exception("CERTIFICADO PERDIDO. El archivo físico ($rutaBD) no existe en el servidor. SOLUCIÓN: Suba de nuevo su firma.");
            }

            // 3. Desencriptar
            $firmador = new FirmadorPDF();
            $dirTemp = __DIR__ . '/../files/temp_certificates/';
            if (!file_exists($dirTemp))
                mkdir($dirTemp, 0755, true);

            $rutaCertTemp = $dirTemp . 'temp_' . $idempleado . '_' . time() . '.p12';
            if (!defined('MASTER_KEY_CERT'))
                define('MASTER_KEY_CERT', 'ClaveSeguraParaEncriptarCertificados2026!');

            if (!$firmador->desencriptarCertificado($rutaCertEncriptadoAbs, $rutaCertTemp, MASTER_KEY_CERT)) {
                throw new Exception('Error: Clave interna de desencriptado incorrecta o archivo dañado.');
            }

            try {
                // 4. Generar y Firmar
                $infoFirma = [
                    'razon' => 'Receta Medica Electronica',
                    'ubicacion' => 'Ecuador',
                    'medico' => 'Dr/a. ' . (isset($_SESSION['nombre']) ? $_SESSION['nombre'] : 'Medico')
                ];
                $paramsFirma = [
                    'rutaCert' => $rutaCertTemp,
                    'password' => $password,
                    'info' => $infoFirma
                ];

                $rutaPDFFirmado = generarPDFReceta($idatencion, null, $paramsFirma);

                if (!$rutaPDFFirmado || !file_exists($rutaPDFFirmado)) {
                    throw new Exception('Error CRITICO: El PDF se generó pero no aparece en disco.');
                }

                // 5. Mover y Actualizar
                $fecha = date('Y/m/d');
                $carpetaDestino = '../files/recetas_firmadas/' . $fecha;
                if (!file_exists($carpetaDestino))
                    mkdir($carpetaDestino, 0755, true);

                $nombreFinal = 'receta_' . $idatencion . '_firmada_' . date('YmdHis') . '.pdf';
                $rutaFinal = $carpetaDestino . '/' . $nombreFinal;
                $rutaRelativa = 'files/recetas_firmadas/' . $fecha . '/' . $nombreFinal;

                if (!rename($rutaPDFFirmado, $rutaFinal)) {
                    // Fallback para windows/permisos: copy + unlink
                    if (copy($rutaPDFFirmado, $rutaFinal)) {
                        unlink($rutaPDFFirmado);
                    } else {
                        throw new Exception("Error CRITICO: No se pudo mover el PDF a la carpeta final ($rutaFinal)");
                    }
                }

                if (!file_exists($rutaFinal)) {
                    throw new Exception("Error CRITICO: El archivo final no existe tras moverlo ($rutaFinal)");
                }

                $fechaFirma = date('Y-m-d H:i:s');
                $valIdEmpleado = !empty($idempleado) ? "'$idempleado'" : "NULL";

                // Mantener tabla legacy `receta` actualizada SOLO si existe en este tenant.
                // El estado canonico de firma vive en atencion_formatos (ver paso 7).
                if (_firmaRecetaTablaExiste('receta')) {
                    $check = ejecutarConsultaSimpleFila("SELECT count(*) as total FROM receta WHERE idatencion='$idatencion'");
                    if (!$check || $check['total'] == 0) {
                        @ejecutarConsulta("INSERT INTO receta (idatencion, medicamento, cantidad) VALUES ('$idatencion', 'INDICACIONES', 1)");
                    }
                    $sqlUpdate = "UPDATE receta SET firmado=1, fecha_firma='$fechaFirma', ruta_pdf_firmado='$rutaRelativa', idempleado_firma=$valIdEmpleado WHERE idatencion='$idatencion'";
                    // Si falla por columnas distintas (firmado/fecha_firma/etc. no existen
                    // en una version antigua de la tabla), no abortamos la firma:
                    // el registro en atencion_formatos sigue siendo la fuente oficial.
                    if (!@ejecutarConsulta($sqlUpdate)) {
                        error_log("[firmar_receta] UPDATE de tabla legacy `receta` fallo para idatencion=$idatencion (no critico, atencion_formatos es la fuente).");
                    }
                }

                // 6. INSERTAR EN HISTORIAL (DOCUMENTO_MEDICO)
                // Obtenemos idpersona de la atención
                $atencionRow = ejecutarConsultaSimpleFila("SELECT idpersona FROM atencion WHERE idatencion='$idatencion'");
                if ($atencionRow && isset($atencionRow['idpersona'])) {
                    $idpersona = $atencionRow['idpersona'];

                    // Verificar si ya existe documento de esta receta para no duplicar
                    // Buscamos documento tipo receta para esta atencion
                    $docCheck = ejecutarConsultaSimpleFila("SELECT iddocumento FROM documento_medico WHERE idatencion='$idatencion' AND tipo='receta'");

                    if ($docCheck) {
                        // Actualizar existente
                        $iddoc = $docCheck['iddocumento'];
                        ejecutarConsulta("UPDATE documento_medico SET ruta_pdf='$rutaRelativa', firmado=1, fecha_emision='$fechaFirma', idempleado_firma=$valIdEmpleado WHERE iddocumento='$iddoc'");
                    } else {
                        // Insertar nuevo
                        $sqlInsertDoc = "INSERT INTO documento_medico (idatencion, idpersona, tipo, contenido, ruta_pdf, fecha_emision, firmado, idempleado, idempleado_firma, estado)
                                        VALUES ('$idatencion', '$idpersona', 'receta', 'Receta Médica Electrónica', '$rutaRelativa', '$fechaFirma', 1, $valIdEmpleado, $valIdEmpleado, 'emitido')";
                        ejecutarConsulta($sqlInsertDoc);
                    }
                }

                // 7. SINCRONIZACIÓN FORZADA CON ATENCION_FORMATOS (FIX PÉRDIDA DE DOCUMENTOS)
                // CRÍTICO: Garantizar que atencion_formatos tenga la ruta del PDF firmado
                $checkFormat = ejecutarConsultaSimpleFila("SELECT id_atencion_formato FROM atencion_formatos WHERE idatencion='$idatencion' AND tipo_formato='RECETA'");
                if ($checkFormat) {
                    $id_fmt = $checkFormat['id_atencion_formato'];
                    $sqlUpdateFormat = "UPDATE atencion_formatos SET ruta_pdf='$rutaRelativa', fecha_modificacion=NOW() WHERE id_atencion_formato='$id_fmt'";
                    if (!ejecutarConsulta($sqlUpdateFormat)) {
                        error_log("❌ ERROR CRÍTICO: No se pudo sincronizar atencion_formatos para receta #$idatencion");
                    } else {
                        error_log("✅ atencion_formatos sincronizado correctamente para receta #$idatencion - Ruta: $rutaRelativa");
                    }
                } else {
                    // Si no existe, crear registro en atencion_formatos para persistencia
                    $sqlInsertFormat = "INSERT INTO atencion_formatos (idatencion, tipo_formato, estado, ruta_pdf, fecha_creacion, usuario_creacion) 
                                       VALUES ('$idatencion', 'RECETA', 'completado', '$rutaRelativa', NOW(), " . ($idempleado ? "'$idempleado'" : "NULL") . ")";
                    if (ejecutarConsulta($sqlInsertFormat)) {
                        error_log("✅ Registro RECETA creado en atencion_formatos para atención #$idatencion");
                    } else {
                        error_log("⚠️ No se pudo crear registro en atencion_formatos para receta #$idatencion (no crítico si ya existe)");
                    }
                }

                if (file_exists($rutaCertTemp))
                    unlink($rutaCertTemp);

                // EXITO TOTAL - Limpiar buffer y enviar JSON limpio
                if (ob_get_length())
                    ob_clean();
                echo json_encode([
                    'success' => true,
                    'message' => 'Receta firmada correctamente (V3.0 FIXED)',
                    'url' => '../' . $rutaRelativa
                ]);

            } catch (Exception $e) {
                if (file_exists($rutaCertTemp))
                    unlink($rutaCertTemp);
                throw $e;
            }
            break;

        default:
            throw new Exception("Operación desconocida");
    }

} catch (Exception $e) {
    if (ob_get_length())
        ob_clean(); // IMPORTANTE: Borra cualquier warning previo
    echo json_encode(['success' => false, 'message' => $e->getMessage()]);
}
?>