<?php
declare(strict_types=1);

function json_response(array $payload, int $status = 200): never {
  http_response_code($status);
  header("Content-Type: application/json; charset=utf-8");
  header("Cache-Control: no-store, no-cache, must-revalidate, max-age=0");
  echo json_encode($payload, JSON_UNESCAPED_UNICODE);
  exit;
}

function read_json_body(): array {
  $raw = file_get_contents("php://input") ?: "";
  $data = json_decode($raw, true);
  return is_array($data) ? $data : ($_POST ?: []);
}

function read_input(): array {
  return read_json_body();
}


function normalize_rut(string $rut): string {
  $rut = strtoupper(trim($rut));
  $rut = str_replace([".", "-", " "], "", $rut);
  return $rut;
}


function fp_normalize_text(string $value): string {
  $value = trim($value);
  $value = preg_replace('/\s+/u', ' ', $value) ?? $value;
  return $value;
}

function fp_parse_excel_date_or_null($value): ?string {
  if ($value === null) return null;
  $raw = trim((string)$value);
  if ($raw === '') return null;

  if (preg_match('/^\d{8}$/', $raw) === 1) {
    $yyyy = substr($raw, 0, 4);
    $mm   = substr($raw, 4, 2);
    $dd   = substr($raw, 6, 2);
    if (checkdate((int)$mm, (int)$dd, (int)$yyyy)) {
      return sprintf('%04d-%02d-%02d', (int)$yyyy, (int)$mm, (int)$dd);
    }
  }

  if (preg_match('/^\d{4}-\d{2}-\d{2}$/', $raw) === 1) {
    return $raw;
  }

  return null;
}

function fp_parse_diagnosticos_cronicos(?string $detalle): array {
  $detalle = fp_normalize_text((string)($detalle ?? ''));
  if ($detalle === '') return [];

  $items = preg_split('/\s*\|\s*/u', $detalle) ?: [];
  $out = [];

  foreach ($items as $idx => $item) {
    $item = trim($item);
    if ($item === '') continue;

    $fecha = null;
    $codigo = null;
    $nombre = $item;

    if (preg_match('/^(?:(\d{8})\s*)?\[([^\]]+)\]\s*-\s*(.+)$/u', $item, $m) === 1) {
      $fecha = fp_parse_excel_date_or_null($m[1] ?? null);
      $codigo = fp_normalize_text((string)($m[2] ?? ''));
      $nombre = fp_normalize_text((string)($m[3] ?? ''));
    } elseif (preg_match('/^(?:(\d{8})\s+)?(.+)$/u', $item, $m) === 1) {
      $fecha = fp_parse_excel_date_or_null($m[1] ?? null);
      $nombre = fp_normalize_text((string)($m[2] ?? $item));
    }

    $out[] = [
      'fecha_diagnostico' => $fecha,
      'codigo_diagnostico' => $codigo ?: null,
      'nombre_diagnostico' => $nombre,
      'diagnostico_completo' => $item,
      'orden_diagnostico' => $idx + 1,
    ];
  }

  return $out;
}

function fp_sync_usuario_diagnosticos(PDO $pdo, string $rut, ?string $detalle): void {
  $rut = normalize_rut($rut);
  if ($rut === '') return;

  $pdo->prepare("DELETE FROM usuario_diagnosticos_cronicos WHERE usuario_rut = ?")->execute([$rut]);

  $diagnosticos = fp_parse_diagnosticos_cronicos($detalle);
  if (!$diagnosticos) return;

  $sql = "INSERT INTO usuario_diagnosticos_cronicos (
            usuario_rut,
            orden_diagnostico,
            fecha_diagnostico,
            codigo_diagnostico,
            nombre_diagnostico,
            diagnostico_completo
          ) VALUES (
            :usuario_rut,
            :orden_diagnostico,
            :fecha_diagnostico,
            :codigo_diagnostico,
            :nombre_diagnostico,
            :diagnostico_completo
          )";
  $st = $pdo->prepare($sql);

  foreach ($diagnosticos as $diag) {
    $st->execute([
      ':usuario_rut' => $rut,
      ':orden_diagnostico' => (int)($diag['orden_diagnostico'] ?? 0),
      ':fecha_diagnostico' => $diag['fecha_diagnostico'] ?? null,
      ':codigo_diagnostico' => $diag['codigo_diagnostico'] ?? null,
      ':nombre_diagnostico' => $diag['nombre_diagnostico'] ?? null,
      ':diagnostico_completo' => $diag['diagnostico_completo'] ?? null,
    ]);
  }
}



