<?php
declare(strict_types=1);

require_once __DIR__ . '/../auth/guard.php';
require_once __DIR__ . '/../conexion.php';
require_once __DIR__ . '/../_helpers.php';

$u = require_login();
require_module_write($u, "familias");

// ✅ helpers de respuesta (por si no existen en este endpoint)
if (!function_exists('respond')) {
  function respond(array $payload, int $code = 200): void {
    json_response($payload, $code);
  }
}
if (!function_exists('respond_error')) {
  function respond_error(string $msg, int $code = 400): void {
    json_response(['ok' => false, 'message' => $msg], $code);
  }
}


function safe_read_json(): array {
  $raw = file_get_contents('php://input');
  if ($raw === false || trim($raw) === '') return [];
  $data = json_decode($raw, true);
  return is_array($data) ? $data : [];
}

function norm_rut(?string $rut): ?string {
  if ($rut === null) return null;
  $rut = strtoupper($rut);
  $rut = preg_replace('/[^0-9K]/', '', $rut) ?? '';
  $rut = substr($rut, 0, 15);
  return $rut !== '' ? $rut : null;
}

function int_or_null($v): ?int {
  if ($v === '' || $v === null) return null;
  if (is_int($v)) return $v;
  if (is_numeric($v)) return (int)$v;
  return null;
}

/**
 * Acepta:
 * - YYYY-MM-DD  (HTML date normal)
 * - DD-MM-YYYY  (como se ve en tu pantalla)
 * - DD/MM/YYYY
 * Devuelve YYYY-MM-DD o null
 */
function norm_date($s): ?string {
  $s = trim((string)$s);
  if ($s === '') return null;

  // ya viene bien
  if (preg_match('/^\d{4}-\d{2}-\d{2}$/', $s)) return $s;

  // DD-MM-YYYY
  if (preg_match('/^(\d{2})-(\d{2})-(\d{4})$/', $s, $m)) {
    return $m[3] . '-' . $m[2] . '-' . $m[1];
  }

  // DD/MM/YYYY
  if (preg_match('/^(\d{2})\/(\d{2})\/(\d{4})$/', $s, $m)) {
    return $m[3] . '-' . $m[2] . '-' . $m[1];
  }

  // último intento (por si llega algo raro)
  $t = strtotime($s);
  if ($t !== false) return date('Y-m-d', $t);

  return null;
}

