<?php
declare(strict_types=1);
session_start();

// Por defecto servimos JSON para los endpoints AJAX.
// En acciones de formulario (registrar/editar) cambiamos a redirección.
header('Content-Type: application/json; charset=utf-8');

require_once '../services/pdo_connection.php';
require_once '../models/model_usuario.php';

/* ======================== Helpers ======================== */
function db(): PDO {
    static $db = null;
    if ($db === null) $db = (new Database())->getConnection();
    return $db;
}
function respond(array $payload): void {
    echo json_encode($payload);
    exit;
}
function require_login(): int {
    $uid = (int)($_SESSION['user_id'] ?? 0);
    if ($uid <= 0) respond(['success'=>false, 'message'=>'No autenticado']);
    return $uid;
}
function require_admin(): int {
    $uid = require_login();
    if ($uid !== 1) respond(['success'=>false, 'message'=>'No autorizado']);
    return $uid;
}
function fetch_user_row(int $id): ?array {
    $u = new Usuario();
    $u->setIdUsuario($id);
    $row = $u->leerUno(db())->fetch(PDO::FETCH_ASSOC);
    return $row ?: null;
}
function clean_phone(string $s): string {
    return preg_replace('/\D+/', '', $s) ?? '';
}
/** Redirige con mensajes de sesión (para formularios). */
function redirect_with_message(string $url, string $msg, string $type='error', array $form = []): never {
    // Cambiamos el header para respuesta HTML con redirección.
    header_remove('Content-Type');
    header('Content-Type: text/html; charset=utf-8');
    if ($form) $_SESSION['form_data'] = $form;
    $_SESSION['message'] = $msg;
    $_SESSION['message_type'] = $type;
    header("Location: $url");
    exit;
}

/* ======================== Router ========================= */
$action = $_POST['action'] ?? $_GET['action'] ?? '';

