<?php
// views/pages/raspadita/api/canillita_admin_actions.php
declare(strict_types=1);

session_start();
date_default_timezone_set('America/Guayaquil');

header('Content-Type: application/json; charset=utf-8');
header('Cache-Control: no-store, no-cache, must-revalidate, max-age=0');
header('Pragma: no-cache');
header('Expires: 0');

header('Access-Control-Allow-Methods: POST, OPTIONS');
header('Access-Control-Allow-Headers: Content-Type, Authorization, X-CSRF-Token');

if (($_SERVER['REQUEST_METHOD'] ?? '') === 'OPTIONS') { http_response_code(204); exit; }
if (($_SERVER['REQUEST_METHOD'] ?? '') !== 'POST') {
  http_response_code(405);
  echo json_encode(['success'=>false,'message'=>'Método no permitido'], JSON_UNESCAPED_UNICODE);
  exit;
}

// ✅ sesión (ajusta si quieres)
if (!isset($_SESSION['idusuario'])) {
  http_response_code(401);
  echo json_encode(['success'=>false,'message'=>'Sesión no iniciada'], JSON_UNESCAPED_UNICODE);
  exit;
}

// ✅ CSRF
$csrfHeader = (string)($_SERVER['HTTP_X_CSRF_TOKEN'] ?? '');
$csrfSess   = (string)($_SESSION['csrf'] ?? '');
if ($csrfSess === '' || !hash_equals($csrfSess, $csrfHeader)) {
  http_response_code(419);
  echo json_encode(['success'=>false,'message'=>'CSRF inválido'], JSON_UNESCAPED_UNICODE);
  exit;
}

require_once __DIR__ . '/../../conex.php';
$db = $conn ?? null;
if (!$db instanceof mysqli) {
  http_response_code(500);
  echo json_encode(['success'=>false,'message'=>'Sin conexión BD'], JSON_UNESCAPED_UNICODE);
  exit;
}
mysqli_set_charset($db, 'utf8mb4');
@mysqli_query($db, "SET time_zone='-05:00'");

function jexit(array $payload, int $code=200): void {
  http_response_code($code);
  echo json_encode($payload, JSON_UNESCAPED_UNICODE);
  exit;
}
function read_json(): array {
  $raw = file_get_contents('php://input');
  $j = json_decode($raw ?: '[]', true);
  return is_array($j) ? $j : [];
}
function upper(string $s): string {
  $s = trim($s);
  return $s === '' ? '' : mb_strtoupper($s, 'UTF-8');
}
function ip(): string {
  $ip = $_SERVER['HTTP_CF_CONNECTING_IP'] ?? $_SERVER['HTTP_X_FORWARDED_FOR'] ?? $_SERVER['REMOTE_ADDR'] ?? '';
  if (strpos($ip, ',') !== false) $ip = trim(explode(',', $ip)[0]);
  return substr($ip, 0, 45);
}

$in = read_json();
$action = (string)($in['action'] ?? '');
$id_admin = (int)($_SESSION['idusuario'] ?? 0);

/* ===================== LIST ===================== */
if ($action === 'list') {
  $rows = [];
  $res = $db->query("SELECT id, canillita, activo, saldo FROM tbr_canillita ORDER BY id DESC");
  if ($res) {
    while ($r = $res->fetch_assoc()) $rows[] = $r;
    $res->free();
  }
  jexit(['success'=>true,'data'=>$rows]);
}