function fp_column_exists(PDO $pdo, string $table, string $column): bool {
  try {
    $st = $pdo->prepare("SHOW COLUMNS FROM `$table` LIKE ?");
    $st->execute([$column]);
    return (bool)$st->fetch(PDO::FETCH_ASSOC);
  } catch (Throwable $e) {
    return false;
  }
}

function fp_ensure_percapita_columns(PDO $pdo): void {
  static $done = false;
  if ($done) return;
  $done = true;

  try {
    if (!fp_column_exists($pdo, 'usuarios', 'percapitado')) {
      $pdo->exec("ALTER TABLE `usuarios` ADD COLUMN `percapitado` TINYINT(1) NOT NULL DEFAULT 1 AFTER `inscrito_cesfam`");
    }
    if (!fp_column_exists($pdo, 'usuarios', 'fecha_actualizacion_percapita')) {
      $pdo->exec("ALTER TABLE `usuarios` ADD COLUMN `fecha_actualizacion_percapita` DATE DEFAULT NULL AFTER `percapitado`");
    }
  } catch (Throwable $e) {
    error_log('FP ENSURE PERCAPITA COLUMNS ERROR: ' . $e->getMessage());
  }
}

function fp_normalize_run_key(string $rut): string {
  $rut = strtoupper(trim($rut));
  $rut = preg_replace('/\.0+$/', '', $rut) ?? $rut;
  $rut = preg_replace('/[^0-9K]/', '', $rut) ?? '';
  $rut = substr($rut, 0, 15);

  // Normaliza formato chileno cuerpo+DV quitando ceros a la izquierda del cuerpo.
  // Ejemplo: 00114352810, 11.435.281-0 y 114352810 quedan en la misma llave.
  if (strlen($rut) > 1) {
    $body = substr($rut, 0, -1);
    $dv = substr($rut, -1);
    $body = ltrim($body, '0');
    if ($body === '') $body = '0';
    return $body . $dv;
  }

  return $rut;
}

function fp_sql_normalized_rut_expr(string $column = 'rut'): string {
  $clean = "UPPER(REPLACE(REPLACE(REPLACE(CAST($column AS CHAR), '.', ''), '-', ''), ' ', ''))";
  $body = "TRIM(LEADING '0' FROM SUBSTRING($clean, 1, CHAR_LENGTH($clean) - 1))";
  return "CASE WHEN CHAR_LENGTH($clean) > 1 THEN CONCAT(CASE WHEN $body = '' THEN '0' ELSE $body END, RIGHT($clean, 1)) ELSE $clean END";
}

function fp_bool_filter_sql(string $column, string $value, array &$where, array &$params, string $paramName): void {
  $value = trim($value);
  if ($value === '1' || $value === '0') {
    $where[] = "$column = :$paramName";
    $params[":$paramName"] = (int)$value;
  }
}

function start_fp_session(): void {
  if (session_status() === PHP_SESSION_ACTIVE) return;

  $secure = (!empty($_SERVER["HTTPS"]) && $_SERVER["HTTPS"] !== "off");
  session_set_cookie_params([
    "lifetime" => 0,
    "path"     => "/",
    "secure"   => $secure,
    "httponly" => true,
    "samesite" => "Lax",
  ]);
  session_start();
}


