<?php
/**
 * turno.php
 * ============================================================
 * BReport · Turno en curso (pestaña dedicada)
 * - Iniciar turno (RUNNING)
 * - Heartbeat para mantener sesión viva
 * - Confirmación al intentar cerrar
 * ============================================================
 */
declare(strict_types=1);

require_once __DIR__ . '/includes/auth.php';
require_once __DIR__ . '/includes/helpers.php';
require_once __DIR__ . '/includes/csrf.php';

require_scope();

$pdo = pdo();
$u   = current_user();
$sc  = scope();

$companyId  = (int)$sc['company_id'];
$locationId = (int)$sc['location_id'];
$action     = (string)($_GET['action'] ?? '');

function jexit($data, int $code = 200): void {
  http_response_code($code);
  header('Content-Type: application/json; charset=utf-8');
  echo json_encode($data, JSON_UNESCAPED_UNICODE);
  exit;
}
function read_json(): array {
  $raw = file_get_contents('php://input');
  $d = json_decode($raw ?: '[]', true);
  return is_array($d) ? $d : [];
}
function need_csrf(): void {
  if (($_SERVER['REQUEST_METHOD'] ?? '') === 'GET') return;
  $hdr = $_SERVER['HTTP_X_CSRF'] ?? '';
  if ($hdr === '') jexit(['ok'=>false,'error'=>'Falta X-CSRF'], 419);
  csrf_verify($hdr);
}

function normalize_dt_local(string $s): string {
  // "YYYY-MM-DDTHH:MM" -> "YYYY-MM-DD HH:MM:00"
  $s = str_replace('T',' ', $s);
  if (strlen($s) === 16) $s .= ':00';
  return $s;
}