try {
  $in = safe_read_json();

  $codigo = trim((string)($in['codigo_familia'] ?? $in['cod_familia'] ?? ''));
  $apellido = trim((string)($in['apellido_familia'] ?? ''));
  $fecha = norm_date($in['fecha_evaluacion'] ?? '');

  $sectorizacion = int_or_null($in['sectorizacion'] ?? null);
  $sector = int_or_null($in['sector'] ?? null);
  $direccion = trim((string)($in['direccion'] ?? ''));

  if ($codigo === '' || $apellido === '') {
    respond_error('Código y apellido son obligatorios', 422);
  }

  // registrado_por desde sesión (normalizado y validado contra funcionario)
  $registrado_por = null;
  if (isset($_SESSION['rut'])) $registrado_por = (string)$_SESSION['rut'];
  elseif (isset($_SESSION['usuario_rut'])) $registrado_por = (string)$_SESSION['usuario_rut'];
  elseif (isset($_SESSION['usuario']['rut'])) $registrado_por = (string)$_SESSION['usuario']['rut'];

  $registrado_por = norm_rut($registrado_por);

  if ($registrado_por !== null) {
    $stCheck = $pdo->prepare("SELECT 1 FROM funcionario WHERE rut = :r LIMIT 1");
    $stCheck->execute([':r' => $registrado_por]);
    if (!$stCheck->fetchColumn()) {
      // si no existe en funcionario, lo dejamos NULL para no romper FK
      $registrado_por = null;
    }
  }

  $integrantes = $in['integrantes'] ?? [];
  if (!is_array($integrantes)) $integrantes = [];
  $integrantes = array_values(array_unique(array_filter(array_map(
    fn($r) => norm_rut((string)$r),
    $integrantes
  ))));

  $clas = $in['clasificacion'] ?? [];
  if (!is_array($clas)) $clas = [];

  $tipo_familia = $clas['tipo_familia'] ?? null;
  $etapa_ciclo_familia = $clas['etapa_ciclo_familia'] ?? null;

  $fp = $clas['factores_protectores'] ?? [];
  $fr = $clas['factores_riesgo'] ?? [];
  if (!is_array($fp)) $fp = [];
  if (!is_array($fr)) $fr = [];

  $puntaje_riesgo = $clas['puntaje_riesgo'] ?? null;
  $puntaje_riesgo = ($puntaje_riesgo === '' || $puntaje_riesgo === null) ? null : (int)$puntaje_riesgo;

  $clasificacion_riesgo = $clas['clasificacion_riesgo'] ?? null;

  $pdo->beginTransaction();

  // Upsert familia
  $st = $pdo->prepare("
    INSERT INTO familias
      (codigo_familia, apellido_familia, sector, sectorizacion, direccion, fecha_evaluacion, registrado_por)
    VALUES
      (:codigo, :apellido, :sector, :sectorizacion, :direccion, :fecha, :reg)
    ON DUPLICATE KEY UPDATE
      apellido_familia = VALUES(apellido_familia),
      sector = VALUES(sector),
      sectorizacion = VALUES(sectorizacion),
      direccion = VALUES(direccion),
      fecha_evaluacion = VALUES(fecha_evaluacion),
      registrado_por = VALUES(registrado_por),
      ultima_actualizacion = CURRENT_TIMESTAMP
  ");
  $st->execute([
    ':codigo' => $codigo,
    ':apellido' => $apellido,
    ':sector' => $sector,
    ':sectorizacion' => $sectorizacion,
    ':direccion' => $direccion,
    ':fecha' => $fecha,
    ':reg' => $registrado_por,
  ]);

  // Upsert clasificación (1 por familia)
  $stFind = $pdo->prepare('SELECT id FROM clasificacion_familiar WHERE codigo_familia = :codigo LIMIT 1');
  $stFind->execute([':codigo' => $codigo]);
  $idClasif = $stFind->fetchColumn();

  $fpJson = json_encode(array_values($fp), JSON_UNESCAPED_UNICODE);
  $frJson = json_encode(array_values($fr), JSON_UNESCAPED_UNICODE);

  if ($idClasif) {
    $stUp = $pdo->prepare("
      UPDATE clasificacion_familiar
      SET tipo_familia = :tipo,
          etapa_ciclo_familia = :etapa,
          factores_protectores = :fp,
          factores_riesgo = :fr,
          puntaje_riesgo = :puntaje,
          clasificacion_riesgo = :cr,
          registrado_por = :reg,
          ultima_actualizacion = CURRENT_TIMESTAMP
      WHERE id = :id
    ");
    $stUp->execute([
      ':tipo' => $tipo_familia,
      ':etapa' => $etapa_ciclo_familia,
      ':fp' => $fpJson,
      ':fr' => $frJson,
      ':puntaje' => $puntaje_riesgo,
      ':cr' => $clasificacion_riesgo,
      ':reg' => $registrado_por,
      ':id' => (int)$idClasif,
    ]);
  } else {
    $stIn = $pdo->prepare("
      INSERT INTO clasificacion_familiar
        (codigo_familia, tipo_familia, etapa_ciclo_familia, factores_protectores, factores_riesgo, puntaje_riesgo, clasificacion_riesgo, registrado_por)
      VALUES
        (:codigo, :tipo, :etapa, :fp, :fr, :puntaje, :cr, :reg)
    ");
    $stIn->execute([
      ':codigo' => $codigo,
      ':tipo' => $tipo_familia,
      ':etapa' => $etapa_ciclo_familia,
      ':fp' => $fpJson,
      ':fr' => $frJson,
      ':puntaje' => $puntaje_riesgo,
      ':cr' => $clasificacion_riesgo,
      ':reg' => $registrado_por,
    ]);
  }

  // Vincular integrantes (usuarios.familia = codigo)
  $stOld = $pdo->prepare('SELECT rut FROM usuarios WHERE familia = :codigo');
  $stOld->execute([':codigo' => $codigo]);
  $old = $stOld->fetchAll(PDO::FETCH_COLUMN) ?: [];

  $oldSet = array_flip(array_map('strval', $old));
  $newSet = array_flip(array_map('strval', $integrantes));

  $toAdd = array_keys(array_diff_key($newSet, $oldSet));
  $toDel = array_keys(array_diff_key($oldSet, $newSet));

  if ($toAdd) {
    $stAdd = $pdo->prepare('UPDATE usuarios SET familia = :codigo WHERE rut = :rut');
    foreach ($toAdd as $rut) {
      $stAdd->execute([':codigo' => $codigo, ':rut' => $rut]);
    }
  }

  if ($toDel) {
    $stDel = $pdo->prepare('UPDATE usuarios SET familia = NULL WHERE rut = :rut AND familia = :codigo');
    foreach ($toDel as $rut) {
      $stDel->execute([':rut' => $rut, ':codigo' => $codigo]);
    }
  }

  $pdo->commit();

  fp_log_activity($pdo, $u, 'Familias', 'Guardar familia', 'Se guardó/actualizó la familia código ' . $codigo, 'familia', (string)$codigo);

  respond([
    'ok' => true,
    'codigo_familia' => $codigo,
    'message' => 'Familia guardada',
  ]);

} catch (Throwable $e) {
  if (isset($pdo) && $pdo->inTransaction()) $pdo->rollBack();

  error_log('SAVE FAMILIAS ERROR: ' . $e->getMessage());

  // Si estás en localhost, es mejor que veas el motivo real (fecha, FK, etc.)
  $msg = $e->getMessage();
  respond_error('Error guardando familia: ' . $msg, 500);
}
