<?php
/**
 * planeador.php
 * ============================================================
 * BReport · Planeador de producción
 * ------------------------------------------------------------
 * Sección inteligente de planeación basada en inventory_moves.
 *
 * Regla operativa:
 * - Inventario inicial del día = saldo comercial al cierre del día anterior.
 * - Entradas = movimientos IN / ADJ del día en almacenes comerciales.
 * - Salidas = movimientos OUT del día en almacenes comerciales.
 * - Inventario al corte = inicial + entradas - salidas.
 * - Faltante = capacidad configurada - inventario al corte.
 *
 * Almacenes comerciales:
 * - BARRA 150 KILOS = CF1 + CF2.
 * - Bolsas / producto terminado = CF3.
 * - CUB, SOB-CUB, MERMA y APROV-MERMA no son inventario comercial.
 *
 * Esta sección NO mueve inventario. Solo consulta inventory_moves.
 * ============================================================
 */

declare(strict_types=1);

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

require_scope();
ensure_session();

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

$companyId  = (int)($sc['company_id'] ?? 0);
$locationId = (int)($sc['location_id'] ?? 0);

if (!function_exists('h')) {
    function h($s): string { return htmlspecialchars((string)$s, ENT_QUOTES, 'UTF-8'); }
}


function pl_location_timezone(PDO $pdo, int $locationId): string {
    try {
        $st = $pdo->prepare("SELECT timezone FROM locations WHERE id = ? LIMIT 1");
        $st->execute([$locationId]);
        $tz = trim((string)($st->fetchColumn() ?: ''));
        if ($tz !== '') {
            try { new DateTimeZone($tz); return $tz; } catch (Throwable $e) {}
        }
    } catch (Throwable $e) {}
    return 'America/Matamoros';
}

function pl_operational_today(string $tz, int $cutoffHour = 7): string {
    $now = new DateTimeImmutable('now', new DateTimeZone($tz));
    if ((int)$now->format('G') < $cutoffHour) {
        $now = $now->modify('-1 day');
    }
    return $now->format('Y-m-d');
}

function pl_num($n, int $dec = 0): string {
    return number_format((float)$n, $dec, '.', ',');
}

function pl_date(string $key, string $default): string {
    $v = trim((string)($_GET[$key] ?? $default));
    return preg_match('/^\d{4}-\d{2}-\d{2}$/', $v) ? $v : $default;
}

function pl_int(string $key, int $default = 0): int {
    return isset($_GET[$key]) ? (int)$_GET[$key] : $default;
}

function pl_table_exists(PDO $pdo, string $table): bool {
    $st = $pdo->prepare("SELECT COUNT(*) FROM information_schema.tables WHERE table_schema = DATABASE() AND table_name = ?");
    $st->execute([$table]);
    return (int)$st->fetchColumn() > 0;
}

function pl_run(PDO $pdo, string $sql, array $params = []): array {
    $st = $pdo->prepare($sql);
    $st->execute($params);
    return $st->fetchAll(PDO::FETCH_ASSOC);
}

function pl_is_bar(string $sku): bool {
    return strtoupper(trim($sku)) === 'BARRA 150 KILOS';
}

function pl_is_aprovechamiento(string $sku, string $name): bool {
    $txt = strtoupper(trim($sku . ' ' . $name));
    return str_contains($txt, 'APROVECHAMIENTO') && str_contains($txt, 'MERMA');
}

function pl_capacity_for(string $sku, string $name): float {
    $txt = strtoupper(trim($sku . ' ' . $name));
    if (strtoupper(trim($sku)) === 'BARRA 150 KILOS') return 2010;
    if (str_contains($txt, '1/12')) return 900;
    if (str_contains($txt, '1/4')) return 405;
    if (str_contains($txt, 'TRIT')) return 315;
    if (str_contains($txt, '5KG') || str_contains($txt, '5 KG')) return 2520;
    if (str_contains($txt, 'SEVEN')) return 2025;
    if (str_contains($txt, '3KG') || str_contains($txt, '3 KG')) return 2025;
    return 0;
}