function fp_ensure_actividad_reciente_table(PDO $pdo): void {
  static $done = false;
  if ($done) return;
  $done = true;

  try {
    $pdo->exec("CREATE TABLE IF NOT EXISTS `actividad_reciente` (
      `id` BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT,
      `funcionario_rut` VARCHAR(15) DEFAULT NULL,
      `funcionario_nombre` VARCHAR(180) DEFAULT NULL,
      `rol_funcionario` VARCHAR(50) DEFAULT NULL,
      `modulo` VARCHAR(80) NOT NULL,
      `accion` VARCHAR(80) NOT NULL,
      `descripcion` VARCHAR(255) NOT NULL,
      `entidad_tipo` VARCHAR(80) DEFAULT NULL,
      `entidad_id` VARCHAR(80) DEFAULT NULL,
      `ip` VARCHAR(45) DEFAULT NULL,
      `user_agent` VARCHAR(255) DEFAULT NULL,
      `fecha_registro` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
      PRIMARY KEY (`id`),
      KEY `idx_actividad_funcionario_fecha` (`funcionario_rut`, `fecha_registro`),
      KEY `idx_actividad_fecha` (`fecha_registro`),
      KEY `idx_actividad_modulo` (`modulo`)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci");
  } catch (Throwable $e) {
    error_log('FP ENSURE ACTIVIDAD TABLE ERROR: ' . $e->getMessage());
  }
}

function fp_user_display_name(PDO $pdo, ?array $u): ?string {
  $name = trim((string)($u['nombre'] ?? $u['nombre_funcionario'] ?? ''));
  if ($name !== '') return mb_substr($name, 0, 180, 'UTF-8');

  $rut = normalize_rut((string)($u['rut'] ?? $u['rut_funcionario'] ?? ''));
  if ($rut === '') return null;

  try {
    $st = $pdo->prepare("SELECT TRIM(CONCAT(COALESCE(nombre,''), ' ', COALESCE(apellido_paterno,''), ' ', COALESCE(apellido_materno,''))) AS nombre_completo FROM funcionario WHERE rut = ? LIMIT 1");
    $st->execute([$rut]);
    $found = trim((string)$st->fetchColumn());
    return $found !== '' ? mb_substr($found, 0, 180, 'UTF-8') : null;
  } catch (Throwable $e) {
    return null;
  }
}

function fp_log_activity(PDO $pdo, ?array $u, string $modulo, string $accion, string $descripcion, ?string $entidadTipo = null, ?string $entidadId = null): void {
  try {
    fp_ensure_actividad_reciente_table($pdo);

    $rut = normalize_rut((string)($u['rut'] ?? $u['rut_funcionario'] ?? ''));
    $rol = strtolower(trim((string)($u['rol'] ?? $u['rol_funcionario'] ?? '')));
    $nombre = fp_user_display_name($pdo, $u);

    $ip = trim((string)($_SERVER['REMOTE_ADDR'] ?? ''));
    $ua = trim((string)($_SERVER['HTTP_USER_AGENT'] ?? ''));

    $st = $pdo->prepare("INSERT INTO actividad_reciente (
      funcionario_rut, funcionario_nombre, rol_funcionario, modulo, accion, descripcion, entidad_tipo, entidad_id, ip, user_agent
    ) VALUES (
      :funcionario_rut, :funcionario_nombre, :rol_funcionario, :modulo, :accion, :descripcion, :entidad_tipo, :entidad_id, :ip, :user_agent
    )");

    $st->execute([
      ':funcionario_rut' => $rut !== '' ? $rut : null,
      ':funcionario_nombre' => $nombre,
      ':rol_funcionario' => $rol !== '' ? mb_substr($rol, 0, 50, 'UTF-8') : null,
      ':modulo' => mb_substr(trim($modulo), 0, 80, 'UTF-8'),
      ':accion' => mb_substr(trim($accion), 0, 80, 'UTF-8'),
      ':descripcion' => mb_substr(trim($descripcion), 0, 255, 'UTF-8'),
      ':entidad_tipo' => $entidadTipo !== null ? mb_substr(trim($entidadTipo), 0, 80, 'UTF-8') : null,
      ':entidad_id' => $entidadId !== null ? mb_substr(trim($entidadId), 0, 80, 'UTF-8') : null,
      ':ip' => $ip !== '' ? mb_substr($ip, 0, 45, 'UTF-8') : null,
      ':user_agent' => $ua !== '' ? mb_substr($ua, 0, 255, 'UTF-8') : null,
    ]);
  } catch (Throwable $e) {
    // Nunca romper una operación principal por un problema en la bitácora.
    error_log('FP LOG ACTIVITY ERROR: ' . $e->getMessage());
  }
}