try {
    switch ($action) {

        /* ---------- Verificar contraseña del ADMIN (AJAX) ---------- */
        case 'verify_password': {
            require_admin();

            $password   = trim($_POST['password'] ?? '');
            $editUserId = (int)($_POST['edit_user_id'] ?? 0);

            if ($password === '') respond(['success'=>false,'message'=>'Contraseña requerida']);

            $row = fetch_user_row(1); // admin
            if (!$row || empty($row['hash_contrasena'])) {
                respond(['success'=>false,'message'=>'Admin no encontrado']);
            }

            if (!password_verify($password, $row['hash_contrasena'])) {
                respond(['success'=>false,'message'=>'Contraseña incorrecta']);
            }

            $_SESSION['admin_verified_at'] = time();
            respond(['success'=>true, 'edit_user_id'=>$editUserId]);
        }

        /* ----------------- Datos de un usuario (AJAX) --------------- */
        case 'get_user': {
            require_admin();
            $id = (int)($_GET['id'] ?? $_POST['id'] ?? 0);
            if ($id <= 0) respond(['success'=>false,'message'=>'ID inválido']);

            $row = fetch_user_row($id);
            if (!$row) respond(['success'=>false,'message'=>'Usuario no encontrado']);

            respond([
                'success'=>true,
                'user'=>[
                    'id'      => (int)$row['id_usuario'],
                    'nombre'  => $row['nombre_completo'],
                    'correo'  => $row['correo'],
                    'telefono'=> $row['telefono'],
                    'activo'  => (int)$row['activo'],
                ]
            ]);
        }

        /* ----------------- Actualizar un usuario (AJAX) ------------- */
        case 'update_user': {
            require_admin();
            $id = (int)($_POST['id'] ?? 0);
            if ($id <= 0) respond(['success'=>false,'message'=>'ID inválido']);
            if ($id === 1) respond(['success'=>false,'message'=>'Usa "update_profile" para el admin']);

            $correo    = trim($_POST['correo'] ?? '');
            $telefono  = trim($_POST['telefono'] ?? '');
            $nombre    = trim($_POST['nombre_completo'] ?? '');
            $activo    = isset($_POST['activo']) ? (int)!!$_POST['activo'] : 0;
            $newpass   = trim($_POST['new_password'] ?? '');

            // Validación mínima
            if ($correo === '' || $nombre === '') respond(['success'=>false,'message'=>'Nombre y correo son obligatorios']);

            // Unicidad de correo/teléfono (ignorando formato), excluyendo el propio
            $tNorm = clean_phone($telefono);
            $st = db()->prepare("
                SELECT 1 FROM usuario
                 WHERE (correo = :c
                    OR REPLACE(REPLACE(REPLACE(REPLACE(telefono,'-',''),' ',''),'(',''),')','') = :t)
                   AND id_usuario <> :id
                 LIMIT 1
            ");
            $st->execute([':c'=>$correo, ':t'=>$tNorm, ':id'=>$id]);
            if ($st->fetchColumn()) {
                respond(['success'=>false,'message'=>'Correo o teléfono ya usados por otro usuario']);
            }

            $u = new Usuario();
            $u->setIdUsuario($id);
            $u->setCorreo($correo);
            $u->setTelefono($telefono);            // guardamos como lo capturó
            $u->setNombreCompleto($nombre);
            $u->setActivo($activo);
            if ($newpass !== '') {
                $u->setHashContrasena(password_hash($newpass, PASSWORD_BCRYPT));
            }

            if ($u->actualizar(db())) {
                respond(['success'=>true,'message'=>'Usuario actualizado']);
            }
            respond(['success'=>false,'message'=>'No se pudo actualizar']);
        }

        /* --------------- Activar / Desactivar (AJAX) ---------------- */
        case 'toggle_status': {
            require_admin();
            $id  = (int)($_POST['id'] ?? 0);
            $to  = strtolower((string)($_POST['to'] ?? ''));
            if ($id <= 0) respond(['success'=>false,'message'=>'ID inválido']);
            if ($id === 1) respond(['success'=>false,'message'=>'No puedes desactivar al administrador']);

            $val = ($to === 'activar') ? 1 : (($to === 'desactivar') ? 0 : null);
            if ($val === null) respond(['success'=>false,'message'=>'Parámetro "to" inválido']);

            $st = db()->prepare('UPDATE usuario SET activo = :a WHERE id_usuario = :id');
            $st->execute([':a'=>$val, ':id'=>$id]);

            respond(['success'=>true,'message'=> $val ? 'Usuario activado' : 'Usuario desactivado']);
        }

        /* ---- Alias para compatibilidad con tu JS actual (AJAX) ----- */
        case 'activar_usuario': {
            $_POST['to'] = 'activar';
            $_POST['action'] = 'toggle_status';
            // Re-entramos en el switch con la acción canon
            // (pequeño truco para no duplicar lógica)
            // Nota: en PHP no es tail-call, así que hacemos include lógico:
            // volvemos a evaluar el case 'toggle_status'
            // => copiamos la lógica directamente:
            require_admin();
            $id  = (int)($_POST['id'] ?? 0);
            if ($id <= 0) respond(['success'=>false,'message'=>'ID inválido']);
            if ($id === 1) respond(['success'=>false,'message'=>'No puedes desactivar al administrador']);
            $st = db()->prepare('UPDATE usuario SET activo = 1 WHERE id_usuario = :id');
            $st->execute([':id'=>$id]);
            respond(['success'=>true,'message'=>'Usuario activado']);
        }
        case 'desactivar_usuario': {
            require_admin();
            $id  = (int)($_POST['id'] ?? 0);
            if ($id <= 0) respond(['success'=>false,'message'=>'ID inválido']);
            if ($id === 1) respond(['success'=>false,'message'=>'No puedes desactivar al administrador']);
            $st = db()->prepare('UPDATE usuario SET activo = 0 WHERE id_usuario = :id');
            $st->execute([':id'=>$id]);
            respond(['success'=>true,'message'=>'Usuario desactivado']);
        }

        /* ------------------- Eliminar usuario (AJAX) ---------------- */
        case 'delete_user': {
            require_admin();
            $id = (int)($_POST['id'] ?? 0);
            if ($id <= 0) respond(['success'=>false,'message'=>'ID inválido']);
            if ($id === 1) respond(['success'=>false,'message'=>'No puedes eliminar al administrador']);
            if ($id === (int)($_SESSION['user_id'])) respond(['success'=>false,'message'=>'No puedes eliminarte a ti mismo']);

            $st = db()->prepare('DELETE FROM usuario WHERE id_usuario = :id');
            $st->execute([':id'=>$id]);

            respond(['success'=>true,'message'=>'Usuario eliminado']);
        }

        /* --------------- Actualizar perfil del admin (AJAX) ---------- */
        case 'update_profile': {
            $uid = require_admin();
            $correo   = trim($_POST['correo'] ?? '');
            $telefono = trim($_POST['telefono'] ?? '');
            $nombre   = trim($_POST['nombre_completo'] ?? '');
            $newpass  = trim($_POST['new_password'] ?? '');

            if ($correo === '' || $nombre === '') respond(['success'=>false,'message'=>'Nombre y correo son obligatorios']);

            // Unicidad vs otros usuarios
            $tNorm = clean_phone($telefono);
            $st = db()->prepare("
                SELECT 1 FROM usuario
                 WHERE (correo = :c
                    OR REPLACE(REPLACE(REPLACE(REPLACE(telefono,'-',''),' ',''),'(',''),')','') = :t)
                   AND id_usuario <> :id
                 LIMIT 1
            ");
            $st->execute([':c'=>$correo, ':t'=>$tNorm, ':id'=>$uid]);
            if ($st->fetchColumn()) {
                respond(['success'=>false,'message'=>'Correo o teléfono ya usados por otro usuario']);
            }

            $u = new Usuario();
            $u->setIdUsuario($uid);
            $u->setCorreo($correo);
            $u->setTelefono($telefono);
            $u->setNombreCompleto($nombre);
            $u->setActivo(1);
            if ($newpass !== '') {
                $u->setHashContrasena(password_hash($newpass, PASSWORD_BCRYPT));
            }

            if ($u->actualizar(db())) {
                respond(['success'=>true,'message'=>'Perfil actualizado']);
            }
            respond(['success'=>false,'message'=>'No se pudo actualizar el perfil']);
        }

        /* ================== FORM: Registro =================== */
        case 'registrar': {
            // Datos desde formulario de registro.php
            $nombre   = trim($_POST['nombre_completo'] ?? '');
            $correo   = trim($_POST['correo'] ?? '');
            $tel_in   = trim($_POST['telefono'] ?? '');
            $pass     = $_POST['contrasena'] ?? '';
            $pass2    = $_POST['confirm_contrasena'] ?? '';

            if ($nombre === '' || $correo === '' || $tel_in === '' || $pass === '' || $pass2 === '') {
                redirect_with_message('../views/registro.php', 'Completa todos los campos.', 'error', $_POST);
            }
            if (!filter_var($correo, FILTER_VALIDATE_EMAIL)) {
                redirect_with_message('../views/registro.php', 'Correo no válido.', 'error', $_POST);
            }
            if ($pass !== $pass2) {
                redirect_with_message('../views/registro.php', 'Las contraseñas no coinciden.', 'error', $_POST);
            }

            // Validar duplicados ignorando formato de teléfono
            $tNorm = clean_phone($tel_in);
            $st = db()->prepare("
                SELECT 1 FROM usuario
                 WHERE correo = :c
                    OR REPLACE(REPLACE(REPLACE(REPLACE(telefono,'-',''),' ',''),'(',''),')','') = :t
                 LIMIT 1
            ");
            $st->execute([':c'=>$correo, ':t'=>$tNorm]);
            if ($st->fetchColumn()) {
                redirect_with_message('../views/registro.php', 'Correo o teléfono ya registrados.', 'error', $_POST);
            }

            $u = new Usuario();
            $u->setCorreo($correo);
            $u->setTelefono($tel_in); // guarda tal cual lo capturó (pero validamos ignorando formato)
            $u->setHashContrasena(password_hash($pass, PASSWORD_BCRYPT));
            $u->setNombreCompleto($nombre);
            $u->setActivo(0); // << Queda PENDIENTE hasta que el admin lo active

            if (!$u->guardar(db())) {
                redirect_with_message('../views/registro.php', 'No se pudo guardar la solicitud.', 'error', $_POST);
            }

            $_SESSION['welcome_message'] = '¡Solicitud enviada! El administrador revisará tu alta.';
            redirect_with_message('../views/login.php', 'Solicitud registrada.', 'ok');
        }

        /* ================== FORM: Editar ===================== */
        case 'editar': {
            // Solo el admin edita a otros desde registro.php?id=...
            if ((int)($_SESSION['user_id'] ?? 0) !== 1) {
                redirect_with_message('../views/login.php', 'No autorizado.', 'error');
            }

            $id       = (int)($_POST['id_usuario'] ?? 0);
            $nombre   = trim($_POST['nombre_completo'] ?? '');
            $correo   = trim($_POST['correo'] ?? '');
            $tel_in   = trim($_POST['telefono'] ?? '');
            $activo   = isset($_POST['activo']) ? (int)$_POST['activo'] : 0;
            $pass     = $_POST['contrasena'] ?? '';
            $pass2    = $_POST['confirm_contrasena'] ?? '';

            if ($id <= 0) redirect_with_message('../views/perfil.php', 'ID inválido.', 'error');
            if ($nombre === '' || $correo === '' || $tel_in === '') {
                redirect_with_message("../views/registro.php?id=$id", 'Completa nombre, correo y teléfono.', 'error', $_POST);
            }
            if (!filter_var($correo, FILTER_VALIDATE_EMAIL)) {
                redirect_with_message("../views/registro.php?id=$id", 'Correo no válido.', 'error', $_POST);
            }
            if ($pass !== '' && $pass !== $pass2) {
                redirect_with_message("../views/registro.php?id=$id", 'Las contraseñas no coinciden.', 'error', $_POST);
            }

            // Unicidad (excluyendo al propio)
            $tNorm = clean_phone($tel_in);
            $st = db()->prepare("
                SELECT 1 FROM usuario
                 WHERE (correo = :c
                    OR REPLACE(REPLACE(REPLACE(REPLACE(telefono,'-',''),' ',''),'(',''),')','') = :t)
                   AND id_usuario <> :id
                 LIMIT 1
            ");
            $st->execute([':c'=>$correo, ':t'=>$tNorm, ':id'=>$id]);
            if ($st->fetchColumn()) {
                redirect_with_message("../views/registro.php?id=$id", 'Correo o teléfono ya usados por otro usuario.', 'error', $_POST);
            }

            $u = new Usuario();
            $u->setIdUsuario($id);
            $u->setCorreo($correo);
            $u->setTelefono($tel_in);
            $u->setNombreCompleto($nombre);
            $u->setActivo($activo);
            if ($pass !== '') {
                $u->setHashContrasena(password_hash($pass, PASSWORD_BCRYPT));
            }

            if (!$u->actualizar(db())) {
                redirect_with_message("../views/registro.php?id=$id", 'No se pudieron guardar los cambios.', 'error', $_POST);
            }

            $_SESSION['message'] = 'Usuario actualizado.';
            $_SESSION['message_type'] = 'ok';
            redirect_with_message('../views/perfil.php', 'Usuario actualizado.', 'ok');
        }

        /* ------------------- Acción no soportada ------------- */
        default:
            respond(['success'=>false,'message'=>'Acción desconocida']);
    }

} catch (PDOException $e) {
    // Duplicados (correo/teléfono) u otros errores SQL
    if (in_array($action, ['registrar','editar'], true)) {
        $target = ($action === 'registrar') ? '../views/registro.php' : '../views/perfil.php';
        $msg = ($e->getCode() === '23000')
             ? 'Correo o teléfono ya existen.'
             : 'Error de base de datos.';
        redirect_with_message($target, $msg, 'error', $_POST);
    } else {
        if ($e->getCode() === '23000') {
            respond(['success'=>false,'message'=>'Correo o teléfono ya existe']);
        }
        respond(['success'=>false,'message'=>'Error de base de datos']);
    }
} catch (Throwable $e) {
    if (in_array($action, ['registrar','editar'], true)) {
        redirect_with_message('../views/login.php', 'Error del servidor.', 'error');
    } else {
        respond(['success'=>false,'message'=>'Error del servidor']);
    }
}
