<?php
// views/pages/raspadita/api/coordinador_devolver.php
// DEVOLUCIÓN por CÓDIGOS + reverso de saldo (PV/CAN)
//
// ✅ Reglas:
// - rol=7
// - solo del id_coordinador en sesión
// - debe estar asignado al destino indicado (PV o CAN)
// - estado requerido:
//     - PV  => estado=2
//     - CAN => estado=3
// - al devolver: estado=1, id_usuario=0, id_canillita=0, fecha_hora=NOW
// - resta saldo al destino:
//     - CAN: tbr_canillita.saldo
//     - PV : tbr_usuario.saldo (solo si existe la columna saldo)
// - devuelve totales: subtotal, descuento, total

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');

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'=>'Use POST'], JSON_UNESCAPED_UNICODE);
  exit;
}

function jexit(array $p, int $c=200): void {
  http_response_code($c);
  echo json_encode($p, JSON_UNESCAPED_UNICODE);
  exit;
}
function read_json(): array {
  $raw = file_get_contents('php://input');
  if (!$raw) return [];
  $j = json_decode($raw, true);
  return is_array($j) ? $j : [];
}
function now_str(): string { return date('Y-m-d H:i:s'); }

if (!isset($_SESSION['ingreso']) || $_SESSION['ingreso'] !== 'YES' || (int)($_SESSION['id_rol'] ?? 0) !== 7) {
  jexit(['success'=>false,'message'=>'No autorizado'], 401);
}

$id_coordinador = (int)($_SESSION['id_coordinador'] ?? 0);
if ($id_coordinador <= 0) jexit(['success'=>false,'message'=>'Sesión sin coordinador'], 401);

$in = read_json();
$tipo       = strtoupper(trim((string)($in['tipo'] ?? ''))); // PV|CAN
$id_destino = (int)($in['id_destino'] ?? 0);
$codigos    = $in['codigos'] ?? null;

$precio_unitario = (float)($in['precio_unitario'] ?? 0.50);
$descuento_in    = (float)($in['descuento'] ?? 0);

if (!in_array($tipo, ['PV','CAN'], true)) jexit(['success'=>false,'message'=>'tipo inválido (PV|CAN)'], 422);
if ($id_destino <= 0) jexit(['success'=>false,'message'=>'id_destino requerido'], 422);
if (!is_array($codigos) || count($codigos) < 1) jexit(['success'=>false,'message'=>'codigos requerido (array)'], 422);
if (count($codigos) > 800) jexit(['success'=>false,'message'=>'Máximo 800 códigos por envío'], 422);

if ($precio_unitario <= 0) jexit(['success'=>false,'message'=>'precio_unitario inválido'], 422);
if ($descuento_in < 0) jexit(['success'=>false,'message'=>'descuento no puede ser negativo'], 422);

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

$fecha = now_str();

/* limpiar códigos */
$clean = [];
foreach ($codigos as $c) {
  $c = trim((string)$c);
  if ($c !== '') $clean[] = $c;
}
$clean = array_values(array_unique($clean));
if (count($clean) < 1) jexit(['success'=>false,'message'=>'Lista de códigos vacía'], 422);

mysqli_begin_transaction($db);

