<?php
require_once __DIR__ . '/../config/user_functions.php';
if (session_status() === PHP_SESSION_NONE) { session_start(); }
require_once __DIR__ . '/../config/users_local.php';
require_once __DIR__ . '/../includes/db.php';      // expects $pdo (PDO)
require_once __DIR__ . '/../config/emailer.php';   // for sp_email_get_alerts (optional)

if (function_exists('user_has_permission') && !user_has_permission('reports')) {
    http_response_code(403);
    include __DIR__ . '/../includes/header.php';
    include __DIR__ . '/../includes/sidebar.php';
    echo "<div class='container-fluid py-4'><h3 class='text-danger'>Access denied</h3></div>";
    include __DIR__ . '/../includes/footer.php';
    exit;
}

/* ======================================================
   Helpers
====================================================== */
function sp_h($v): string { return htmlspecialchars((string)$v, ENT_QUOTES, 'UTF-8'); }
function sp_int($v): int { return (int)($v ?? 0); }
function sp_badge_class_source(string $s): string {
    $s = strtolower($s);
    if ($s === 'keyence') return 'primary';
    if ($s === 'symcode') return 'success';
    if ($s === 'manual')  return 'secondary';
    return 'dark';
}
function sp_badge_class_fn(string $f): string {
    $f = strtolower($f);
    if ($f === 'case_count') return 'info';
    if ($f === 'dump_bins')  return 'warning';
    if ($f === 'palletize')  return 'secondary';
    return 'dark';
}

/* ======================================================
   Filters
====================================================== */
$range = $_GET['range'] ?? 'day';
if (!in_array($range, ['day','7d','30d','all','custom'], true)) $range = 'day';

$now = new DateTime('now');
$from = null;
$to = null;

if ($range === 'custom') {
    $fromStr = trim($_GET['from'] ?? '');
    $toStr   = trim($_GET['to'] ?? '');
    if ($fromStr !== '') $from = DateTime::createFromFormat('Y-m-d', $fromStr) ?: null;
    if ($toStr !== '')   $to   = DateTime::createFromFormat('Y-m-d', $toStr) ?: null;

    // if only one specified, make reasonable bounds
    if ($from && !$to) $to = clone $from;
    if ($to && !$from) $from = clone $to;

    if ($from && $to) {
        // inclusive day bounds
        $from->setTime(0,0,0);
        $to->setTime(23,59,59);
    } else {
        $range = 'day';
    }
}

if ($range !== 'custom') {
    $to = clone $now;
    $to->setTime(23,59,59);

    $from = clone $now;
    if ($range === '7d') {
        $from->modify('-6 days')->setTime(0,0,0);
    } elseif ($range === '30d') {
        $from->modify('-29 days')->setTime(0,0,0);
    } elseif ($range === 'all') {
        $from = new DateTime('2000-01-01 00:00:00');
    } else { // day
        $from->setTime(0,0,0);
    }
}

$fromSql = $from->format('Y-m-d H:i:s');
$toSql   = $to->format('Y-m-d H:i:s');

// UI params
$rowsParam = strtolower(trim($_GET['rows'] ?? '100'));
$rowsLimit = 100;
if (in_array($rowsParam, ['20','50','100','200'], true)) $rowsLimit = (int)$rowsParam;
if ($rowsParam === 'all') $rowsLimit = 1000;

$refreshSeconds = 5;
try {
    $settingsFile = __DIR__ . '/../config/production_settings.json';
    if (is_file($settingsFile)) {
        $cfg = json_decode(file_get_contents($settingsFile), true) ?: [];
        $refreshSeconds = max(2, (int)($cfg['refresh_interval'] ?? 5));
    }
} catch (Throwable $e) { /* ignore */ }

// Idle/line stopped threshold (minutes) from email alerts settings if present
$idleMinutes = 60;
try {
    if (function_exists('sp_email_get_alerts')) {
        $alertsCfg = sp_email_get_alerts();
        if (is_array($alertsCfg) && isset($alertsCfg['timeout_minutes'])) {
            $idleMinutes = max(1, (int)$alertsCfg['timeout_minutes']);
        }
    }
} catch (Throwable $e) { /* ignore */ }

