<?php
// php/auth/guard.php
declare(strict_types=1);

require_once __DIR__ . '/../_helpers.php';

if (session_status() !== PHP_SESSION_ACTIVE) {
  session_start();
}

function is_local_env(): bool {
  $serverName = $_SERVER['SERVER_NAME'] ?? '';
  $serverAddr = $_SERVER['SERVER_ADDR'] ?? '';
  $remoteAddr = $_SERVER['REMOTE_ADDR'] ?? '';

  if (!function_exists('str_contains')) {
    function str_contains($haystack, $needle) {
      return $needle !== '' && strpos($haystack, $needle) !== false;
    }
  }

  return
    in_array($serverName, ['localhost', '127.0.0.1'], true)
    || str_contains($serverName, '.local')
    || in_array($serverAddr, ['127.0.0.1', '::1'], true)
    || in_array($remoteAddr, ['127.0.0.1', '::1'], true);
}

function normalize_role(string $rol): string {
  $rol = strtolower(trim($rol));
  $rol = str_replace(['_', ' '], '-', $rol);

  // Roles oficiales del sistema
  if (in_array($rol, ['admin', 'administrador'], true)) return 'administrador';
  if (in_array($rol, ['digitador'], true)) return 'digitador';
  if (in_array($rol, ['digitador-terreno', 'terreno'], true)) return 'digitador-terreno';
  if (in_array($rol, ['monitor', 'lectura', 'solo-lectura', 'readonly', 'read-only'], true)) return 'monitor';

  // Compatibilidad con roles antiguos.
  if ($rol === 'supervisor') return 'digitador';

  // Por seguridad, cualquier rol antiguo/desconocido queda como digitador.
  return 'digitador';
}

function normalize_user(array $u): array {
  // Unifica claves típicas
  if (!isset($u['rut']) && isset($u['rut_funcionario'])) $u['rut'] = $u['rut_funcionario'];
  if (!isset($u['rol']) && isset($u['rol_funcionario'])) $u['rol'] = $u['rol_funcionario'];

  // Normaliza rut (sin puntos/guión/espacios)
  if (isset($u['rut'])) $u['rut'] = normalize_rut((string)$u['rut']);

  // Normaliza rol a los roles oficiales vigentes.
  $u['rol'] = normalize_role((string)($u['rol'] ?? 'digitador'));

  return $u;
}

function current_user(): ?array {
  // 1) Sesión (ideal)
  if (!empty($_SESSION['fp_user']) && is_array($_SESSION['fp_user'])) {
    return normalize_user($_SESSION['fp_user']);
  }
  if (!empty($_SESSION['user']) && is_array($_SESSION['user'])) {
    return normalize_user($_SESSION['user']);
  }

  // 2) Fallback DEV: headers desde frontend (solo local)
  if (is_local_env()) {
    $rut = $_SERVER['HTTP_X_FP_RUT'] ?? '';
    $rol = $_SERVER['HTTP_X_FP_ROL'] ?? '';
    $rut = $rut ? normalize_rut($rut) : '';
    if ($rut) return normalize_user(['rut' => $rut, 'rol' => ($rol ?: null)]);
  }

  return null;
}

function require_login(): array {
  $u = current_user();
  if (!$u) {
    json_response(["ok" => false, "message" => "No autenticado."], 401);
  }
  return $u;
}

function fp_role_label(string $rol): string {
  $rol = normalize_role($rol);
  if ($rol === 'administrador') return 'administrador';
  if ($rol === 'digitador-terreno') return 'digitador-terreno';
  if ($rol === 'monitor') return 'monitor';
  return 'digitador';
}

