<?php
/**
 * Registra un evento de auditoría en la base de datos (VERSIÓN 12 - Implementación C5, C6, C7, C8).
 *
 * Esta función centraliza todo el registro de logs de la aplicación, manejando la lógica
 * de anti-duplicados, IP, y conversión segura de tipos NULL/INT para PDO.
 *
 * @param PDO $db Objeto de conexión a la BD (de 'db.php').
 * @param string $action_string La ACCIÓN (ej. 'LOGIN_SUCCESS', 'USER_REGISTERED').
 * @param int|null $actor_user_id El ID del usuario que realiza la acción (el admin/fisio).
 * @param string|null $actor_username El nombre del usuario que realiza la acción (para denormalizar).
 * @param string $details Texto descriptivo.
 * @param int|null $target_user_id El ID del usuario "víctima" (ej. el paciente).
 * @param int|null $target_object_id El ID de un objeto (ej. el ID del tratamiento).
 * @return bool True si se registró, False si hubo un error.
 */
function registrar_log($db, $action_string, $actor_user_id, $actor_username, $details = '', $target_user_id = null, $target_object_id = null) {

    // --- Lógica de Anti-Duplicados ---
    if (session_status() === PHP_SESSION_NONE) {
        session_start();
    }

    $log_fingerprint = $action_string . '|' . ($actor_user_id ?? 'null') . '|' . ($target_user_id ?? 'null') . '|' . ($target_object_id ?? 'null');
    $current_time = time();

    if (isset($_SESSION['last_log_fingerprint']) && $_SESSION['last_log_fingerprint'] === $log_fingerprint) {
        if (isset($_SESSION['last_log_timestamp']) && ($current_time - $_SESSION['last_log_timestamp']) < 3) {
            return true;
        }
    }

    // 4. Obtención de IP
    $ip_address = 'UNKNOWN';
    if (!empty($_SERVER['HTTP_CLIENT_IP'])) {
        $ip_address = $_SERVER['HTTP_CLIENT_IP'];
    } elseif (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) {
        $ip_address = $_SERVER['HTTP_X_FORWARDED_FOR'];
    } else {
        $ip_address = $_SERVER['REMOTE_ADDR'] ?? 'UNKNOWN';
    }

    // 5. Normalización de valores para PDO
    $actor_user_id_int = $actor_user_id ?? null;
    $target_user_id_int = $target_user_id ?? null;
    $target_object_id_int = $target_object_id ?? null;
    $actor_username_str = $actor_username ?? 'N/A';


    try {
        $sql = "INSERT INTO log_auditoria
                    (actor_user_id, actor_username, action, details, target_user_id, target_object_id, ip_address, timestamp)
                VALUES
                    (:actor_user_id, :actor_username, :action, :details, :target_user_id, :target_object_id, :ip_address, CURRENT_TIMESTAMP)";

        $stmt = $db->prepare($sql);

        // ★★★ BINDING SEGURO PARA NULL/INT ★★★
        $stmt->bindValue(':actor_user_id', $actor_user_id_int, $actor_user_id_int === null ? PDO::PARAM_NULL : PDO::PARAM_INT);
        $stmt->bindValue(':actor_username', $actor_username_str, PDO::PARAM_STR);
        $stmt->bindValue(':action', $action_string, PDO::PARAM_STR);
        $stmt->bindValue(':details', $details, PDO::PARAM_STR);
        $stmt->bindValue(':ip_address', $ip_address, PDO::PARAM_STR);

        $stmt->bindValue(':target_user_id', $target_user_id_int, $target_user_id_int === null ? PDO::PARAM_NULL : PDO::PARAM_INT);
        $stmt->bindValue(':target_object_id', $target_object_id_int, $target_object_id_int === null ? PDO::PARAM_NULL : PDO::PARAM_INT);

        $success = $stmt->execute();

        // Guardar huella
        if ($success) {
            $_SESSION['last_log_fingerprint'] = $log_fingerprint;
            $_SESSION['last_log_timestamp'] = $current_time;
        }

        return $success;

    } catch (PDOException $e) {
        error_log("Error fatal al registrar log de auditoría (v9): " . $e->getMessage());
        return false;
    }
}


// =================================================================
// ★★★ GRUPO I: FUNCIONES DE ACCESO, REGISTRO Y SUPLANTACIÓN (A1, A2, A3, A4, B4) ★★★
// =================================================================