/* ===================== CREATE ===================== */
if ($action === 'create') {
  $canillita = upper((string)($in['canillita'] ?? ''));
  $activo = (int)($in['activo'] ?? 1);
  if ($canillita === '') jexit(['success'=>false,'message'=>'Nombre requerido'], 422);
  if (!in_array($activo, [0,1], true)) $activo = 1;

  // duplicado
  $st = $db->prepare("SELECT id FROM tbr_canillita WHERE canillita=? LIMIT 1");
  $st->bind_param("s", $canillita);
  $st->execute();
  $dup = $st->get_result()->fetch_assoc();
  $st->close();
  if ($dup) jexit(['success'=>false,'message'=>'Ya existe un canillita con ese nombre'], 409);

  $saldo = "0.00";
  $st = $db->prepare("INSERT INTO tbr_canillita (canillita, activo, saldo) VALUES (?,?,?)");
  $st->bind_param("sis", $canillita, $activo, $saldo);
  if (!$st->execute()) {
    $err = $st->error ?: 'Error insertando';
    $st->close();
    jexit(['success'=>false,'message'=>'No se pudo crear','detail'=>$err], 500);
  }
  $id = (int)$st->insert_id;
  $st->close();

  jexit(['success'=>true,'message'=>'Canillita creado','id'=>$id]);
}

/* ===================== UPDATE ===================== */
if ($action === 'update') {
  $id = (int)($in['id'] ?? 0);
  $canillita = upper((string)($in['canillita'] ?? ''));
  $activo = (int)($in['activo'] ?? 1);

  if ($id <= 0) jexit(['success'=>false,'message'=>'ID inválido'], 422);
  if ($canillita === '') jexit(['success'=>false,'message'=>'Nombre requerido'], 422);
  if (!in_array($activo, [0,1], true)) $activo = 1;

  // duplicado (otro id)
  $st = $db->prepare("SELECT id FROM tbr_canillita WHERE canillita=? AND id<>? LIMIT 1");
  $st->bind_param("si", $canillita, $id);
  $st->execute();
  $dup = $st->get_result()->fetch_assoc();
  $st->close();
  if ($dup) jexit(['success'=>false,'message'=>'Ya existe un canillita con ese nombre'], 409);

  $st = $db->prepare("UPDATE tbr_canillita SET canillita=?, activo=? WHERE id=? LIMIT 1");
  $st->bind_param("sii", $canillita, $activo, $id);
  if (!$st->execute()) {
    $err = $st->error ?: 'Error actualizando';
    $st->close();
    jexit(['success'=>false,'message'=>'No se pudo actualizar','detail'=>$err], 500);
  }
  $st->close();

  jexit(['success'=>true,'message'=>'Actualizado']);
}

/* ===================== TOGGLE ===================== */
if ($action === 'toggle') {
  $id = (int)($in['id'] ?? 0);
  $activo = (int)($in['activo'] ?? -1);
  if ($id <= 0) jexit(['success'=>false,'message'=>'ID inválido'], 422);
  if (!in_array($activo, [0,1], true)) jexit(['success'=>false,'message'=>'Activo inválido'], 422);

  $st = $db->prepare("UPDATE tbr_canillita SET activo=? WHERE id=? LIMIT 1");
  $st->bind_param("ii", $activo, $id);
  if (!$st->execute()) {
    $err = $st->error ?: 'Error actualizando';
    $st->close();
    jexit(['success'=>false,'message'=>'No se pudo cambiar estado','detail'=>$err], 500);
  }
  $st->close();
  jexit(['success'=>true,'message'=>'Estado actualizado']);
}

/* ===================== DELETE ===================== */
if ($action === 'delete') {
  $id = (int)($in['id'] ?? 0);
  if ($id <= 0) jexit(['success'=>false,'message'=>'ID inválido'], 422);

  $st = $db->prepare("DELETE FROM tbr_canillita WHERE id=? LIMIT 1");
  $st->bind_param("i", $id);
  if (!$st->execute()) {
    $err = $st->error ?: 'Error eliminando';
    $st->close();
    jexit(['success'=>false,'message'=>'No se pudo eliminar','detail'=>$err], 500);
  }
  $st->close();
  jexit(['success'=>true,'message'=>'Eliminado']);
}