/* ======================================================
   Unified Events Subquery
   - Primary: barcode_scans
   - Secondary: keyence_scans rows not already present in barcode_scans by code
====================================================== */
$eventsSub = "
    (
      SELECT bs.code, bs.source, bs.scanned_at AS event_time, bs.scan_function
      FROM barcode_scans bs
      WHERE bs.scanned_at BETWEEN :from AND :to
      UNION ALL
      SELECT ks.code, 'keyence' AS source, ks.received_at AS event_time, 'case_count' AS scan_function
      FROM keyence_scans ks
      WHERE ks.received_at BETWEEN :from AND :to
        AND NOT EXISTS (SELECT 1 FROM barcode_scans b2 WHERE b2.code = ks.code)
    ) ev
";

// Export CSV
if (isset($_GET['export']) && $_GET['export'] === 'csv') {
    header('Content-Type: text/csv; charset=utf-8');
    header('Content-Disposition: attachment; filename="production_summary.csv"');
    $out = fopen('php://output', 'w');
    fputcsv($out, ['event_time','code','source','scan_function','SKU','variety','packaging','size','grower']);

    $sql = "
      SELECT ev.event_time, ev.code, ev.source, ev.scan_function,
             cc.SKU, cc.variety, cc.packaging, cc.size, cc.grower
      FROM $eventsSub
      LEFT JOIN casecodes cc ON cc.serial = ev.code
      ORDER BY ev.event_time DESC
    ";
    $st = $pdo->prepare($sql);
    $st->execute([':from'=>$fromSql, ':to'=>$toSql]);
    while ($r = $st->fetch(PDO::FETCH_ASSOC)) {
        fputcsv($out, [
            $r['event_time'], $r['code'], $r['source'], $r['scan_function'],
            $r['SKU'], $r['variety'], $r['packaging'], $r['size'], $r['grower']
        ]);
    }
    fclose($out);
    exit;
}

// Manual insert (PC keyboard only)
$flash = '';
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['manual_barcode'])) {
    $code = trim($_POST['manual_barcode']);
    if ($code !== '') {
        $fn = trim($_POST['scan_function'] ?? 'case_count');
        if (!in_array($fn, ['case_count','dump_bins','palletize'], true)) $fn = 'case_count';

        $ins = $pdo->prepare("INSERT IGNORE INTO barcode_scans (code, source, scan_function) VALUES (:c, 'manual', :fn)");
        $ins->execute([':c'=>$code, ':fn'=>$fn]);
        $flash = $ins->rowCount() > 0 ? 'Manual scan saved.' : 'Duplicate barcode ignored.';
    }
    // do not redirect: keep visible flash
}

/* ======================================================
   KPIs
====================================================== */
// Total + per source
$kpi = ['total'=>0,'keyence'=>0,'symcode'=>0,'manual'=>0,'last_time'=>null,'last_code'=>null,'last_source'=>null];
$sql = "
  SELECT
    COUNT(*) AS total,
    SUM(CASE WHEN source='keyence' THEN 1 ELSE 0 END) AS keyence_c,
    SUM(CASE WHEN source='symcode' THEN 1 ELSE 0 END) AS symcode_c,
    SUM(CASE WHEN source='manual' THEN 1 ELSE 0 END) AS manual_c,
    MAX(event_time) AS last_time
  FROM $eventsSub
";
$st = $pdo->prepare($sql);
$st->execute([':from'=>$fromSql, ':to'=>$toSql]);
$row = $st->fetch(PDO::FETCH_ASSOC) ?: [];
$kpi['total']   = sp_int($row['total'] ?? 0);
$kpi['keyence'] = sp_int($row['keyence_c'] ?? 0);
$kpi['symcode'] = sp_int($row['symcode_c'] ?? 0);
$kpi['manual']  = sp_int($row['manual_c'] ?? 0);
$kpi['last_time'] = $row['last_time'] ?? null;