// [A2] LOGIN FALLIDO
function registrar_login_fallido($db, $email) {
    $stmt = $db->prepare("SELECT id FROM cuentas WHERE email = ?");
    $stmt->execute([$email]);
    $user = $stmt->fetch(PDO::FETCH_ASSOC);
    $target_id = $user['id'] ?? null;
    $details = "Intento de login fallido para email: " . $email;
    registrar_log($db, 'LOGIN_FAIL', null, 'N/A', $details, $target_id);
}

// [A1] LOGIN EXITOSO
function registrar_login_exitoso($db, $user) {
    $actor_name = ($user['nombre'] ?? 'Desconegut') . ' ' . ($user['apellido'] ?? '');
    $details = "Login con éxito. Rol: " . ($user['rol'] ?? 'N/A');
    registrar_log($db, 'LOGIN_SUCCESS', $user['id'], $actor_name, $details, $user['id']);
}

// [B4] REGISTRO EXITOSO
function registrar_registro_exitoso($db, $new_user_id, $new_user_email) {
    $details = "Nou pacient registrat amb èxit. Email: " . $new_user_email;
    registrar_log($db, 'USER_REGISTERED', null, 'N/A', $details, $new_user_id);
}

// [A3] INICIO DE SUPLANTACIÓN
function registrar_impersonate_start($db, $admin_id, $admin_name, $target_id, $target_info) {
    registrar_log(
        $db,
        'IMPERSONATE_START',
        $admin_id,
        $admin_name,
        'Inici de suplantació al compte: ' . $target_info,
        $target_id
    );
}

// [A4] FIN DE SUPLANTACIÓN
function registrar_impersonate_stop($db, $admin_id, $admin_name, $target_id, $target_info) {
    registrar_log(
        $db,
        'IMPERSONATE_STOP',
        $admin_id,
        $admin_name,
        'Fi de suplantació al compte: ' . $target_info,
        $target_id
    );
}


// =================================================================
// ★★★ GRUPO II: FUNCIONES DE SEGURIDAD DE CONTRASEÑA (B5 y B6) ★★★
// =================================================================

/**
 * Registra una solicitud de reseteo de contraseña (B5: PASSWORD_RESET_REQUEST).
 *
 * @param PDO $db Objeto de conexión a la BD.
 * @param string $email El email que solicitó el reseteo.
 * @param int|null $target_user_id ID del usuario objetivo (si existe en la BBDD).
 */
function registrar_reset_solicitado($db, $email, $target_user_id = null) {
    $details = "Solicitud de reseteo de contraseña para email: " . $email;

    // El actor es NULL ('N/A') ya que no está autenticado
    registrar_log(
        $db,
        'PASSWORD_RESET_REQUEST',
        null,
        'N/A',
        $details,
        $target_user_id
    );
}

/**
 * Registra un reseteo de contraseña completado (B6: PASSWORD_RESET_COMPLETED).
 *
 * @param PDO $db Objeto de conexión a la BD.
 * @param int $target_user_id ID del usuario que reseteó su contraseña.
 * @param string $target_user_email Email del usuario reseteado.
 */
function registrar_reset_completado($db, $target_user_id, $target_user_email) {
    $details = "Reseteo de contraseña completado para email: " . $target_user_email;

    // El actor es NULL ('N/A') ya que el usuario aún no ha iniciado sesión, pero SÍ está identificado por el token.
    registrar_log(
        $db,
        'PASSWORD_RESET_COMPLETED',
        null,
        'N/A',
        $details,
        $target_user_id
    );
}


// =================================================================
// ★★★ GRUPO III: FUNCIONES DE ADMINISTRACIÓN Y GOBERNANZA (A5, A6, A7, A8, B1, B7, B8, C9-C13) ★★★
// =================================================================

// [A8] CREACIÓN MANUAL DE BACKUP
function registrar_backup_creado($db, $actor_id, $actor_name, $filename) {
    registrar_log(
        $db,
        'BACKUP_CREATED',
        $actor_id,
        $actor_name,
        'Creació manual d\'un arxiu de còpia de seguretat: ' . $filename
    );
}

// [A5] RESTAURACIÓN DE BACKUP
function registrar_backup_restaurado($db, $actor_id, $actor_name, $filename) {
    registrar_log(
        $db,
        'BACKUP_RESTORED',
        $actor_id,
        $actor_name,
        'Canvi massiu de dades (Restauració de BD): ' . $filename
    );
}