/* ===================== COBRO (ABONO AL SALDO) ===================== */
if ($action === 'cobro') {
  $id_canillita = (int)($in['id_canillita'] ?? 0);
  $abono = (float)($in['abono'] ?? 0);
  $observacion = trim((string)($in['observacion'] ?? ''));

  if ($id_canillita <= 0) jexit(['success'=>false,'message'=>'Canillita inválido'], 422);
  if ($abono <= 0) jexit(['success'=>false,'message'=>'Abono inválido'], 422);

  // saldo actual
  $st = $db->prepare("SELECT saldo FROM tbr_canillita WHERE id=? LIMIT 1");
  $st->bind_param("i", $id_canillita);
  $st->execute();
  $row = $st->get_result()->fetch_assoc();
  $st->close();
  if (!$row) jexit(['success'=>false,'message'=>'Canillita no existe'], 404);

  $saldoActual = (float)($row['saldo'] ?? 0);
  if ($abono > $saldoActual + 0.00001) jexit(['success'=>false,'message'=>'El abono no puede ser mayor al saldo actual'], 422);

  $saldoNuevo = $saldoActual - $abono;

  // Guardar historial en tbr_coordinador_saldo (misma idea que coordinador):
  // subtotal = saldo_anterior
  // descuento = abono
  // total_pagar = saldo_nuevo
  $fecha_hora = date('Y-m-d H:i:s');
  $ip = ip();
  $tipo_pago = 'ABONO'; // fijo, puedes cambiar si quieres

  $db->begin_transaction();
  try {
    $num_raspaditas = 0;
    $subtotal = $saldoActual;
    $descuento = $abono;
    $total_pagar = $saldoNuevo;

    $ins = $db->prepare("
      INSERT INTO tbr_coordinador_saldo
      (fecha_hora, num_raspaditas, subtotal, descuento, total_pagar, observacion, id_admin, ip, tipo_pago, id_canillita)
      VALUES (?,?,?,?,?,?,?,?,?,?)
    ");
    if (!$ins) throw new Exception("Error preparando insert historial");

    $ins->bind_param(
      "siddsdissi",
      $fecha_hora,
      $num_raspaditas,
      $subtotal,
      $descuento,
      $total_pagar,
      $observacion,
      $id_admin,
      $ip,
      $tipo_pago,
      $id_canillita
    );
    if (!$ins->execute()) {
      $err = $ins->error ?: 'Error insertando historial';
      $ins->close();
      throw new Exception($err);
    }
    $ins->close();

    // actualizar saldo
    $up = $db->prepare("UPDATE tbr_canillita SET saldo=? WHERE id=? LIMIT 1");
    if (!$up) throw new Exception("Error preparando update saldo");
    $up->bind_param("di", $saldoNuevo, $id_canillita);
    if (!$up->execute()) {
      $err = $up->error ?: 'Error actualizando saldo';
      $up->close();
      throw new Exception($err);
    }
    $up->close();

    $db->commit();
    jexit(['success'=>true,'message'=>'Cobro registrado']);
  } catch (Throwable $e) {
    $db->rollback();
    jexit(['success'=>false,'message'=>'Error en cobro','detail'=>$e->getMessage()], 500);
  }
}

/* ===================== HISTORIAL ===================== */
if ($action === 'list_historial') {
  $id_canillita = (int)($in['id_canillita'] ?? 0);
  $desde = trim((string)($in['desde'] ?? ''));
  $hasta = trim((string)($in['hasta'] ?? ''));

  $w = [];
  $p = [];
  $t = '';

  if ($id_canillita > 0) { $w[] = "cs.id_canillita=?"; $t .= "i"; $p[] = $id_canillita; }
  if ($desde !== '') { $w[] = "DATE(cs.fecha_hora) >= ?"; $t .= "s"; $p[] = $desde; }
  if ($hasta !== '') { $w[] = "DATE(cs.fecha_hora) <= ?"; $t .= "s"; $p[] = $hasta; }

  $where = $w ? ("WHERE " . implode(" AND ", $w)) : "";

  $sql = "
    SELECT cs.id, cs.fecha_hora, cs.id_canillita, c.canillita,
           cs.subtotal AS saldo_anterior,
           cs.descuento AS abono,
           cs.total_pagar AS saldo_nuevo,
           cs.observacion
    FROM tbr_coordinador_saldo cs
    INNER JOIN tbr_canillita c ON c.id = cs.id_canillita
    {$where}
    ORDER BY cs.id DESC
    LIMIT 1000
  ";

  $rows = [];
  if ($w) {
    $st = $db->prepare($sql);
    $st->bind_param($t, ...$p);
    $st->execute();
    $res = $st->get_result();
    while ($r = $res->fetch_assoc()) $rows[] = $r;
    $st->close();
  } else {
    $res = $db->query($sql);
    if ($res) {
      while ($r = $res->fetch_assoc()) $rows[] = $r;
      $res->free();
    }
  }

  jexit(['success'=>true,'data'=>$rows]);
}

/* ===================== ANULAR COBRO ===================== */
if ($action === 'anular_cobro') {
  $id_cobro = (int)($in['id_cobro'] ?? 0);
  $motivo = trim((string)($in['motivo'] ?? ''));

  if ($id_cobro <= 0) jexit(['success'=>false,'message'=>'ID cobro inválido'], 422);
  if ($motivo === '') jexit(['success'=>false,'message'=>'Motivo requerido'], 422);

  // Traer registro
  $st = $db->prepare("SELECT id, id_canillita, subtotal, descuento, total_pagar FROM tbr_coordinador_saldo WHERE id=? LIMIT 1");
  $st->bind_param("i", $id_cobro);
  $st->execute();
  $row = $st->get_result()->fetch_assoc();
  $st->close();

  if (!$row) jexit(['success'=>false,'message'=>'Cobro no existe'], 404);

  $id_canillita = (int)$row['id_canillita'];
  $saldo_anterior = (float)($row['subtotal'] ?? 0);
  $abono = (float)($row['descuento'] ?? 0);
  $saldo_nuevo = (float)($row['total_pagar'] ?? 0);

  $db->begin_transaction();
  try {
    // Revertir saldo al anterior (idéntico estilo)
    $up = $db->prepare("UPDATE tbr_canillita SET saldo=? WHERE id=? LIMIT 1");
    if (!$up) throw new Exception("Error preparando reverse saldo");
    $up->bind_param("di", $saldo_anterior, $id_canillita);
    if (!$up->execute()) {
      $err = $up->error ?: 'Error revirtiendo saldo';
      $up->close();
      throw new Exception($err);
    }
    $up->close();

    // (Opcional) Auditoría: si tienes tabla de anulaciones, aquí insertas el motivo.
    // Si NO tienes tabla, al menos dejamos el motivo en observacion del registro (o lo borras).
    // Aquí hacemos: actualizar observacion y luego eliminar (si prefieres no eliminar, me dices y lo cambio a "anulado=1").

    $obsAnul = "ANULADO: {$motivo}";
    $uobs = $db->prepare("UPDATE tbr_coordinador_saldo SET observacion = CONCAT(?, ' | ', COALESCE(observacion,'')) WHERE id=? LIMIT 1");
    if ($uobs) {
      $uobs->bind_param("si", $obsAnul, $id_cobro);
      $uobs->execute();
      $uobs->close();
    }

    // Eliminar (misma idea que tú usas)
    $del = $db->prepare("DELETE FROM tbr_coordinador_saldo WHERE id=? LIMIT 1");
    if (!$del) throw new Exception("Error preparando delete");
    $del->bind_param("i", $id_cobro);
    if (!$del->execute()) {
      $err = $del->error ?: 'Error eliminando cobro';
      $del->close();
      throw new Exception($err);
    }
    $del->close();

    $db->commit();
    jexit(['success'=>true,'message'=>'Cobro anulado y saldo revertido']);
  } catch (Throwable $e) {
    $db->rollback();
    jexit(['success'=>false,'message'=>'Error al anular','detail'=>$e->getMessage()], 500);
  }
}

jexit(['success'=>false,'message'=>'Acción inválida'], 400);