function pl_commercial_wh_condition(): string {
    return "(
        (UPPER(p.sku) = 'BARRA 150 KILOS' AND UPPER(COALESCE(w.code,'')) IN ('CF1','CF2'))
        OR
        (UPPER(p.sku) <> 'BARRA 150 KILOS' AND UPPER(COALESCE(w.code,'')) = 'CF3')
    )";
}

function pl_dates_between(string $from, string $to): array {
    $out = [];
    $d = new DateTimeImmutable($from);
    $end = new DateTimeImmutable($to);
    while ($d <= $end) {
        $out[] = $d->format('Y-m-d');
        $d = $d->modify('+1 day');
    }
    return $out;
}

$appTz = pl_location_timezone($pdo, $locationId);
date_default_timezone_set($appTz);
$today = pl_operational_today($appTz, 7);
$dateFrom = pl_date('date_from', $today);
$dateTo   = pl_date('date_to', $today);
if ($dateFrom > $dateTo) { [$dateFrom, $dateTo] = [$dateTo, $dateFrom]; }
$turns = pl_int('turns', 1);
if (!in_array($turns, [1,2,3], true)) $turns = 1;
$productId = pl_int('product_id', 0);
$lookbackDays = pl_int('lookback_days', 7);
if (!in_array($lookbackDays, [3,7,15,30], true)) $lookbackDays = 7;
$action = trim((string)($_GET['action'] ?? ''));

$companyName = '';
$locationName = '';
$st = $pdo->prepare("SELECT name FROM companies WHERE id=? LIMIT 1");
$st->execute([$companyId]);
$companyName = (string)($st->fetchColumn() ?: ('Empresa #' . $companyId));
$st = $pdo->prepare("SELECT name FROM locations WHERE id=? LIMIT 1");
$st->execute([$locationId]);
$locationName = (string)($st->fetchColumn() ?: ('Localidad #' . $locationId));