// [A6] ELIMINACIÓN DE ARCHIVO DE BACKUP
function registrar_backup_eliminado($db, $actor_id, $actor_name, $filename) {
    registrar_log(
        $db,
        'BACKUP_DELETED',
        $actor_id,
        $actor_name,
        'Destrucció d\'un arxiu de seguretat: ' . $filename
    );
}

// [A7] PURGA DE DATOS HUÉRFANOS
function registrar_purga_ejecutada($db, $actor_id, $actor_name, $detail_info) {
    registrar_log(
        $db,
        'PURGE_EVOLUTIONS',
        $actor_id,
        $actor_name,
        'Purga de registres: ' . $detail_info
    );
}

// [B1] CAMBIO DE CONTRASEÑA PROPIA
function registrar_password_cambiada($db, $actor_id, $actor_name) {
    registrar_log(
        $db,
        'PASSWORD_CHANGED_SELF',
        $actor_id,
        $actor_name,
        'Contrasenya canviada per l\'usuari.'
    );
}

// [B7] ACTUALIZACIÓN DE PERFIL
function registrar_perfil_actualizado($db, $actor_id, $actor_name, $detail_info) {
    registrar_log(
        $db,
        'USER_PROFILE_UPDATED',
        $actor_id,
        $actor_name,
        'Dades de perfil actualitzades: ' . $detail_info
    );
}

// [B8] ACTUALIZACIÓN DE PREFERENCIAS
function registrar_preferencias_actualizadas($db, $actor_id, $actor_name, $detail_info) {
    registrar_log(
        $db,
        'USER_PREFS_UPDATED',
        $actor_id,
        $actor_name,
        'Preferències d\'interfície actualitzades: ' . $detail_info
    );
}

// [C9] GUARDAR CONFIGURACIÓN DE EMAILS
function registrar_config_emails_guardada($db, $actor_id, $actor_name, $detail_info) {
    registrar_log(
        $db,
        'EMAIL_SETTINGS_UPDATED',
        $actor_id,
        $actor_name,
        'Configuració d\'emails actualitzada. Dades: ' . $detail_info
    );
}

// [C10] AÑADIR EMAIL BANEADO
function registrar_email_baneado_anadido($db, $actor_id, $actor_name, $email, $reason) {
    registrar_log(
        $db,
        'BANNED_EMAIL_ADDED',
        $actor_id,
        $actor_name,
        'Email afegit a la llista de baneig: ' . $email . '. Motiu: ' . $reason
    );
}

// [C11] ELIMINAR EMAIL BANEADO
function registrar_email_baneado_eliminado($db, $actor_id, $actor_name, $email) {
    registrar_log(
        $db,
        'BANNED_EMAIL_REMOVED',
        $actor_id,
        $actor_name,
        'Email eliminat de la llista de baneig: ' . $email
    );
}

// [C12] AÑADIR CONTRASEÑA PROHIBIDA
function registrar_pass_prohibida_anadida($db, $actor_id, $actor_name, $pass_text) {
    registrar_log(
        $db,
        'PROHIBITED_PASS_ADDED',
        $actor_id,
        $actor_name,
        'Contrasenya afegida a la llista de prohibides (Text: ' . substr($pass_text, 0, 5) . '...).'
    );
}

// [C13] ELIMINAR CONTRASEÑA PROHIBIDA
function registrar_pass_prohibida_eliminada($db, $actor_id, $actor_name, $pass_text) {
    registrar_log(
        $db,
        'PROHIBITED_PASS_REMOVED',
        $actor_id,
        $actor_name,
        'Contrasenya eliminada de la llista de prohibides (Text: ' . substr($pass_text, 0, 5) . '...).'
    );
}

// [C1] VISUALIZACIÓN DE FICHA DE PACIENTE
function registrar_paciente_visto($db, $actor_id, $actor_name, $target_id) {
    registrar_log(
        $db,
        'PATIENT_RECORD_VIEWED',
        $actor_id,
        $actor_name,
        'Accés a la fitxa confidencial del pacient (ID: ' . $target_id . ')',
        $target_id
    );
}