function fp_module_key(string $moduleName): string {
  $m = strtolower(trim($moduleName));
  $m = str_replace(
    ['á','é','í','ó','ú','ñ','Á','É','Í','Ó','Ú','Ñ',' ', '_'],
    ['a','e','i','o','u','n','a','e','i','o','u','n','-', '-'],
    $m
  );
  $m = preg_replace('/[^a-z0-9-]/', '', $m) ?? $m;

  if (in_array($m, ['persona', 'personas', 'usuario', 'usuarios'], true)) return 'usuarios';
  if (in_array($m, ['busqueda', 'buscar'], true)) return 'busqueda';
  if (in_array($m, ['instrumento', 'instrumentos'], true)) return 'instrumentos';
  if (in_array($m, ['familia', 'familias'], true)) return 'familias';
  if (in_array($m, ['vivienda', 'viviendas'], true)) return 'vivienda';
  if (in_array($m, ['reporte', 'reportes'], true)) return 'reportes';
  if (in_array($m, ['geolocalizacion', 'geo'], true)) return 'geolocalizacion';
  if (in_array($m, ['geolocalizacion-comunitaria', 'geolocalizacioncomunitaria', 'geo-comunitaria', 'geocomunitaria', 'comunitaria'], true)) return 'geolocalizacion-comunitaria';
  if (in_array($m, ['config', 'configuracion'], true)) return 'configuracion';

  return $m;
}

function fp_allowed_modules_for_role(string $rol): array {
  $rol = normalize_role($rol);

  $all = [
    'dashboard',
    'busqueda',
    'instrumentos',
    'familias',
    'vivienda',
    'usuarios',
    'reportes',
    'geolocalizacion',
    'geolocalizacion-comunitaria',
    'configuracion',
  ];

  if ($rol === 'administrador') return $all;

  // Rol existente: mantiene sus permisos originales y se suma Familias.
  if ($rol === 'digitador') return ['dashboard', 'usuarios', 'familias', 'reportes', 'geolocalizacion', 'geolocalizacion-comunitaria'];

  // Rol nuevo para terreno: sin Personas ni Configuración.
  if ($rol === 'digitador-terreno') return ['dashboard', 'busqueda', 'instrumentos', 'familias', 'vivienda', 'reportes', 'geolocalizacion', 'geolocalizacion-comunitaria'];

  // Rol nuevo monitor: todo menos Configuración, pero solo lectura.
  if ($rol === 'monitor') return ['dashboard', 'busqueda', 'instrumentos', 'familias', 'vivienda', 'usuarios', 'reportes', 'geolocalizacion', 'geolocalizacion-comunitaria'];

  return ['dashboard'];
}

function fp_user_role(array $u): string {
  return normalize_role((string)($u['rol'] ?? $u['rol_funcionario'] ?? ''));
}

function fp_can_access_module(array $u, string $moduleName): bool {
  $module = fp_module_key($moduleName);
  $rol = fp_user_role($u);
  return in_array($module, fp_allowed_modules_for_role($rol), true);
}

function require_module_access(array $u, string $moduleName): void {
  if (!fp_can_access_module($u, $moduleName)) {
    json_response([
      "ok" => false,
      "message" => "No autorizado. Tu rol no tiene acceso al módulo " . $moduleName . "."
    ], 403);
  }
}

function is_admin_user(array $u): bool {
  return fp_user_role($u) === 'administrador';
}

function is_monitor_user(array $u): bool {
  return fp_user_role($u) === 'monitor';
}

function require_admin(array $u): void {
  if (!is_admin_user($u)) {
    json_response(["ok" => false, "message" => "No autorizado. Solo administrador puede acceder a configuración."], 403);
  }
}

function require_module_write(array $u, string $moduleName): void {
  require_module_access($u, $moduleName);

  if (is_monitor_user($u)) {
    json_response([
      "ok" => false,
      "message" => "No autorizado. El rol monitor es solo lectura: puede buscar, filtrar, visualizar e imprimir, pero no puede crear, modificar ni eliminar datos."
    ], 403);
  }
}

// Compatibilidad con endpoints antiguos: antes exigía administrador para algunos módulos.
// Ahora valida el acceso por rol al módulo.
function require_admin_module(array $u, string $moduleName = 'este módulo'): void {
  require_module_access($u, $moduleName);
}