$products = pl_run($pdo, "
    SELECT id, sku, name, uom
    FROM products
    WHERE company_id = ?
      AND active = 1
      AND (? = 0 OR id = ?)
    ORDER BY FIELD(UPPER(sku),'BARRA 150 KILOS'), sku
", [$companyId, $productId, $productId]);

$productMap = [];
foreach ($products as $p) {
    $sku = (string)$p['sku'];
    $name = (string)$p['name'];
    if (pl_is_aprovechamiento($sku, $name)) continue;
    $pid = (int)$p['id'];
    $productMap[$pid] = [
        'id' => $pid,
        'sku' => $sku,
        'name' => $name,
        'uom' => (string)($p['uom'] ?? 'pz'),
        'capacity' => pl_capacity_for($sku, $name),
    ];
}

/* Inventario inicial al arranque del rango: saldo antes de date_from. */
$initialMap = [];
if ($productMap && pl_table_exists($pdo, 'inventory_moves')) {
    $sql = "
        SELECT im.product_id,
               COALESCE(SUM(CASE
                   WHEN UPPER(im.move_type) IN ('IN','ADJ') THEN im.qty
                   WHEN UPPER(im.move_type) = 'OUT' THEN -im.qty
                   ELSE 0
               END),0) AS qty
        FROM inventory_moves im
        JOIN products p ON p.id = im.product_id
        LEFT JOIN warehouses w ON w.id = im.warehouse_id
        WHERE im.company_id = ?
          AND im.location_id = ?
          AND im.work_date < ?
          AND " . pl_commercial_wh_condition() . "
          AND NOT (
            UPPER(TRIM(p.sku)) = 'APROVECHAMIENTO DE MERMA'
            OR UPPER(TRIM(p.name)) = 'APROVECHAMIENTO DE MERMA'
            OR UPPER(CONCAT(COALESCE(p.sku,''),' ',COALESCE(p.name,''))) LIKE '%APROVECHAMIENTO%MERMA%'
          )
          AND (? = 0 OR im.product_id = ?)
        GROUP BY im.product_id
    ";
    foreach (pl_run($pdo, $sql, [$companyId, $locationId, $dateFrom, $productId, $productId]) as $r) {
        $initialMap[(int)$r['product_id']] = round((float)$r['qty'], 3);
    }
}

/* Movimientos por día dentro del rango. */
$movementsByDateProduct = [];
if ($productMap && pl_table_exists($pdo, 'inventory_moves')) {
    $sql = "
        SELECT im.work_date, im.product_id,
               COALESCE(SUM(CASE WHEN UPPER(im.move_type) IN ('IN','ADJ') THEN im.qty ELSE 0 END),0) AS entradas,
               COALESCE(SUM(CASE WHEN UPPER(im.move_type) = 'OUT' THEN im.qty ELSE 0 END),0) AS salidas
        FROM inventory_moves im
        JOIN products p ON p.id = im.product_id
        LEFT JOIN warehouses w ON w.id = im.warehouse_id
        WHERE im.company_id = ?
          AND im.location_id = ?
          AND im.work_date BETWEEN ? AND ?
          AND " . pl_commercial_wh_condition() . "
          AND NOT (
            UPPER(TRIM(p.sku)) = 'APROVECHAMIENTO DE MERMA'
            OR UPPER(TRIM(p.name)) = 'APROVECHAMIENTO DE MERMA'
            OR UPPER(CONCAT(COALESCE(p.sku,''),' ',COALESCE(p.name,''))) LIKE '%APROVECHAMIENTO%MERMA%'
          )
          AND (? = 0 OR im.product_id = ?)
        GROUP BY im.work_date, im.product_id
        ORDER BY im.work_date, im.product_id
    ";
    foreach (pl_run($pdo, $sql, [$companyId, $locationId, $dateFrom, $dateTo, $productId, $productId]) as $r) {
        $d = (string)$r['work_date'];
        $pid = (int)$r['product_id'];
        $movementsByDateProduct[$d][$pid] = [
            'entradas' => round((float)$r['entradas'], 3),
            'salidas' => round((float)$r['salidas'], 3),
        ];
    }
}

/* Promedio de salidas recientes para priorizar recomendación. */
$avgOutMap = [];
if ($productMap && pl_table_exists($pdo, 'inventory_moves')) {
    $lbStart = (new DateTimeImmutable($dateFrom))->modify('-' . $lookbackDays . ' days')->format('Y-m-d');
    $lbEnd   = (new DateTimeImmutable($dateFrom))->modify('-1 day')->format('Y-m-d');
    $sql = "
        SELECT im.product_id,
               COALESCE(SUM(CASE WHEN UPPER(im.move_type) = 'OUT' THEN im.qty ELSE 0 END),0) AS salidas
        FROM inventory_moves im
        JOIN products p ON p.id = im.product_id
        LEFT JOIN warehouses w ON w.id = im.warehouse_id
        WHERE im.company_id = ?
          AND im.location_id = ?
          AND im.work_date BETWEEN ? AND ?
          AND " . pl_commercial_wh_condition() . "
          AND (? = 0 OR im.product_id = ?)
        GROUP BY im.product_id
    ";
    foreach (pl_run($pdo, $sql, [$companyId, $locationId, $lbStart, $lbEnd, $productId, $productId]) as $r) {
        $avgOutMap[(int)$r['product_id']] = round(((float)$r['salidas']) / max(1, $lookbackDays), 3);
    }
}

$rows = [];
$runningStock = [];
foreach ($productMap as $pid => $p) {
    $runningStock[$pid] = (float)($initialMap[$pid] ?? 0.0);
}

foreach (pl_dates_between($dateFrom, $dateTo) as $d) {
    foreach ($productMap as $pid => $p) {
        $initial = round((float)$runningStock[$pid], 3);
        $ent = (float)($movementsByDateProduct[$d][$pid]['entradas'] ?? 0.0);
        $out = (float)($movementsByDateProduct[$d][$pid]['salidas'] ?? 0.0);
        $current = round($initial + $ent - $out, 3);
        $capacity = (float)$p['capacity'];
        $missing = $capacity > 0 ? max(0.0, round($capacity - $current, 3)) : 0.0;
        $avgOut = (float)($avgOutMap[$pid] ?? 0.0);
        $suggested = $capacity > 0 ? $missing : 0.0;
        $perShift = $turns > 0 ? round($suggested / $turns, 3) : $suggested;
        $score = $missing + ($avgOut * 0.35);
        $priority = 'OK';
        if ($capacity > 0) {
            $pct = $capacity > 0 ? ($current / $capacity) * 100.0 : 0.0;
            if ($pct < 70 || $missing >= ($capacity * 0.25)) $priority = 'ALTA';
            elseif ($pct < 90 || $avgOut > 0) $priority = 'MEDIA';
        } else {
            $pct = 0.0;
            $priority = 'SIN CAP.';
        }

        $rows[] = [
            'date' => $d,
            'product_id' => $pid,
            'sku' => $p['sku'],
            'name' => $p['name'],
            'uom' => $p['uom'],
            'initial' => $initial,
            'entries' => round($ent, 3),
            'current' => $current,
            'outs' => round($out, 3),
            'capacity' => $capacity,
            'missing' => $missing,
            'avg_out' => $avgOut,
            'suggested' => $suggested,
            'per_shift' => $perShift,
            'turns' => $turns,
            'priority' => $priority,
            'score' => $score,
            'pct' => $capacity > 0 ? min(100.0, round(($current / $capacity) * 100.0, 1)) : 0.0,
        ];
        $runningStock[$pid] = $current;
    }
}

/* Plan del último día filtrado, ordenado por prioridad / faltante. */
$planRows = array_values(array_filter($rows, fn($r) => $r['date'] === $dateTo && (float)$r['capacity'] > 0));
usort($planRows, function($a, $b) {
    if ((float)$b['score'] === (float)$a['score']) return strcmp((string)$a['sku'], (string)$b['sku']);
    return ((float)$b['score'] <=> (float)$a['score']);
});

$totalCapacity = array_sum(array_map(fn($r)=>(float)$r['capacity'], $planRows));
$totalCurrent  = array_sum(array_map(fn($r)=>(float)$r['current'], $planRows));
$totalMissing  = array_sum(array_map(fn($r)=>(float)$r['missing'], $planRows));
$totalSuggested = array_sum(array_map(fn($r)=>(float)$r['suggested'], $planRows));
$globalOcc = $totalCapacity > 0 ? min(100.0, round(($totalCurrent / $totalCapacity) * 100.0, 1)) : 0.0;

if ($action === 'csv') {
    $fileName = 'planeador_' . $dateFrom . '_a_' . $dateTo . '.csv';
    header('Content-Type: text/csv; charset=utf-8');
    header('Content-Disposition: attachment; filename="' . $fileName . '"');
    $out = fopen('php://output', 'w');
    fputcsv($out, ['Fecha','Articulo','Descripcion','Inv inicial','Entradas','Inv al corte','Salidas','Capacidad','Faltante','Prom salidas','Sugerido producir','Turnos','Por turno','Prioridad']);
    foreach ($rows as $r) {
        fputcsv($out, [
            $r['date'], $r['sku'], $r['name'], $r['initial'], $r['entries'], $r['current'], $r['outs'], $r['capacity'], $r['missing'], $r['avg_out'], $r['suggested'], $r['turns'], $r['per_shift'], $r['priority']
        ]);
    }
    fclose($out);
    exit;
}

$csvUrl = '?' . http_build_query([
    'action'=>'csv', 'date_from'=>$dateFrom, 'date_to'=>$dateTo, 'turns'=>$turns, 'product_id'=>$productId, 'lookback_days'=>$lookbackDays
]);
?>
<!doctype html>
<html lang="es">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>BReport · Planeador</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet">
<link href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.3/font/bootstrap-icons.min.css" rel="stylesheet">
<style>
:root{--bg:#f6f8fc;--card:#fff;--line:#dbe5f1;--text:#0f172a;--muted:#64748b;--blue:#0b3a75;--blue2:#2563eb;--green:#059669;--red:#dc2626;--gold:#d97706;--shadow:0 18px 42px rgba(15,23,42,.10);--radius:22px}
*{box-sizing:border-box}body{font-family:Inter,system-ui,-apple-system,"Segoe UI",Arial,sans-serif;background:radial-gradient(circle at 12% 10%,rgba(37,99,235,.12),transparent 24%),linear-gradient(135deg,#f8fafc 0%,#eef4fb 100%);color:var(--text);min-height:100vh}.topbar{background:#0f3b66;color:white;box-shadow:0 10px 28px rgba(15,23,42,.12);position:sticky;top:0;z-index:1000}.brand-title{font-weight:900;font-size:1.25rem}.brand-sub{font-size:.83rem;opacity:.9}.shell{max-width:1680px;margin:0 auto;padding:24px 16px 40px}.glass{background:var(--card);border:1px solid var(--line);border-radius:var(--radius);box-shadow:var(--shadow)}.panel-pad{padding:22px}.muted{color:var(--muted)}.btn-soft{border-radius:15px;font-weight:800}.btn-primary-soft{background:linear-gradient(135deg,#2563eb,#0ea5e9);color:#fff;border:0}.toolbar-btn{background:#fff;border:1px solid #cbd5e1;color:#10243e;border-radius:14px;font-weight:800}.form-control,.form-select{border-radius:15px;min-height:45px;border:1px solid #cbd5e1}.form-label{font-weight:800;color:#334155}.kpi{border:1px solid var(--line);border-radius:20px;background:linear-gradient(180deg,#fff,#f8fbff);padding:18px;height:100%}.kpi .lbl{font-size:.85rem;color:#64748b;font-weight:800}.kpi .val{font-size:1.75rem;font-weight:900;color:#0b3a75}.kpi .note{font-size:.82rem;color:#64748b}.table-wrap{border:1px solid var(--line);border-radius:18px;overflow:auto;background:#fff}.table{margin:0}.table thead th{background:#eaf2ff;color:#0f172a;font-weight:900;white-space:nowrap;position:sticky;top:0;z-index:2}.table td{vertical-align:middle}.num{text-align:right;font-variant-numeric:tabular-nums;font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace}.text-stock{color:#0b5ed7!important;font-weight:900}.text-in{color:#00884f!important;font-weight:900}.text-out{color:#e11d2e!important;font-weight:900}.badge-priority{border-radius:999px;padding:.42rem .7rem;font-weight:900}.prio-ALTA{background:#fee2e2;color:#991b1b;border:1px solid #fecaca}.prio-MEDIA{background:#fef3c7;color:#92400e;border:1px solid #fde68a}.prio-OK{background:#dcfce7;color:#166534;border:1px solid #bbf7d0}.prio-SIN{background:#e2e8f0;color:#475569;border:1px solid #cbd5e1}.small-note{border:1px solid #fed7aa;background:#fff7ed;color:#9a3412;padding:.75rem 1rem;border-radius:16px;font-weight:800}.progress{height:10px;border-radius:999px}.progress-bar{border-radius:999px}@media(max-width:768px){.panel-pad{padding:16px}.kpi .val{font-size:1.35rem}.table{font-size:.86rem}.brand-title{font-size:1.05rem}}@media print{.topbar,.no-print,.filters{display:none!important}.shell{padding:0}.glass{box-shadow:none;border:0}.table thead th{position:static}.page-break{break-before:page}}
</style>
</head>
<body>
<nav class="navbar topbar">
  <div class="container-fluid px-3 px-lg-4">
    <div>
      <div class="brand-title">BReport · Planeador</div>
      <div class="brand-sub">Plan de producción sugerido por inventario inicial, entradas, salidas y capacidad</div>
    </div>
    <div class="ms-auto d-flex gap-2 flex-wrap no-print">
      <a class="btn btn-light btn-sm fw-bold" href="almacen_salidas.php"><i class="bi bi-arrow-left me-1"></i>Almacén</a>
      <a class="btn btn-outline-light btn-sm fw-bold" href="dashboard.php">Dashboard</a>
    </div>
  </div>
</nav>

<div class="shell">
  <div class="glass panel-pad mb-4 filters">
    <div class="d-flex justify-content-between gap-3 flex-wrap align-items-start mb-3">
      <div>
        <h2 class="fw-black mb-1"><i class="bi bi-calendar2-week text-primary me-2"></i>Planeador de producción</h2>
        <div class="muted"><?= h($companyName) ?> · <?= h($locationName) ?></div>
      </div>
    </div>
    <form class="row g-3 align-items-end" method="get">
      <div class="col-6 col-md-2"><label class="form-label">Fecha inicial</label><input class="form-control" type="date" name="date_from" value="<?= h($dateFrom) ?>"></div>
      <div class="col-6 col-md-2"><label class="form-label">Fecha final</label><input class="form-control" type="date" name="date_to" value="<?= h($dateTo) ?>"></div>
      <div class="col-12 col-md-3"><label class="form-label">Artículo</label><select class="form-select" name="product_id"><option value="0">Todos los artículos comerciales</option><?php foreach ($productMap as $p): ?><option value="<?= (int)$p['id'] ?>" <?= (int)$p['id'] === $productId ? 'selected' : '' ?>><?= h($p['sku'] . ' · ' . $p['name']) ?></option><?php endforeach; ?></select></div>
      <div class="col-6 col-md-2"><label class="form-label">Turnos a correr</label><select class="form-select" name="turns"><?php foreach ([1,2,3] as $t): ?><option value="<?= $t ?>" <?= $turns === $t ? 'selected' : '' ?>><?= $t ?> turno<?= $t > 1 ? 's' : '' ?></option><?php endforeach; ?></select></div>
      <div class="col-6 col-md-1"><label class="form-label">Promedio</label><select class="form-select" name="lookback_days"><?php foreach ([3,7,15,30] as $d): ?><option value="<?= $d ?>" <?= $lookbackDays === $d ? 'selected' : '' ?>><?= $d ?>d</option><?php endforeach; ?></select></div>
      <div class="col-12 col-md-2"><button class="btn btn-primary-soft btn-soft w-100" type="submit"><i class="bi bi-search me-1"></i>Actualizar</button></div>
    </form>
    <div class="d-flex gap-2 flex-wrap mt-3">
      <a class="btn toolbar-btn" href="<?= h($csvUrl) ?>"><i class="bi bi-download me-1"></i>Descargar CSV</a>
      <button class="btn toolbar-btn" onclick="window.print()" type="button"><i class="bi bi-printer me-1"></i>Imprimir / PDF</button>
    </div>
  </div>

  <div class="row g-3 mb-4">
    <div class="col-12 col-md-3"><div class="kpi"><div class="lbl">Capacidad total</div><div class="val num"><?= pl_num($totalCapacity) ?></div><div class="note">Artículos con capacidad configurada</div></div></div>
    <div class="col-12 col-md-3"><div class="kpi"><div class="lbl">Inventario al corte</div><div class="val num text-stock"><?= pl_num($totalCurrent) ?></div><div class="note">Saldo comercial al <?= h($dateTo) ?></div></div></div>
    <div class="col-12 col-md-3"><div class="kpi"><div class="lbl">Faltante para llenar</div><div class="val num text-out"><?= pl_num($totalMissing) ?></div><div class="note">Capacidad - inventario al corte</div></div></div>
    <div class="col-12 col-md-3"><div class="kpi"><div class="lbl">Ocupación global</div><div class="val num"><?= pl_num($globalOcc, 1) ?>%</div><div class="note">Disponible contra capacidad</div></div></div>
  </div>

  <div class="glass panel-pad mb-4">
    <div class="d-flex justify-content-between gap-3 flex-wrap mb-3">
      <div>
        <h3 class="fw-bold mb-1">Plan recomendado para producción</h3>

      </div>
      <span class="badge text-bg-primary align-self-start">Distribuido en <?= (int)$turns ?> turno<?= $turns > 1 ? 's' : '' ?></span>
    </div>
    <div class="table-wrap">
      <table class="table table-hover align-middle">
        <thead><tr><th>Prioridad</th><th>Artículo</th><th class="num">Capacidad</th><th class="num">Al corte</th><th class="num">Faltante</th><th class="num">Prom. salidas <?= (int)$lookbackDays ?>d</th><th class="num">Sugerido producir</th><th class="num">Por turno</th><th>Ocupación</th></tr></thead>
        <tbody>
        <?php if (!$planRows): ?>
          <tr><td colspan="9" class="text-center text-muted py-4">Sin artículos comerciales para planear.</td></tr>
        <?php else: foreach ($planRows as $r): ?>
          <?php $prioClass = $r['priority'] === 'SIN CAP.' ? 'prio-SIN' : 'prio-' . $r['priority']; ?>
          <tr>
            <td><span class="badge-priority <?= h($prioClass) ?>"><?= h($r['priority']) ?></span></td>
            <td><b><?= h($r['sku']) ?></b><br><span class="muted small"><?= h($r['name']) ?></span></td>
            <td class="num"><?= pl_num($r['capacity']) ?></td>
            <td class="num text-stock"><?= pl_num($r['current']) ?></td>
            <td class="num text-out"><?= pl_num($r['missing']) ?></td>
            <td class="num"><?= pl_num($r['avg_out'], 1) ?></td>
            <td class="num fw-bold"><?= pl_num($r['suggested']) ?></td>
            <td class="num fw-bold"><?= pl_num($r['per_shift']) ?></td>
            <td style="min-width:150px"><div class="d-flex justify-content-between small"><span><?= pl_num($r['pct'],1) ?>%</span></div><div class="progress"><div class="progress-bar" style="width:<?= (float)$r['pct'] ?>%"></div></div></td>
          </tr>
        <?php endforeach; endif; ?>
        </tbody>
      </table>
    </div>
  </div>

  <div class="glass panel-pad">
    <div class="d-flex justify-content-between gap-3 flex-wrap mb-3">
      <div>
        <h3 class="fw-bold mb-1">Detalle diario de inventario</h3>
      </div>
      <span class="badge text-bg-light border">Rango: <?= h($dateFrom) ?> a <?= h($dateTo) ?></span>
    </div>
    <div class="table-wrap">
      <table class="table table-hover align-middle">
        <thead><tr><th>Fecha</th><th>Artículo</th><th class="num">Inv. inicial</th><th class="num">Entradas</th><th class="num">Inv. al corte</th><th class="num">Salidas</th><th class="num">Capacidad</th><th class="num">Faltante</th><th class="num">Por turno</th></tr></thead>
        <tbody>
        <?php if (!$rows): ?>
          <tr><td colspan="9" class="text-center text-muted py-4">Sin datos para mostrar.</td></tr>
        <?php else: foreach ($rows as $r): ?>
          <tr>
            <td class="fw-bold"><?= h($r['date']) ?></td>
            <td><b><?= h($r['sku']) ?></b><br><span class="muted small"><?= h($r['name']) ?></span></td>
            <td class="num"><?= pl_num($r['initial']) ?></td>
            <td class="num text-in"><?= pl_num($r['entries']) ?></td>
            <td class="num text-stock"><?= pl_num($r['current']) ?></td>
            <td class="num text-out"><?= pl_num($r['outs']) ?></td>
            <td class="num"><?= pl_num($r['capacity']) ?></td>
            <td class="num fw-bold"><?= pl_num($r['missing']) ?></td>
            <td class="num"><?= pl_num($r['per_shift']) ?></td>
          </tr>
        <?php endforeach; endif; ?>
        </tbody>
      </table>
    </div>
  </div>

</div>
</body>
</html>