// [C2] ELIMINACIÓN DE PACIENTE
function registrar_paciente_eliminado($db, $actor_id, $actor_name, $patient_info) {
    registrar_log(
        $db,
        'PATIENT_DELETED',
        $actor_id,
        $actor_name,
        'Eliminació permanent del pacient: ' . $patient_info,
        null,        // TARGET_USER_ID: Ya no existe
        null         // TARGET_OBJECT_ID
    );
}

// ★★★ INICIO: IMPLEMENTACIÓN DE C5, C6, C7 y C8 (TRATAMIENTOS) ★★★

// [C5] CREACIÓN DE TRATAMIENTO
function registrar_tratamiento_creado($db, $actor_id, $actor_name, $treatment_id, $patient_id, $patient_name, $treatment_title) {
    registrar_log(
        $db,
        'TREATMENT_CREATED',
        $actor_id,
        $actor_name,
        "Nou tractament '{$treatment_title}' creat per a pacient {$patient_name}.",
        $patient_id,
        $treatment_id
    );
}

// [C6] MODIFICACIÓN DE TRATAMIENTO
function registrar_tratamiento_modificado($db, $actor_id, $actor_name, $treatment_id, $patient_id, $treatment_title) {
    registrar_log(
        $db,
        'TREATMENT_UPDATED',
        $actor_id,
        $actor_name,
        "Tractament '{$treatment_title}' modificat (exercicis, dates o pautes).",
        $patient_id,
        $treatment_id
    );
}

// [C7] ELIMINACIÓN DE TRATAMIENTO (CRÍTICO)
function registrar_tratamiento_eliminado($db, $actor_id, $actor_name, $treatment_id, $patient_id, $treatment_title) {
    registrar_log(
        $db,
        'TREATMENT_DELETED',
        $actor_id,
        $actor_name,
        "CRÍTIC: Eliminació permanent del tractament: '{$treatment_title}'.",
        $patient_id,
        $treatment_id
    );
}

// [C8] TRANSFERENCIA DE PROPIEDAD DE TRATAMIENTO
function registrar_tratamiento_transferido($db, $actor_id, $actor_name, $treatment_id, $patient_id, $new_fisio_id) {
    registrar_log(
        $db,
        'TREATMENT_TRANSFERRED',
        $actor_id,
        $actor_name,
        "CRÍTIC: Propietat del tractament ID {$treatment_id} transferida al Fisio ID {$new_fisio_id}.",
        $patient_id,
        $treatment_id
    );
}

// ★★★ FIN: IMPLEMENTACIÓN DE C5, C6, C7 y C8 ★★★


// =================================================================
// ★★★ GRUPO IV: FUNCIONES DE CHAT (C14 y C15) ★★★
// =================================================================

/**
 * [C14] Registra el envío de un mensaje de chat (Texto o Imagen).
 *
 * @param PDO $db Objeto de conexión a la BD.
 * @param int $from_id ID del usuario que envía el mensaje (actor).
 * @param string $from_name Nombre del usuario que envía.
 * @param int $to_id ID del usuario que recibe el mensaje (target).
 * @param string $message_preview Texto corto del mensaje o "[Imatge]".
 */
function registrar_mensaje_chat_enviado($db, $from_id, $from_name, $to_id, $to_name, $message_preview) {
    $details = "Missatge enviat a {$to_name}. Contingut: " . substr($message_preview, 0, 50) . '...';
    registrar_log(
        $db,
        'CHAT_MESSAGE_SENT',
        $from_id,
        $from_name,
        $details,
        $to_id
    );
}

/**
 * [C15] Registra el borrado/ocultación de un historial de conversación.
 *
 * @param PDO $db Objeto de conexión a la BD.
 * @param int $actor_id ID del usuario que borra/oculta (actor).
 * @param string $actor_name Nombre del usuario que borra/oculta.
 * @param int $other_user_id ID del otro usuario de la conversación (target).
 * @param string $mode 'self' (ocultar) o 'both' (borrado permanente).
 */
function registrar_conversacion_borrada($db, $actor_id, $actor_name, $other_user_id, $other_user_name, $mode) {
    $action_text = ($mode === 'both') ? 'BORRAT PERMANENT' : 'OCULTAT';
    $details = "Historial de xat amb {$other_user_name} ({$other_user_id}) marcat com a '{$action_text}'.";

    // target_user_id es el otro usuario de la conversación
    registrar_log(
        $db,
        'CHAT_CONV_CLEARED',
        $actor_id,
        $actor_name,
        $details,
        $other_user_id
    );
}