try {
  // ===== 0) validar destino =====
  if ($tipo === 'PV') {
    $st = mysqli_prepare($db, "SELECT idusuario FROM tbr_usuario WHERE idusuario=? AND activo=1 AND condicion=1 LIMIT 1");
    if (!$st) throw new Exception('SQL destino PV error');
    mysqli_stmt_bind_param($st, "i", $id_destino);
    mysqli_stmt_execute($st);
    mysqli_stmt_store_result($st);
    $ok = (mysqli_stmt_num_rows($st) > 0);
    mysqli_stmt_close($st);
    if (!$ok) { mysqli_rollback($db); jexit(['success'=>false,'message'=>'Punto de venta inválido o inactivo'], 422); }
  } else {
    $st = mysqli_prepare($db, "SELECT id FROM tbr_canillita WHERE id=? AND activo=1 LIMIT 1");
    if (!$st) throw new Exception('SQL destino CAN error');
    mysqli_stmt_bind_param($st, "i", $id_destino);
    mysqli_stmt_execute($st);
    mysqli_stmt_store_result($st);
    $ok = (mysqli_stmt_num_rows($st) > 0);
    mysqli_stmt_close($st);
    if (!$ok) { mysqli_rollback($db); jexit(['success'=>false,'message'=>'Canillita inválido o inactivo'], 422); }
  }

  // ===== 1) EXISTENCIAS =====
  $ph = implode(',', array_fill(0, count($clean), '?'));
  $types = str_repeat('s', count($clean));

  $sqlExist = "SELECT codigo, estado,
                      COALESCE(id_usuario,0) id_usuario,
                      COALESCE(id_canillita,0) id_canillita,
                      COALESCE(id_coordinador,0) id_coordinador
               FROM tbr_raspadita
               WHERE codigo IN ($ph)";
  $stmtE = mysqli_prepare($db, $sqlExist);
  if (!$stmtE) throw new Exception('SQL existencia error');

  mysqli_stmt_bind_param($stmtE, $types, ...$clean);
  mysqli_stmt_execute($stmtE);
  mysqli_stmt_store_result($stmtE);
  mysqli_stmt_bind_result($stmtE, $cCodigo, $cEstado, $cIdU, $cIdCan, $cIdCoord);

  $existMap = [];
  while (mysqli_stmt_fetch($stmtE)) {
    $existMap[(string)$cCodigo] = [
      'codigo'=>(string)$cCodigo,
      'estado'=>(int)$cEstado,
      'id_usuario'=>(int)$cIdU,
      'id_canillita'=>(int)$cIdCan,
      'id_coordinador'=>(int)$cIdCoord,
    ];
  }
  mysqli_stmt_close($stmtE);

  $no_encontrados = [];
  $no_disponibles = [];
  $para_devolver  = [];

  foreach ($clean as $c) {
    if (!isset($existMap[$c])) { $no_encontrados[] = $c; continue; }

    $r = $existMap[$c];
    $esMio = ((int)$r['id_coordinador'] === $id_coordinador);

    // Debe estar asignado EXACTO a ese destino
    $asignadoAlDestino = false;
    if ($tipo === 'PV') {
      $asignadoAlDestino = ((int)$r['id_usuario'] === $id_destino) && ((int)$r['id_canillita'] === 0);
    } else {
      $asignadoAlDestino = ((int)$r['id_canillita'] === $id_destino) && ((int)$r['id_usuario'] === 0);
    }

    // ✅ Estado requerido según tipo
    $estadoOk = ($tipo === 'PV')
      ? ((int)$r['estado'] === 2)   // PV: 2
      : ((int)$r['estado'] === 3);  // CAN: 3

    if (!$esMio || !$asignadoAlDestino || !$estadoOk) {
      $no_disponibles[] = $c;
      continue;
    }

    $para_devolver[] = $c;
  }

  if (count($para_devolver) < 1) {
    mysqli_rollback($db);
    jexit([
      'success'=>false,
      'message'=>'Ningún código disponible para devolver',
      'enviados'=>count($clean),
      'devueltos'=>0,
      'devueltos_codigos'=>[],
      'no_encontrados'=>$no_encontrados,
      'no_disponibles'=>$no_disponibles
    ], 409);
  }

  // ===== 2) DEVOLVER (estado=1 + limpiar destino) =====
  $ph2 = implode(',', array_fill(0, count($para_devolver), '?'));

  $sqlUp = "
    UPDATE tbr_raspadita
    SET id_usuario=0,
        id_canillita=0,
        estado=1,
        fecha_hora=?
    WHERE id_coordinador=?
      AND codigo IN ($ph2)
  ";

  $stmtU = mysqli_prepare($db, $sqlUp);
  if (!$stmtU) throw new Exception('SQL update devolver error');

  $typesU  = "si" . str_repeat("s", count($para_devolver)); // fecha, id_coord, codigos...
  $paramsU = array_merge([$fecha, $id_coordinador], $para_devolver);
  mysqli_stmt_bind_param($stmtU, $typesU, ...$paramsU);
  mysqli_stmt_execute($stmtU);
  mysqli_stmt_close($stmtU);

  // ===== 3) RE-CONSULTA (confirmar devueltos) =====
  $devueltos = [];

  $ph3 = implode(',', array_fill(0, count($para_devolver), '?'));
  $types3 = str_repeat('s', count($para_devolver));

  // ✅ Si devolvió bien, quedó estado=1 y destino en 0
  $sqlChk = "SELECT codigo FROM tbr_raspadita
             WHERE codigo IN ($ph3)
               AND estado = 1
               AND COALESCE(id_usuario,0)=0
               AND COALESCE(id_canillita,0)=0
             LIMIT 10000";

  $stmtC = mysqli_prepare($db, $sqlChk);
  if (!$stmtC) throw new Exception('SQL check devueltos error');

  mysqli_stmt_bind_param($stmtC, $types3, ...$para_devolver);
  mysqli_stmt_execute($stmtC);
  mysqli_stmt_store_result($stmtC);
  mysqli_stmt_bind_result($stmtC, $cx);
  while (mysqli_stmt_fetch($stmtC)) $devueltos[] = (string)$cx;
  mysqli_stmt_close($stmtC);

  // Los que no quedaron devueltos (carrera) -> no_disponibles
  $devSet = array_fill_keys($devueltos, true);
  foreach ($para_devolver as $c) if (!isset($devSet[$c])) $no_disponibles[] = $c;

  // ===== 4) TOTALES según devueltos reales =====
  $cant_dev = count($devueltos);
  $subtotal = round($cant_dev * $precio_unitario, 2);
  $descuento = round(min(max(0, $descuento_in), $subtotal), 2);
  $total = round(max(0, $subtotal - $descuento), 2);

  // ===== 5) RESTAR SALDO destino =====
  $saldo_restado = false;
  $nuevo_saldo = null;
  $saldo_target = null; // CAN|PV
  $saldo_warning = null;

  if ($cant_dev > 0 && $total > 0) {

    if ($tipo === 'CAN') {
      $stSaldo = mysqli_prepare($db, "UPDATE tbr_canillita SET saldo = GREATEST(0, COALESCE(saldo,0) - ?) WHERE id=? LIMIT 1");
      if (!$stSaldo) throw new Exception('SQL restar saldo canillita error');
      mysqli_stmt_bind_param($stSaldo, "di", $total, $id_destino);
      mysqli_stmt_execute($stSaldo);
      if (mysqli_stmt_affected_rows($stSaldo) < 1) {
        mysqli_stmt_close($stSaldo);
        throw new Exception('No se pudo restar saldo del canillita');
      }
      mysqli_stmt_close($stSaldo);

      $stGet = mysqli_prepare($db, "SELECT COALESCE(saldo,0) FROM tbr_canillita WHERE id=? LIMIT 1");
      if ($stGet) {
        mysqli_stmt_bind_param($stGet, "i", $id_destino);
        mysqli_stmt_execute($stGet);
        mysqli_stmt_store_result($stGet);
        mysqli_stmt_bind_result($stGet, $s);
        mysqli_stmt_fetch($stGet);
        $nuevo_saldo = (float)$s;
        mysqli_stmt_close($stGet);
      }

      $saldo_restado = true;
      $saldo_target = 'CAN';

    } else {
      // PV: solo si existe tbr_usuario.saldo
      $hasSaldo = false;
      $chk = mysqli_prepare($db, "
        SELECT 1
        FROM information_schema.COLUMNS
        WHERE TABLE_SCHEMA = DATABASE()
          AND TABLE_NAME = 'tbr_usuario'
          AND COLUMN_NAME = 'saldo'
        LIMIT 1
      ");
      if ($chk) {
        mysqli_stmt_execute($chk);
        mysqli_stmt_store_result($chk);
        $hasSaldo = (mysqli_stmt_num_rows($chk) > 0);
        mysqli_stmt_close($chk);
      }

      if ($hasSaldo) {
        $stSaldoPv = mysqli_prepare($db, "UPDATE tbr_usuario SET saldo = GREATEST(0, COALESCE(saldo,0) - ?) WHERE idusuario=? LIMIT 1");
        if (!$stSaldoPv) throw new Exception('SQL restar saldo PV error');
        mysqli_stmt_bind_param($stSaldoPv, "di", $total, $id_destino);
        mysqli_stmt_execute($stSaldoPv);
        if (mysqli_stmt_affected_rows($stSaldoPv) < 1) {
          mysqli_stmt_close($stSaldoPv);
          throw new Exception('No se pudo restar saldo del punto de venta');
        }
        mysqli_stmt_close($stSaldoPv);

        $stGetPv = mysqli_prepare($db, "SELECT COALESCE(saldo,0) FROM tbr_usuario WHERE idusuario=? LIMIT 1");
        if ($stGetPv) {
          mysqli_stmt_bind_param($stGetPv, "i", $id_destino);
          mysqli_stmt_execute($stGetPv);
          mysqli_stmt_store_result($stGetPv);
          mysqli_stmt_bind_result($stGetPv, $s2);
          mysqli_stmt_fetch($stGetPv);
          $nuevo_saldo = (float)$s2;
          mysqli_stmt_close($stGetPv);
        }

        $saldo_restado = true;
        $saldo_target = 'PV';
      } else {
        $saldo_warning = "No se restó saldo en PV porque tbr_usuario no tiene columna 'saldo'.";
      }
    }
  }

  mysqli_commit($db);

  jexit([
    'success'=>true,
    'message'=>'Devolución realizada',
    'tipo'=>$tipo,
    'id_destino'=>$id_destino,
    'fecha_hora'=>$fecha,

    'enviados'=>count($clean),
    'devueltos'=>$cant_dev,
    'devueltos_codigos'=>$devueltos,
    'no_encontrados'=>$no_encontrados,
    'no_disponibles'=>$no_disponibles,

    'precio_unitario'=>$precio_unitario,
    'subtotal'=>$subtotal,
    'descuento'=>$descuento,
    'total'=>$total,

    'saldo_restado'=>$saldo_restado,
    'saldo_target'=>$saldo_target,
    'nuevo_saldo'=>$nuevo_saldo,
    'saldo_warning'=>$saldo_warning
  ]);

} catch (Throwable $e) {
  mysqli_rollback($db);
  jexit(['success'=>false,'message'=>'Error', 'detail'=>$e->getMessage()], 500);
}