if ($action !== '') {
  ensure_session();
  need_csrf();

  if ($action === 'shift_status') {
    $date = (string)($_GET['date'] ?? date('Y-m-d'));

    $st = $pdo->prepare("
      SELECT id, work_date, shift, start_at, end_at, status, last_heartbeat_at
      FROM shift_sessions
      WHERE company_id=? AND location_id=? AND user_id=? AND work_date=? AND status='RUNNING'
      ORDER BY id DESC
      LIMIT 1
    ");
    $st->execute([$companyId,$locationId,(int)$u['id'],$date]);
    $row = $st->fetch();
    jexit(['ok'=>true,'running'=>$row ?: null]);
  }

  if ($action === 'shift_start') {
    $d = read_json();
    $date  = (string)($d['date'] ?? date('Y-m-d'));
    $shift = (int)($d['shift'] ?? 1);
    if (!in_array($shift,[1,2,3],true)) jexit(['ok'=>false,'error'=>'Turno inválido'], 400);

    // Si ya hay uno corriendo, regresarlo
    $st = $pdo->prepare("
      SELECT id FROM shift_sessions
      WHERE company_id=? AND location_id=? AND user_id=? AND work_date=? AND status='RUNNING'
      ORDER BY id DESC LIMIT 1
    ");
    $st->execute([$companyId,$locationId,(int)$u['id'],$date]);
    $id = (int)($st->fetchColumn() ?: 0);
    if ($id > 0) jexit(['ok'=>true,'id'=>$id,'already'=>true]);

    $startAt = date('Y-m-d H:i:s');

    $st = $pdo->prepare("
      INSERT INTO shift_sessions(company_id,location_id,user_id,work_date,shift,start_at,status,last_heartbeat_at)
      VALUES(?,?,?,?,?,?, 'RUNNING', NOW())
    ");
    $st->execute([$companyId,$locationId,(int)$u['id'],$date,$shift,$startAt]);
    jexit(['ok'=>true,'id'=>(int)$pdo->lastInsertId(),'already'=>false]);
  }

  if ($action === 'shift_heartbeat') {
    $d = read_json();
    $id = (int)($d['id'] ?? 0);
    if ($id<=0) jexit(['ok'=>false,'error'=>'ID inválido'], 400);

    $st = $pdo->prepare("
      UPDATE shift_sessions
      SET last_heartbeat_at=NOW()
      WHERE id=? AND company_id=? AND location_id=? AND user_id=? AND status='RUNNING'
    ");
    $st->execute([$id,$companyId,$locationId,(int)$u['id']]);
    jexit(['ok'=>true]);
  }

  if ($action === 'shift_end') {
    $d = read_json();
    $id = (int)($d['id'] ?? 0);
    if ($id<=0) jexit(['ok'=>false,'error'=>'ID inválido'], 400);

    $st = $pdo->prepare("
      UPDATE shift_sessions
      SET status='ENDED', end_at=NOW(), last_heartbeat_at=NOW()
      WHERE id=? AND company_id=? AND location_id=? AND user_id=? AND status='RUNNING'
    ");
    $st->execute([$id,$companyId,$locationId,(int)$u['id']]);
    jexit(['ok'=>true]);
  }

  jexit(['ok'=>false,'error'=>'Acción no válida'], 404);
}

/* UI */
$csrf = csrf_token();
$date = (string)($_GET['date'] ?? date('Y-m-d'));

$st = $pdo->prepare("SELECT name FROM companies WHERE id=?");
$st->execute([$companyId]);
$companyName = (string)($st->fetchColumn() ?: '');

$st = $pdo->prepare("SELECT name FROM locations WHERE id=?");
$st->execute([$locationId]);
$locationName = (string)($st->fetchColumn() ?: '');
?>
<!doctype html>
<html lang="es">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>BReport · Turno en curso</title>
  <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet">
  <style>
    .mono{font-family:ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;}
    body{background:#0b1220;color:#fff;}
    .card{background:rgba(255,255,255,.06); border:1px solid rgba(255,255,255,.12);}
    .muted{color:rgba(255,255,255,.7);}
  </style>
</head>
<body>
<div class="container py-4">
  <div class="d-flex align-items-center justify-content-between">
    <div>
      <div class="fw-bold fs-4">Turno en curso</div>
      <div class="muted small"><?=h($companyName)?> · <?=h($locationName)?> · Fecha: <span class="mono"><?=h($date)?></span></div>
    </div>
    <a class="btn btn-outline-light btn-sm" href="produccion.php" target="_blank">Abrir Producción</a>
  </div>

  <div class="row g-3 mt-2">
    <div class="col-12 col-lg-6">
      <div class="card rounded-4 p-3">
        <div class="muted small">Hora actual</div>
        <div class="display-5 mono" id="clock">--:--:--</div>

        <hr class="border-light opacity-25">

        <label class="form-label">Selecciona turno</label>
        <select class="form-select" id="shiftSel">
          <option value="1">Turno 1 (07:00 - 15:00)</option>
          <option value="2">Turno 2 (15:00 - 22:30)</option>
          <option value="3">Turno 3 (22:30 - 07:00)</option>
        </select>

        <div class="d-flex gap-2 mt-3">
          <button class="btn btn-success flex-grow-1" id="btnStart">Iniciar turno</button>
          <button class="btn btn-danger flex-grow-1" id="btnEnd" disabled>Terminar turno</button>
        </div>

        <div class="alert alert-warning mt-3 mb-0" id="warn" style="display:none;">
          Turno corriendo. Si intentas cerrar esta pestaña, el sistema te pedirá confirmación.
        </div>
      </div>
    </div>

    <div class="col-12 col-lg-6">
      <div class="card rounded-4 p-3">
        <div class="fw-bold">Estado</div>
        <div class="muted small">Se mantiene activo con “heartbeat” para evitar expiración por inactividad.</div>

        <div class="mt-3">
          <div class="muted small">Session ID</div>
          <div class="mono fs-5" id="sid">—</div>
        </div>

        <div class="mt-3">
          <div class="muted small">Inició</div>
          <div class="mono" id="started">—</div>
        </div>

        <div class="mt-3">
          <div class="muted small">Último ping</div>
          <div class="mono" id="ping">—</div>
        </div>

        <div class="mt-3 muted small">
          * No es posible impedir al 100% que se cierre una pestaña (limitación del navegador), pero el turno queda guardado en BD y se puede recuperar.
        </div>
      </div>
    </div>
  </div>
</div>

<script>
const CSRF = <?=json_encode($csrf)?>;
const DATE = <?=json_encode($date)?>;
const $ = (id)=>document.getElementById(id);

async function apiGet(action, params={}){
  const u = new URL(location.href);
  u.search = '';
  u.searchParams.set('action', action);
  for(const [k,v] of Object.entries(params)) u.searchParams.set(k, v);
  const r = await fetch(u.toString(), {credentials:'same-origin'});
  return r.json();
}
async function apiPost(action, payload){
  const u = new URL(location.href);
  u.search = '';
  u.searchParams.set('action', action);
  const r = await fetch(u.toString(), {
    method:'POST',
    credentials:'same-origin',
    headers:{'Content-Type':'application/json','X-CSRF':CSRF},
    body: JSON.stringify(payload||{})
  });
  return r.json();
}

let runningId = 0;
let hbTimer = null;

function tickClock(){
  const d = new Date();
  const pad = (n)=>String(n).padStart(2,'0');
  $('clock').textContent = pad(d.getHours())+':'+pad(d.getMinutes())+':'+pad(d.getSeconds());
}
setInterval(tickClock, 500);
tickClock();

function setRunningUI(row){
  runningId = row ? parseInt(row.id,10) : 0;

  $('sid').textContent = runningId ? String(runningId) : '—';
  $('started').textContent = row?.start_at ?? '—';
  $('ping').textContent = row?.last_heartbeat_at ?? '—';

  $('btnStart').disabled = !!runningId;
  $('btnEnd').disabled = !runningId;
  $('warn').style.display = runningId ? 'block' : 'none';

  if (hbTimer) { clearInterval(hbTimer); hbTimer = null; }
  if (runningId) {
    hbTimer = setInterval(async ()=>{
      const j = await apiPost('shift_heartbeat', {id: runningId});
      if (j.ok) $('ping').textContent = new Date().toISOString().slice(0,19).replace('T',' ');
    }, 25000);
  }
}

// Confirmación al cerrar (solo si hay turno corriendo)
window.addEventListener('beforeunload', (e)=>{
  if (!runningId) return;
  e.preventDefault();
  e.returnValue = '';
});

// Intentar mandar beacon al salir (mejor esfuerzo)
window.addEventListener('unload', ()=>{
  if (!runningId) return;
  try{
    const url = new URL(location.href);
    url.search = '';
    url.searchParams.set('action','shift_heartbeat');
    const blob = new Blob([JSON.stringify({id:runningId})], {type:'application/json'});
    navigator.sendBeacon(url.toString(), blob);
  }catch{}
});

async function loadStatus(){
  const j = await apiGet('shift_status', {date: DATE});
  if (j.ok) setRunningUI(j.running);
}

$('btnStart').addEventListener('click', async ()=>{
  const shift = parseInt($('shiftSel').value,10);
  const j = await apiPost('shift_start', {date: DATE, shift});
  if (!j.ok) return alert(j.error||'Error');
  await loadStatus();
});

$('btnEnd').addEventListener('click', async ()=>{
  if (!runningId) return;
  if (!confirm('¿Terminar turno?')) return;
  const j = await apiPost('shift_end', {id: runningId});
  if (!j.ok) return alert(j.error||'Error');
  await loadStatus();
});

loadStatus();
</script>
</body>
</html>