<?php
// php/geolocalizacion_comunitaria/save.php
declare(strict_types=1);
require_once __DIR__ . '/_bootstrap.php';

$u = gcomm_user();
gcomm_require_write($u);

try {
  gcomm_ensure_tables($pdo);

  $in = read_json_body();
  $id = gcomm_int_or_null($in['id'] ?? null);
  $tipo = gcomm_type((string)($in['tipo'] ?? 'activo'));
  $categoriaId = gcomm_int_or_null($in['categoria_id'] ?? null);
  $nombre = gcomm_null($in['nombre'] ?? null);
  $rutPersona = normalize_rut((string)($in['rut_persona'] ?? ''));
  $rutPersona = $rutPersona !== '' ? $rutPersona : null;
  $contactoNombre = gcomm_null($in['contacto_nombre'] ?? null);
  $telefono = gcomm_null($in['telefono'] ?? null);
  $correo = gcomm_null($in['correo'] ?? null);
  $direccion = gcomm_null($in['direccion'] ?? null);
  $sectorizacion = gcomm_int_or_null($in['sectorizacion'] ?? null);
  $sector = gcomm_int_or_null($in['sector'] ?? null);
  $descripcion = gcomm_null($in['descripcion'] ?? null);
  $observaciones = gcomm_null($in['observaciones'] ?? null);
  $latitud = gcomm_float_or_null($in['latitud'] ?? null);
  $longitud = gcomm_float_or_null($in['longitud'] ?? null);
  $estado = gcomm_estado((string)($in['estado'] ?? 'activo'));
  $syncPersona = gcomm_bool($in['sync_persona'] ?? true, true);
  $registradoPor = gcomm_current_rut($u);

  gcomm_validate_lat_lng($latitud, $longitud);

  if ($nombre === null) {
    json_response(['ok' => false, 'message' => 'El nombre del activo o agente comunitario es obligatorio.'], 400);
  }

  if ($tipo === 'agente' && $rutPersona === null && $contactoNombre === null) {
    json_response(['ok' => false, 'message' => 'Para un agente comunitario debes vincular una persona por RUT o escribir un nombre de contacto.'], 400);
  }

  if ($categoriaId !== null) {
    $st = $pdo->prepare("SELECT tipo FROM geo_comunitaria_categorias WHERE id = ? AND activo = 1 LIMIT 1");
    $st->execute([$categoriaId]);
    $catTipo = $st->fetchColumn();
    if (!$catTipo) {
      json_response(['ok' => false, 'message' => 'La categoría seleccionada no existe.'], 409);
    }
    if ($catTipo !== $tipo) {
      json_response(['ok' => false, 'message' => 'La categoría seleccionada no corresponde al tipo elegido.'], 409);
    }
  }

  if ($rutPersona !== null) {
    $st = $pdo->prepare("SELECT rut, nombres, apellidos, celular, telefonos, direccion, sector, sectorizacion FROM usuarios WHERE rut = ? LIMIT 1");
    $st->execute([$rutPersona]);
    $persona = $st->fetch(PDO::FETCH_ASSOC);
    if (!$persona) {
      json_response(['ok' => false, 'message' => 'El RUT vinculado no existe en la base de personas.'], 409);
    }
    if ($contactoNombre === null) $contactoNombre = gcomm_person_display($persona);
    if ($telefono === null) $telefono = gcomm_null($persona['celular'] ?? null) ?? gcomm_null($persona['telefonos'] ?? null);
    if ($direccion === null) $direccion = gcomm_null($persona['direccion'] ?? null);
    if ($sector === null) $sector = gcomm_int_or_null($persona['sector'] ?? null);
    if ($sectorizacion === null) $sectorizacion = gcomm_int_or_null($persona['sectorizacion'] ?? null);
  }

  if ($sectorizacion !== null) {
    $st = $pdo->prepare("SELECT 1 FROM sectorizacion WHERE id = ? LIMIT 1");
    $st->execute([$sectorizacion]);
    if (!$st->fetchColumn()) json_response(['ok' => false, 'message' => 'La sectorización no existe.'], 409);
  }
  if ($sector !== null) {
    $st = $pdo->prepare("SELECT 1 FROM sectores WHERE id = ? LIMIT 1");
    $st->execute([$sector]);
    if (!$st->fetchColumn()) json_response(['ok' => false, 'message' => 'El sector no existe.'], 409);
  }
  if ($registradoPor !== null) {
    $st = $pdo->prepare("SELECT 1 FROM funcionario WHERE rut = ? LIMIT 1");
    $st->execute([$registradoPor]);
    if (!$st->fetchColumn()) $registradoPor = null;
  }

  $payload = [
    ':tipo' => $tipo,
    ':categoria_id' => $categoriaId,
    ':nombre' => mb_substr($nombre, 0, 180, 'UTF-8'),
    ':rut_persona' => $rutPersona,
    ':contacto_nombre' => $contactoNombre !== null ? mb_substr($contactoNombre, 0, 180, 'UTF-8') : null,
    ':telefono' => $telefono !== null ? mb_substr($telefono, 0, 60, 'UTF-8') : null,
    ':correo' => $correo !== null ? mb_substr($correo, 0, 140, 'UTF-8') : null,
    ':direccion' => $direccion,
    ':sectorizacion' => $sectorizacion,
    ':sector' => $sector,
    ':descripcion' => $descripcion,
    ':observaciones' => $observaciones,
    ':latitud' => $latitud,
    ':longitud' => $longitud,
    ':estado' => $estado,
    ':registrado_por' => $registradoPor,
  ];

  $esNuevo = ($id === null);

  $pdo->beginTransaction();

  if ($id !== null) {
    $exists = $pdo->prepare("SELECT id FROM geo_comunitaria_puntos WHERE id = ? LIMIT 1");
    $exists->execute([$id]);
    if (!$exists->fetchColumn()) {
      $pdo->rollBack();
      json_response(['ok' => false, 'message' => 'El punto comunitario no existe.'], 404);
    }

    $payload[':id'] = $id;
    $sql = "UPDATE geo_comunitaria_puntos SET
      tipo = :tipo,
      categoria_id = :categoria_id,
      nombre = :nombre,
      rut_persona = :rut_persona,
      contacto_nombre = :contacto_nombre,
      telefono = :telefono,
      correo = :correo,
      direccion = :direccion,
      sectorizacion = :sectorizacion,
      sector = :sector,
      descripcion = :descripcion,
      observaciones = :observaciones,
      latitud = :latitud,
      longitud = :longitud,
      estado = :estado,
      registrado_por = :registrado_por
      WHERE id = :id";
    $pdo->prepare($sql)->execute($payload);
  } else {
    $sql = "INSERT INTO geo_comunitaria_puntos (
        tipo, categoria_id, nombre, rut_persona, contacto_nombre, telefono, correo, direccion,
        sectorizacion, sector, descripcion, observaciones, latitud, longitud, estado, registrado_por
      ) VALUES (
        :tipo, :categoria_id, :nombre, :rut_persona, :contacto_nombre, :telefono, :correo, :direccion,
        :sectorizacion, :sector, :descripcion, :observaciones, :latitud, :longitud, :estado, :registrado_por
      )";
    $pdo->prepare($sql)->execute($payload);
    $id = (int)$pdo->lastInsertId();
  }

  if ($rutPersona !== null && $syncPersona) {
    $sets = ['latitud = :ulat', 'longitud = :ulng'];
    $up = [':ulat' => $latitud, ':ulng' => $longitud, ':urut' => $rutPersona];

    if ($direccion !== null) { $sets[] = 'direccion = :udir'; $up[':udir'] = $direccion; }
    if ($telefono !== null) { $sets[] = 'celular = :ucel'; $up[':ucel'] = $telefono; }
    if ($sectorizacion !== null) { $sets[] = 'sectorizacion = :usectorizacion'; $up[':usectorizacion'] = $sectorizacion; }
    if ($sector !== null) { $sets[] = 'sector = :usector'; $up[':usector'] = $sector; }
    if ($registradoPor !== null) { $sets[] = 'registrado_por = :ureg'; $up[':ureg'] = $registradoPor; }

    $pdo->prepare('UPDATE usuarios SET ' . implode(', ', $sets) . ' WHERE rut = :urut')->execute($up);
  }

  $pdo->commit();

  // La bitácora se registra después del commit principal para evitar que
  // una creación automática de tabla o falla de auditoría cambie la respuesta
  // del guardado. El punto ya quedó confirmado correctamente.
  fp_log_activity(
    $pdo,
    $u,
    'Geolocalización Comunitaria',
    $esNuevo ? 'Crear punto' : 'Guardar punto',
    'Se guardó el punto comunitario: ' . $nombre,
    'geo_comunitaria_puntos',
    (string)$id
  );

  json_response(['ok' => true, 'id' => $id, 'message' => 'Punto comunitario guardado correctamente.']);
} catch (Throwable $e) {
  if ($pdo->inTransaction()) $pdo->rollBack();
  error_log('GEO COM SAVE ERROR: ' . $e->getMessage());
  json_response(['ok' => false, 'message' => 'Error guardando punto comunitario.'], 500);
}