// Last scan row details
$lastRow = null;
$st = $pdo->prepare("
  SELECT ev.event_time, ev.code, ev.source, ev.scan_function
  FROM $eventsSub
  ORDER BY ev.event_time DESC
  LIMIT 1
");
$st->execute([':from'=>$fromSql, ':to'=>$toSql]);
$lastRow = $st->fetch(PDO::FETCH_ASSOC) ?: null;

$kpi['last_code']   = $lastRow['code'] ?? null;
$kpi['last_source'] = $lastRow['source'] ?? null;

$lastAgeSec = null;
$lineStopped = false;
if (!empty($kpi['last_time'])) {
    $ts = strtotime($kpi['last_time']);
    if ($ts !== false) {
        $lastAgeSec = time() - $ts;
        $lineStopped = ($lastAgeSec >= ($idleMinutes * 60));
    }
}

// Rate: boxes/min last 15 minutes (always from unified events, regardless of range)
$ratePerMin = 0.0;
$rateWindowMin = 15;
$st = $pdo->prepare("
  SELECT COUNT(*) AS c
  FROM (
    SELECT bs.id
    FROM barcode_scans bs
    WHERE bs.scanned_at >= NOW() - INTERVAL $rateWindowMin MINUTE
    UNION ALL
    SELECT ks.id
    FROM keyence_scans ks
    WHERE ks.received_at >= NOW() - INTERVAL $rateWindowMin MINUTE
      AND NOT EXISTS (SELECT 1 FROM barcode_scans b2 WHERE b2.code = ks.code)
  ) x
");
$st->execute();
$r = $st->fetch(PDO::FETCH_ASSOC) ?: ['c'=>0];
$ratePerMin = ((int)$r['c']) / max(1, $rateWindowMin);

/* ======================================================
   Charts
====================================================== */
// Stacked chart buckets: hourly if day/custom single-day, else daily
$singleDay = false;
if ($range === 'day') $singleDay = true;
if ($range === 'custom') {
    $singleDay = ($from->format('Y-m-d') === $to->format('Y-m-d'));
}

$bucketExpr = $singleDay ? "DATE_FORMAT(event_time, '%Y-%m-%d %H:00:00')" : "DATE(event_time)";
$bucketLabel = $singleDay ? "Hour" : "Day";

$stack = []; // bucket => ['keyence'=>x,'symcode'=>y,'manual'=>z]
$st = $pdo->prepare("
  SELECT $bucketExpr AS b, source, COUNT(*) AS c
  FROM $eventsSub
  GROUP BY $bucketExpr, source
  ORDER BY b ASC
");
$st->execute([':from'=>$fromSql, ':to'=>$toSql]);
while ($r = $st->fetch(PDO::FETCH_ASSOC)) {
    $b = (string)$r['b'];
    $s = (string)$r['source'];
    if (!isset($stack[$b])) $stack[$b] = ['keyence'=>0,'symcode'=>0,'manual'=>0];
    if (isset($stack[$b][$s])) $stack[$b][$s] = (int)$r['c'];
}
$stackLabels = array_keys($stack);
$stackKeyence = [];
$stackSymcode = [];
$stackManual  = [];
foreach ($stackLabels as $b) {
    $stackKeyence[] = (int)($stack[$b]['keyence'] ?? 0);
    $stackSymcode[] = (int)($stack[$b]['symcode'] ?? 0);
    $stackManual[]  = (int)($stack[$b]['manual'] ?? 0);
}

// Top SKU
$topSku = []; // rows for table
$topSkuLabels = [];
$topSkuTotals = [];
$limitTop = 15;

$st = $pdo->prepare("
  SELECT
    COALESCE(NULLIF(TRIM(cc.SKU), ''), '(n/a)') AS sku,
    COALESCE(NULLIF(TRIM(COALESCE(cc.variety,'')), ''), '(n/a)') AS variety,
    COALESCE(NULLIF(TRIM(COALESCE(cc.packaging,'')), ''), '(n/a)') AS packaging,
    COALESCE(NULLIF(TRIM(COALESCE(cc.size,'')), ''), '(n/a)') AS size,
    COUNT(*) AS total
  FROM $eventsSub
  LEFT JOIN casecodes cc ON cc.serial = ev.code
  GROUP BY sku, variety, packaging, size
  ORDER BY total DESC
  LIMIT $limitTop
");
$st->execute([':from'=>$fromSql, ':to'=>$toSql]);
while ($r = $st->fetch(PDO::FETCH_ASSOC)) {
    $desc = trim(($r['variety'] ?? '') . ' - ' . ($r['packaging'] ?? '') . ' - ' . ($r['size'] ?? ''), ' -');
    if ($desc === '') $desc = '(n/a)';
    $topSku[] = ['sku'=>$r['sku'], 'desc'=>$desc, 'total'=>(int)$r['total']];
    $topSkuLabels[] = $r['sku'] . ' ' . $desc;
    $topSkuTotals[] = (int)$r['total'];
}

// SKU -> Source drilldown counts (for top table)
$skuSource = []; // sku => ['keyence'=>..,'symcode'=>..,'manual'=>..]
if (!empty($topSku)) {
    $skus = array_values(array_unique(array_map(static fn($x) => (string)$x['sku'], $topSku)));
    // Build IN clause
    $in = implode(',', array_fill(0, count($skus), '?'));

    $sql = "
      SELECT COALESCE(NULLIF(TRIM(cc.SKU), ''), '(n/a)') AS sku, ev.source, COUNT(*) AS c
      FROM $eventsSub
      LEFT JOIN casecodes cc ON cc.serial = ev.code
      WHERE COALESCE(NULLIF(TRIM(cc.SKU), ''), '(n/a)') IN ($in)
      GROUP BY sku, ev.source
    ";
    $st = $pdo->prepare($sql);
    $params = [':from'=>$fromSql, ':to'=>$toSql];
    // PDO cannot mix named and positional in same statement reliably; rebuild with positional for from/to too
    $sql2 = "
      SELECT COALESCE(NULLIF(TRIM(cc.SKU), ''), '(n/a)') AS sku, ev.source, COUNT(*) AS c
      FROM (
        SELECT bs.code, bs.source, bs.scanned_at AS event_time, bs.scan_function
        FROM barcode_scans bs
        WHERE bs.scanned_at BETWEEN ? AND ?
        UNION ALL
        SELECT ks.code, 'keyence' AS source, ks.received_at AS event_time, 'case_count' AS scan_function
        FROM keyence_scans ks
        WHERE ks.received_at BETWEEN ? AND ?
          AND NOT EXISTS (SELECT 1 FROM barcode_scans b2 WHERE b2.code = ks.code)
      ) ev
      LEFT JOIN casecodes cc ON cc.serial = ev.code
      WHERE COALESCE(NULLIF(TRIM(cc.SKU), ''), '(n/a)') IN ($in)
      GROUP BY sku, ev.source
    ";
    $st = $pdo->prepare($sql2);
    $bind = [$fromSql, $toSql, $fromSql, $toSql];
    foreach ($skus as $s) $bind[] = $s;
    $st->execute($bind);
    while ($r = $st->fetch(PDO::FETCH_ASSOC)) {
        $sku = (string)$r['sku'];
        if (!isset($skuSource[$sku])) $skuSource[$sku] = ['keyence'=>0,'symcode'=>0,'manual'=>0];
        $src = (string)$r['source'];
        if (isset($skuSource[$sku][$src])) $skuSource[$sku][$src] = (int)$r['c'];
    }
}

/* ======================================================
   Live feed (latest)
====================================================== */
$live = [];
$st = $pdo->prepare("
  SELECT ev.event_time, ev.code, ev.source, ev.scan_function,
         cc.SKU, cc.crop, cc.variety, cc.packaging, cc.size, cc.grower
  FROM $eventsSub
  LEFT JOIN casecodes cc ON cc.serial = ev.code
  ORDER BY ev.event_time DESC
  LIMIT $rowsLimit
");
$st->execute([':from'=>$fromSql, ':to'=>$toSql]);
$live = $st->fetchAll(PDO::FETCH_ASSOC) ?: [];

/* ======================================================
   UI
====================================================== */
include __DIR__ . '/../includes/header.php';
include __DIR__ . '/../includes/sidebar.php';
?>
<div class="container-fluid py-4">
  <div class="d-flex justify-content-between align-items-center flex-wrap gap-2 mb-2">
    <h3 class="mb-0">Production Summary</h3>
    <div class="d-flex gap-2 align-items-center flex-wrap">
      <a class="btn btn-outline-secondary btn-sm" href="/smproduce/pages/settings_production.php">Production Settings</a>
      <a class="btn btn-success btn-sm" href="?<?= http_build_query(array_merge($_GET, ['export'=>'csv'])) ?>">Export CSV</a>
    </div>
  </div>

  <?php if ($flash): ?>
    <div class="alert alert-info py-2 mb-3"><?= sp_h($flash) ?></div>
  <?php endif; ?>

  <!-- Filters -->
  <div class="card mb-3">
    <div class="card-body">
      <form method="get" class="row g-2 align-items-end">
        <div class="col-md-3">
          <label class="form-label">Range</label>
          <select name="range" class="form-select form-select-sm" id="rangeSelect">
            <option value="day"  <?= $range==='day'?'selected':'' ?>>Today</option>
            <option value="7d"   <?= $range==='7d'?'selected':'' ?>>Last 7 days</option>
            <option value="30d"  <?= $range==='30d'?'selected':'' ?>>Last 30 days</option>
            <option value="all"  <?= $range==='all'?'selected':'' ?>>All time</option>
            <option value="custom" <?= $range==='custom'?'selected':'' ?>>Custom (from/to)</option>
          </select>
        </div>

        <div class="col-md-3">
          <label class="form-label">From</label>
          <input type="date" name="from" class="form-control form-control-sm" value="<?= sp_h($from->format('Y-m-d')) ?>">
        </div>
        <div class="col-md-3">
          <label class="form-label">To</label>
          <input type="date" name="to" class="form-control form-control-sm" value="<?= sp_h($to->format('Y-m-d')) ?>">
        </div>

        <div class="col-md-3">
          <label class="form-label">Rows</label>
          <select name="rows" class="form-select form-select-sm">
            <option value="20"  <?= $rowsLimit===20?'selected':'' ?>>20</option>
            <option value="50"  <?= $rowsLimit===50?'selected':'' ?>>50</option>
            <option value="100" <?= $rowsLimit===100?'selected':'' ?>>100</option>
            <option value="200" <?= $rowsLimit===200?'selected':'' ?>>200</option>
            <option value="all" <?= $rowsParam==='all'?'selected':'' ?>>All (max 1000)</option>
          </select>
        </div>

        <div class="col-12 d-flex justify-content-end gap-2">
          <button class="btn btn-primary btn-sm">Apply</button>
          <a class="btn btn-outline-secondary btn-sm" href="production_summary.php">Reset</a>
        </div>
      </form>
      <div class="small text-muted mt-2">
        Auto-refresh every <?= (int)$refreshSeconds ?>s. Line stopped threshold: <?= (int)$idleMinutes ?> minutes.
      </div>
    </div>
  </div>

  <!-- KPI Cards -->
  <div class="row g-3 mb-3">
    <div class="col-md-3">
      <div class="card h-100 shadow-sm">
        <div class="card-body">
          <div class="text-muted small">Total boxes</div>
          <div class="display-6"><?= (int)$kpi['total'] ?></div>
          <div class="small text-muted"><?= sp_h($from->format('Y-m-d')) ?> → <?= sp_h($to->format('Y-m-d')) ?></div>
        </div>
      </div>
    </div>

    <div class="col-md-3">
      <div class="card h-100 shadow-sm">
        <div class="card-body">
          <div class="text-muted small">By source</div>
          <div class="d-flex gap-2 flex-wrap mt-2">
            <span class="badge bg-primary px-3 py-2">Keyence: <?= (int)$kpi['keyence'] ?></span>
            <span class="badge bg-success px-3 py-2">Symcode: <?= (int)$kpi['symcode'] ?></span>
            <span class="badge bg-secondary px-3 py-2">Manual: <?= (int)$kpi['manual'] ?></span>
          </div>
        </div>
      </div>
    </div>

    <div class="col-md-3">
      <div class="card h-100 shadow-sm">
        <div class="card-body">
          <div class="text-muted small">Speed (last <?= (int)$rateWindowMin ?> min)</div>
          <div class="display-6"><?= number_format($ratePerMin, 2) ?></div>
          <div class="small text-muted">boxes/min</div>
        </div>
      </div>
    </div>

    <div class="col-md-3">
      <div class="card h-100 shadow-sm <?= $lineStopped ? 'border border-2 border-danger' : '' ?>">
        <div class="card-body">
          <div class="text-muted small">Line status</div>
          <?php if ($lineStopped): ?>
            <div class="h4 text-danger mb-1">STOPPED</div>
            <div class="small text-muted">Last scan <?= $lastAgeSec !== null ? (int)floor($lastAgeSec/60) . ' min ago' : 'n/a' ?></div>
          <?php else: ?>
            <div class="h4 text-success mb-1">RUNNING</div>
            <div class="small text-muted">Last scan <?= $lastAgeSec !== null ? (int)$lastAgeSec . 's ago' : 'n/a' ?></div>
          <?php endif; ?>
          <?php if ($lastRow): ?>
            <div class="small mt-2">
              <span class="badge bg-<?= sp_badge_class_source((string)$lastRow['source']) ?>"><?= sp_h($lastRow['source']) ?></span>
              <span class="badge bg-<?= sp_badge_class_fn((string)$lastRow['scan_function']) ?>"><?= sp_h($lastRow['scan_function']) ?></span>
              <div class="mt-1"><code><?= sp_h($lastRow['code']) ?></code></div>
            </div>
          <?php endif; ?>
        </div>
      </div>
    </div>
  </div>

  <!-- Scanner inputs -->
  <div class="row g-3 mb-3">
    <div class="col-lg-6">
      <div class="card h-100 shadow-sm">
        <div class="card-header bg-light">
          <strong>Symcode scanner (case count)</strong>
          <div class="small text-muted">Scan here with Symcode. This will be saved as <code>source=symcode</code>.</div>
        </div>
        <div class="card-body">
          <div class="d-flex gap-2">
            <input id="symcodeInput" class="form-control" placeholder="Scan barcode with Symcode..." autocomplete="off">
            <button type="button" class="btn btn-outline-secondary" id="symClearBtn">Clear</button>
          </div>
          <div class="mt-2 d-flex gap-2 align-items-center flex-wrap">
            <span id="symStatus" class="badge bg-secondary">Ready</span>
            <span class="small text-muted">Endpoint: <code>/smproduce/pages/scan_ingest.php</code></span>
          </div>
          <div class="mt-3">
            <button type="button" class="btn btn-sm btn-outline-primary" id="symSimOk">Simulator: symcode OK</button>
            <button type="button" class="btn btn-sm btn-outline-danger" id="symSimDup">Simulator: duplicate</button>
          </div>
        </div>
      </div>
    </div>

    <div class="col-lg-6">
      <div class="card h-100 shadow-sm">
        <div class="card-header bg-light">
          <strong>Manual input (PC keyboard only)</strong>
          <div class="small text-muted">Type with keyboard. Saved as <code>source=manual</code>.</div>
        </div>
        <div class="card-body">
          <form method="post" class="d-flex gap-2">
            <input name="manual_barcode" class="form-control" placeholder="Type barcode..." autocomplete="off">
            <input type="hidden" name="scan_function" value="case_count">
            <button class="btn btn-primary">Add</button>
          </form>
          <div class="small text-muted mt-2">Duplicates are ignored (unique barcode).</div>
        </div>
      </div>
    </div>
  </div>

  <!-- Charts -->
  <div class="row g-3 mb-3">
    <div class="col-lg-7">
      <div class="card shadow-sm h-100">
        <div class="card-header bg-light">
          <strong>Production by source (stacked)</strong>
          <div class="small text-muted"><?= sp_h($bucketLabel) ?> buckets</div>
        </div>
        <div class="card-body" style="height:330px;">
          <canvas id="stackedChart"></canvas>
        </div>
      </div>
    </div>

    <div class="col-lg-5">
      <div class="card shadow-sm h-100">
        <div class="card-header bg-light">
          <strong>Top SKU</strong>
          <div class="small text-muted">Click a row for drill-down (source split).</div>
        </div>
        <div class="card-body">
          <div style="height:260px;">
            <canvas id="topSkuChart"></canvas>
          </div>
          <div class="table-responsive mt-3">
            <table class="table table-sm table-striped mb-0 align-middle">
              <thead>
                <tr>
                  <th>SKU</th>
                  <th class="text-end">Total</th>
                </tr>
              </thead>
              <tbody>
                <?php if (empty($topSku)): ?>
                  <tr><td colspan="2" class="text-center text-muted">No data</td></tr>
                <?php else: ?>
                  <?php foreach ($topSku as $r): ?>
                    <tr class="sku-row" data-sku="<?= sp_h($r['sku']) ?>" style="cursor:pointer">
                      <td>
                        <div class="fw-semibold"><?= sp_h($r['sku']) ?></div>
                        <div class="small text-muted"><?= sp_h($r['desc']) ?></div>
                      </td>
                      <td class="text-end fw-semibold"><?= (int)$r['total'] ?></td>
                    </tr>
                  <?php endforeach; ?>
                <?php endif; ?>
              </tbody>
            </table>
          </div>
        </div>
      </div>
    </div>
  </div>

  <!-- Live feed -->
  <div class="card shadow-sm">
    <div class="card-header bg-light d-flex justify-content-between align-items-center flex-wrap gap-2">
      <strong>Live feed</strong>
      <span class="small text-muted">Latest <?= (int)$rowsLimit ?> rows</span>
    </div>
    <div class="card-body table-responsive">
      <table class="table table-sm table-striped align-middle mb-0">
        <thead>
          <tr>
            <th>Time</th>
            <th>Code</th>
            <th>Source</th>
            <th>Function</th>
            <th>SKU</th>
            <th>Variety</th>
            <th>Packaging</th>
            <th>Size</th>
            <th>Grower</th>
          </tr>
        </thead>
        <tbody>
          <?php if (empty($live)): ?>
            <tr><td colspan="9" class="text-center text-muted">No scans in selected range.</td></tr>
          <?php else: ?>
            <?php foreach ($live as $r): ?>
              <tr>
                <td><?= sp_h($r['event_time']) ?></td>
                <td><code><?= sp_h($r['code']) ?></code></td>
                <td><span class="badge bg-<?= sp_badge_class_source((string)$r['source']) ?>"><?= sp_h($r['source']) ?></span></td>
                <td><span class="badge bg-<?= sp_badge_class_fn((string)$r['scan_function']) ?>"><?= sp_h($r['scan_function']) ?></span></td>
                <td><?= sp_h($r['SKU'] ?? '') ?></td>
                <td><?= sp_h($r['variety'] ?? '') ?></td>
                <td><?= sp_h($r['packaging'] ?? '') ?></td>
                <td><?= sp_h($r['size'] ?? '') ?></td>
                <td><?= sp_h($r['grower'] ?? '') ?></td>
              </tr>
            <?php endforeach; ?>
          <?php endif; ?>
        </tbody>
      </table>
    </div>
  </div>

</div>

<!-- SKU Drilldown Modal -->
<div class="modal fade" id="skuModal" tabindex="-1" aria-hidden="true">
  <div class="modal-dialog modal-dialog-centered modal-lg">
    <div class="modal-content">
      <div class="modal-header">
        <h5 class="modal-title">SKU Drill-down</h5>
        <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
      </div>
      <div class="modal-body">
        <div class="d-flex gap-2 flex-wrap mb-2">
          <span id="skuBadgeKeyence" class="badge bg-primary">Keyence: 0</span>
          <span id="skuBadgeSymcode" class="badge bg-success">Symcode: 0</span>
          <span id="skuBadgeManual"  class="badge bg-secondary">Manual: 0</span>
        </div>
        <div class="small text-muted mb-3" id="skuModalSku"></div>
        <div class="alert alert-light mb-0">
          This drill-down is based on counts by source for the selected SKU within the current date range.
        </div>
      </div>
      <div class="modal-footer">
        <button type="button" class="btn btn-secondary btn-sm" data-bs-dismiss="modal">Close</button>
      </div>
    </div>
  </div>
</div>

<?php include __DIR__ . '/../includes/footer.php'; ?>

<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
<script>
// Auto-refresh
setTimeout(() => location.reload(), <?= (int)$refreshSeconds * 1000 ?>);

// Beep helpers (no external assets)
function beep(freq, ms) {
  try {
    const ctx = new (window.AudioContext || window.webkitAudioContext)();
    const o = ctx.createOscillator();
    const g = ctx.createGain();
    o.frequency.value = freq;
    o.type = 'sine';
    o.connect(g);
    g.connect(ctx.destination);
    o.start();
    g.gain.setValueAtTime(0.08, ctx.currentTime);
    setTimeout(() => { o.stop(); ctx.close(); }, ms);
  } catch(e) {}
}
function beepOk(){ beep(880, 80); }
function beepWarn(){ beep(550, 120); setTimeout(()=>beep(550,120),140); }
function beepErr(){ beep(220, 240); }

// Stacked chart
const stackLabels  = <?= json_encode($stackLabels, JSON_UNESCAPED_UNICODE) ?>;
const stackKeyence = <?= json_encode($stackKeyence, JSON_NUMERIC_CHECK) ?>;
const stackSymcode = <?= json_encode($stackSymcode, JSON_NUMERIC_CHECK) ?>;
const stackManual  = <?= json_encode($stackManual,  JSON_NUMERIC_CHECK) ?>;

(function(){
  const el = document.getElementById('stackedChart');
  if (!el || !stackLabels.length) return;

  new Chart(el.getContext('2d'), {
    type: 'bar',
    data: {
      labels: stackLabels,
      datasets: [
        { label: 'keyence', data: stackKeyence, stack:'s' },
        { label: 'symcode', data: stackSymcode, stack:'s' },
        { label: 'manual',  data: stackManual,  stack:'s' },
      ]
    },
    options: {
      responsive: true,
      maintainAspectRatio: false,
      scales: {
        x: { stacked:true, ticks:{ autoSkip:true, maxTicksLimit: 12 } },
        y: { stacked:true, beginAtZero:true, ticks:{ precision:0 } }
      }
    }
  });
})();

// Top SKU chart
const topSkuLabels = <?= json_encode($topSkuLabels, JSON_UNESCAPED_UNICODE) ?>;
const topSkuTotals = <?= json_encode($topSkuTotals, JSON_NUMERIC_CHECK) ?>;
(function(){
  const el = document.getElementById('topSkuChart');
  if (!el || !topSkuLabels.length) return;

  new Chart(el.getContext('2d'), {
    type: 'bar',
    data: { labels: topSkuLabels, datasets: [{ label: 'boxes', data: topSkuTotals }] },
    options: {
      responsive: true,
      maintainAspectRatio: false,
      scales: {
        x: { ticks:{ autoSkip:true, maxTicksLimit: 6 } },
        y: { beginAtZero:true, ticks:{ precision:0 } }
      }
    }
  });
})();

// SKU drilldown
const skuSource = <?= json_encode($skuSource, JSON_UNESCAPED_UNICODE | JSON_NUMERIC_CHECK) ?>;
(function(){
  const modalEl = document.getElementById('skuModal');
  if (!modalEl) return;

  const skuModal = new bootstrap.Modal(modalEl);
  document.querySelectorAll('.sku-row').forEach(row => {
    row.addEventListener('click', () => {
      const sku = row.getAttribute('data-sku') || '(n/a)';
      const m = skuSource[sku] || {keyence:0,symcode:0,manual:0};

      document.getElementById('skuModalSku').textContent = 'SKU: ' + sku;
      document.getElementById('skuBadgeKeyence').textContent = 'Keyence: ' + (m.keyence || 0);
      document.getElementById('skuBadgeSymcode').textContent = 'Symcode: ' + (m.symcode || 0);
      document.getElementById('skuBadgeManual').textContent  = 'Manual: ' + (m.manual  || 0);
      skuModal.show();
    });
  });
})();

// Symcode ingest (keyboard wedge)
// This avoids "symcode becomes manual" because it does NOT submit the manual form.
(function(){
  const input = document.getElementById('symcodeInput');
  const status = document.getElementById('symStatus');
  const clearBtn = document.getElementById('symClearBtn');

  function setStatus(text, cls){
    status.className = 'badge ' + cls;
    status.textContent = text;
  }

  async function ingest(code, simulate=false){
    code = (code || '').trim();
    if (!code) return;

    setStatus('Sending...', 'bg-secondary');
    try {
      const res = await fetch('/smproduce/pages/scan_ingest.php', {
        method: 'POST',
        headers: {'Content-Type':'application/json'},
        body: JSON.stringify({
          code,
          source: 'symcode',
          scan_function: 'case_count',
          page: 'production_summary',
          dry_run: simulate ? 1 : 0
        })
      });

      const j = await res.json().catch(() => ({}));
      if (j.status === 'ok') {
        setStatus('OK', 'bg-success');
        beepOk();
        if (!simulate) setTimeout(()=>location.reload(), 250);
      } else if (j.status === 'duplicate') {
        setStatus('Duplicate (ignored)', 'bg-warning text-dark');
        beepWarn();
      } else if (j.status === 'blocked') {
        setStatus('BLOCKED', 'bg-danger');
        beepErr();
      } else {
        setStatus('Error', 'bg-danger');
        beepErr();
      }
    } catch(e) {
      setStatus('Endpoint error', 'bg-danger');
      beepErr();
    }
  }

  if (clearBtn) clearBtn.addEventListener('click', ()=>{ input.value=''; input.focus(); });

  if (input) {
    input.addEventListener('keydown', (e)=>{
      if (e.key === 'Enter') {
        e.preventDefault();
        const code = input.value;
        input.value = '';
        ingest(code, false);
      }
    });
    // keep focus for scanners
    setInterval(()=>{ if (document.activeElement !== input) input.focus(); }, 2000);
  }

  // Simulator buttons
  const simOk = document.getElementById('symSimOk');
  const simDup = document.getElementById('symSimDup');
  if (simOk) simOk.addEventListener('click', ()=>ingest('SIM' + Date.now(), false));
  if (simDup) simDup.addEventListener('click', ()=>ingest('SIM_DUPLICATE', false));
})();
</script>
