<?php
/**
 * reportes.php
 * ============================================================
 * BReport · REPORTES · Hielo Barra
 * ------------------------------------------------------------
 * Dashboards de Producción, Calidad y Recargas / Capacidad.
 * - Diseño claro alineado a Almacén.
 * - Gráficas solicitadas en Dashboard.pdf.
 * - Capacidad por presentación vs disponible en almacén.
 * ============================================================
 */

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

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

/* ============================================================
 * Helpers
 * ============================================================ */
function rpt_num0($n): string { return number_format((float)$n, 0); }
function rpt_num2($n): string { return number_format((float)$n, 2); }
function rpt_num3($n): string { return number_format((float)$n, 3); }
function rpt_pct_value($num, $den): float {
    $n = (float)$num; $d = (float)$den;
    return $d > 0 ? round(($n / $d) * 100, 2) : 0.0;
}
function rpt_get_int(string $key, int $default = 0): int { return isset($_GET[$key]) ? (int)$_GET[$key] : $default; }
function rpt_get_str(string $key, string $default = ''): string { return isset($_GET[$key]) ? trim((string)$_GET[$key]) : $default; }
function rpt_normalize_date(string $date, string $fallback): string { return preg_match('/^\d{4}-\d{2}-\d{2}$/', $date) ? $date : $fallback; }
function rpt_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 rpt_column_exists(PDO $pdo, string $table, string $column): bool {
    $st = $pdo->prepare("SELECT COUNT(*) FROM information_schema.columns WHERE table_schema = DATABASE() AND table_name = ? AND column_name = ?");
    $st->execute([$table, $column]);
    return (int)$st->fetchColumn() > 0;
}
function rpt_date_label(string $date): string {
    $ts = strtotime($date);
    return $ts ? date('d/m', $ts) : $date;
}
function rpt_run(PDO $pdo, string $sql, array $params = []): array {
    try {
        $st = $pdo->prepare($sql);
        $st->execute($params);
        return $st->fetchAll(PDO::FETCH_ASSOC);
    } catch (Throwable $e) {
        return [];
    }
}
function rpt_one(PDO $pdo, string $sql, array $params = []): array {
    try {
        $st = $pdo->prepare($sql);
        $st->execute($params);
        $r = $st->fetch(PDO::FETCH_ASSOC);
        return $r ?: [];
    } catch (Throwable $e) {
        return [];
    }
}
function rpt_is_bar_sku(string $sku): bool { return mb_strtoupper(trim($sku)) === 'BARRA 150 KILOS'; }
function rpt_is_commercial_bar_warehouse(string $code): bool { return in_array(mb_strtoupper(trim($code)), ['CF1','CF2'], true); }

/* ============================================================
 * Filtros
 * ============================================================ */
$scopeCompanyId  = (int)($sc['company_id'] ?? 0);
$scopeLocationId = (int)($sc['location_id'] ?? 0);

$today     = date('Y-m-d');
$dateFromD = $today;
$dateToD   = $today;

$companyId  = rpt_get_int('company_id', $scopeCompanyId > 0 ? $scopeCompanyId : 1);
$locationId = rpt_get_int('location_id', $scopeLocationId);
$productId  = rpt_get_int('product_id', 0);
$dateFrom   = rpt_normalize_date(rpt_get_str('date_from', $dateFromD), $dateFromD);
$dateTo     = rpt_normalize_date(rpt_get_str('date_to', $dateToD), $dateToD);
if ($dateFrom > $dateTo) { [$dateFrom, $dateTo] = [$dateTo, $dateFrom]; }

/* ============================================================
 * Catálogos
 * ============================================================ */
$companies = rpt_run($pdo, "SELECT id, name, code FROM companies WHERE active = 1 ORDER BY name");
$locations = rpt_run($pdo, "SELECT id, name, code FROM locations WHERE active = 1 AND (? = 0 OR company_id = ?) ORDER BY name", [$companyId, $companyId]);
$products  = rpt_run($pdo, "SELECT id, sku, name FROM products WHERE active = 1 AND (? = 0 OR company_id = ?) ORDER BY name", [$companyId, $companyId]);

$selectedCompanyName = 'Todas';
$selectedCompanyCode = '';
foreach ($companies as $c) {
    if ((int)$c['id'] === $companyId) { $selectedCompanyName = (string)$c['name']; $selectedCompanyCode = (string)$c['code']; break; }
}
$selectedLocationName = 'Todas';
foreach ($locations as $l) {
    if ((int)$l['id'] === $locationId) { $selectedLocationName = (string)$l['name']; break; }
}

/* ============================================================
 * Producción general
 * ============================================================ */
$prodKpi = rpt_one($pdo, "
    SELECT COALESCE(SUM(total_prod_qty),0) total_prod_qty,
           COALESCE(SUM(target_total),0) total_target_qty,
           COALESCE(SUM(diff_qty),0) total_diff_qty,
           COUNT(*) total_days
    FROM production_day
    WHERE company_id = ? AND prod_date BETWEEN ? AND ?
      AND (? = 0 OR location_id = ?)
", [$companyId, $dateFrom, $dateTo, $locationId, $locationId]);

$totalProd   = (float)($prodKpi['total_prod_qty'] ?? 0);
$totalTarget = (float)($prodKpi['total_target_qty'] ?? 0);
$compliancePct = rpt_pct_value($totalProd, $totalTarget);

/* Producción diaria de barra 150 kg: se toma production_day como dashboard principal de barras */
$dailyRows = rpt_run($pdo, "
    SELECT prod_date, COALESCE(SUM(total_prod_qty),0) prod_qty, COALESCE(SUM(target_total),0) target_qty
    FROM production_day
    WHERE company_id = ? AND prod_date BETWEEN ? AND ?
      AND (? = 0 OR location_id = ?)
    GROUP BY prod_date
    ORDER BY prod_date ASC
", [$companyId, $dateFrom, $dateTo, $locationId, $locationId]);

/* ============================================================
 * Merma / scrap
 * ============================================================ */
$warehouseMermaTable = rpt_table_exists($pdo, 'warehouse_merma_entries');
$prodMermaDaily = rpt_run($pdo, "
    SELECT qe.work_date, COALESCE(SUM(qe.qty),0) qty
    FROM quality_entries qe
    WHERE qe.company_id = ? AND qe.work_date BETWEEN ? AND ?
      AND (? = 0 OR qe.location_id = ?)
      AND (? = 0 OR qe.product_id = ?)
      AND qe.concept_type IN ('MERMA','SCRAP')
      " . ($warehouseMermaTable ? "AND qe.id NOT IN (SELECT quality_entry_id FROM warehouse_merma_entries WHERE quality_entry_id IS NOT NULL)" : "") . "
    GROUP BY qe.work_date
    ORDER BY qe.work_date ASC
", [$companyId, $dateFrom, $dateTo, $locationId, $locationId, $productId, $productId]);

$whMermaDaily = $warehouseMermaTable ? rpt_run($pdo, "
    SELECT work_date, COALESCE(SUM(qty),0) qty
    FROM warehouse_merma_entries
    WHERE company_id = ? AND work_date BETWEEN ? AND ?
      AND (? = 0 OR location_id = ?)
      AND (? = 0 OR product_id = ?)
    GROUP BY work_date
    ORDER BY work_date ASC
", [$companyId, $dateFrom, $dateTo, $locationId, $locationId, $productId, $productId]) : [];

$prodMermaByDate = [];
foreach ($prodMermaDaily as $r) { $prodMermaByDate[(string)$r['work_date']] = (float)$r['qty']; }
$whMermaByDate = [];
foreach ($whMermaDaily as $r) { $whMermaByDate[(string)$r['work_date']] = (float)$r['qty']; }

$allDates = [];
foreach ($dailyRows as $r) { $allDates[(string)$r['prod_date']] = true; }
foreach ($prodMermaByDate as $d => $_) { $allDates[$d] = true; }
foreach ($whMermaByDate as $d => $_) { $allDates[$d] = true; }
ksort($allDates);

$totalMerma = array_sum($prodMermaByDate) + array_sum($whMermaByDate);
$mermaPct = rpt_pct_value($totalMerma, $totalProd);
$litersPerBar = 150;
$litersLost = $totalMerma * $litersPerBar;

/* ============================================================
 * Calidad: monitor y salmuera
 * ============================================================ */
function rpt_quality_series(PDO $pdo, int $companyId, int $locationId, string $dateFrom, string $dateTo, string $kind): array {
    /*
     * Las gráficas de Calidad no dependen de artículo/presentación.
     * El query anterior enviaba parámetros extra de product_id que no existían
     * como placeholders en SQL; PDO lanzaba error y rpt_run() devolvía []
     * silenciosamente, por eso las gráficas aparecían sin datos.
     */
    if (!rpt_table_exists($pdo, 'quality_monitor_readings') || !rpt_table_exists($pdo, 'quality_monitor_points')) {
        return [];
    }

    $wherePoint = "";
    if ($kind === 'cub') {
        $wherePoint = "AND (UPPER(COALESCE(qmp.point_code,'')) LIKE '%CUB%' OR UPPER(COALESCE(qmp.point_name,'')) LIKE '%CUBIC%')";
    } elseif ($kind === 'tds') {
        $wherePoint = "AND (UPPER(COALESCE(qmp.point_type,'')) = 'PPM' OR UPPER(COALESCE(qmp.point_code,'')) LIKE '%PPM%' OR UPPER(COALESCE(qmp.point_name,'')) LIKE '%TDS%' OR UPPER(COALESCE(qmp.point_name,'')) LIKE '%AGUA%')";
    } elseif ($kind === 'cf') {
        $wherePoint = "AND (UPPER(COALESCE(qmp.point_code,'')) LIKE 'CF%' OR UPPER(COALESCE(qmp.point_name,'')) LIKE '%FRIO%' OR UPPER(COALESCE(qmp.point_name,'')) LIKE '%FRÍO%')";
    }

    return rpt_run($pdo, "
        SELECT qmr.work_date, qmp.point_name, AVG(qmr.reading_value) value,
               MIN(qmp.min_allowed) min_allowed, MAX(qmp.max_allowed) max_allowed,
               MIN(qmp.ok_min) ok_min, MAX(qmp.ok_max) ok_max
        FROM quality_monitor_readings qmr
        JOIN quality_monitor_points qmp ON qmp.id = qmr.point_id
        WHERE qmr.company_id = ? AND qmr.work_date BETWEEN ? AND ?
          AND (? = 0 OR qmr.location_id = ?)
          $wherePoint
        GROUP BY qmr.work_date, qmp.point_name
        ORDER BY qmr.work_date ASC, qmp.point_name ASC
    ", [$companyId, $dateFrom, $dateTo, $locationId, $locationId]);
}
$qualityCub = rpt_quality_series($pdo, $companyId, $locationId, $dateFrom, $dateTo, 'cub');
$qualityTds = rpt_quality_series($pdo, $companyId, $locationId, $dateFrom, $dateTo, 'tds');
$qualityCf  = rpt_quality_series($pdo, $companyId, $locationId, $dateFrom, $dateTo, 'cf');
$qualityBrine = rpt_table_exists($pdo, 'quality_brine_readings') ? rpt_run($pdo, "
    SELECT qbr.work_date, qbt.tank_name AS point_name, AVG(qbr.brine_degree) value
    FROM quality_brine_readings qbr
    LEFT JOIN quality_brine_tanks qbt ON qbt.id = qbr.tank_id
    WHERE qbr.company_id = ? AND qbr.work_date BETWEEN ? AND ?
      AND (? = 0 OR qbr.location_id = ?)
    GROUP BY qbr.work_date, qbt.tank_name
    ORDER BY qbr.work_date ASC, qbt.tank_name ASC
", [$companyId, $dateFrom, $dateTo, $locationId, $locationId]) : [];

/* ============================================================
 * Inventario disponible y capacidad por presentación
 * ============================================================ */
function rpt_inventory_snapshot(PDO $pdo, int $companyId, int $locationId): array {
    /**
     * Inventario real para Reportes.
     * ------------------------------------------------------------
     * Regla oficial:
     * - inventory_moves es la única fuente de inventario.
     * - IN / ADJ suman.
     * - OUT resta.
     * - BARRA 150 KILOS disponible comercial = CF1 + CF2.
     * - Bolsas / producto terminado disponible comercial = CF3.
     * - CUB, MERMA, APROV-MERMA, SOB-CUB y SIN-WH son trazabilidad/proceso,
     *   no disponibilidad comercial para capacidad.
     * - No se ocultan negativos. Si hay descuadre, Reportes debe mostrarlo.
     */
    $products = rpt_run($pdo, "
        SELECT id, sku, name, uom
        FROM products
        WHERE company_id = ? AND active = 1
        ORDER BY sku
    ", [$companyId]);

    $rows = [];
    foreach ($products as $p) {
        $pid = (int)$p['id'];
        $rows[$pid] = [
            'product_id' => $pid,
            'sku' => (string)$p['sku'],
            'name' => (string)$p['name'],
            'uom' => (string)$p['uom'],
            // Campos conservados por compatibilidad visual del reporte.
            'prod_cf1' => 0.0,
            'prod_cf2' => 0.0,
            'prod_cf3' => 0.0,
            'prod_cub' => 0.0,
            'prod_merma' => 0.0,
            'prod_aprov' => 0.0,
            'prod_sobcub' => 0.0,
            'prod_total' => 0.0,
            'cubing_in' => 0.0,
            'quality_out' => 0.0,
            'manual_in' => 0.0,
            'manual_out' => 0.0,
            'physical_total' => 0.0,
            'on_hand' => 0.0,
        ];
    }

    $whRows = rpt_run($pdo, "
        SELECT id, code
        FROM warehouses
        WHERE company_id = ?
          AND (? = 0 OR location_id = ?)
          AND active = 1
    ", [$companyId, $locationId, $locationId]);
    $whMap = [];
    foreach ($whRows as $w) {
        $whMap[(int)$w['id']] = strtoupper(trim((string)$w['code']));
    }

    $moveRows = rpt_run($pdo, "
        SELECT product_id, move_type, warehouse_id, SUM(qty) qty
        FROM inventory_moves
        WHERE company_id = ?
          AND (? = 0 OR location_id = ?)
        GROUP BY product_id, UPPER(move_type), warehouse_id
    ", [$companyId, $locationId, $locationId]);

    foreach ($moveRows as $r) {
        $pid = (int)$r['product_id'];
        if (!isset($rows[$pid])) continue;

        $qty = (float)$r['qty'];
        $typ = strtoupper(trim((string)$r['move_type']));
        $wid = (int)($r['warehouse_id'] ?? 0);
        $code = $whMap[$wid] ?? '';

        if ($typ === 'IN' || $typ === 'ADJ') {
            $signed = $qty;
            $rows[$pid]['manual_in'] += $qty;
        } elseif ($typ === 'OUT') {
            $signed = -$qty;
            $rows[$pid]['manual_out'] += $qty;
        } else {
            continue;
        }

        // Total físico real por producto, incluyendo almacenes internos.
        $rows[$pid]['physical_total'] += $signed;

        // Buckets de almacén para trazabilidad y capacidad comercial.
        if ($code === 'CF1') $rows[$pid]['prod_cf1'] += $signed;
        elseif ($code === 'CF2') $rows[$pid]['prod_cf2'] += $signed;
        elseif ($code === 'CF3') {
            $rows[$pid]['prod_cf3'] += $signed;
            $rows[$pid]['cubing_in'] += $signed;
        }
        elseif ($code === 'CUB') $rows[$pid]['prod_cub'] += $signed;
        elseif ($code === 'MERMA') $rows[$pid]['prod_merma'] += $signed;
        elseif ($code === 'APROV-MERMA') $rows[$pid]['prod_aprov'] += $signed;
        elseif ($code === 'SOB-CUB') $rows[$pid]['prod_sobcub'] += $signed;
    }

    foreach ($rows as &$r) {
        if (rpt_is_bar_sku((string)$r['sku'])) {
            $r['on_hand'] = (float)$r['prod_cf1'] + (float)$r['prod_cf2'];
        } else {
            $r['on_hand'] = (float)$r['prod_cf3'];
        }

        // Alias existente usado por vistas antiguas.
        $r['prod_total'] = (float)$r['physical_total'];

        foreach (['prod_cf1','prod_cf2','prod_cf3','prod_cub','prod_merma','prod_aprov','prod_sobcub','prod_total','cubing_in','quality_out','manual_in','manual_out','physical_total','on_hand'] as $k) {
            $r[$k] = round((float)$r[$k], 3);
        }
    }
    unset($r);

    return array_values($rows);
}

$inventoryRowsAll = rpt_inventory_snapshot($pdo, $companyId, $locationId);
$capacityDefinitions = [
    ['label' => 'Barra de 1/4',          'capacity' => 405,  'match' => ['BOLSA 1/4','1/4']],
    ['label' => 'Barra 1/12',            'capacity' => 900,  'match' => ['BOLSA 1/12','1/12']],
    ['label' => 'Triturado',             'capacity' => 315,  'match' => ['BOLSA TRIT','TRITURADO']],
    ['label' => 'Gourmet 5kg',           'capacity' => 2520, 'match' => ['BOLSA 5KG','5 KG','5KG']],
    ['label' => 'Hielo Gourmet 3kg',     'capacity' => 2025, 'match' => ['BOLSA 3KG','3 KG']],
    ['label' => 'Hielo Gourmet seven',   'capacity' => 2025, 'match' => ['SEVEN']],
    ['label' => 'Barras 150',            'capacity' => 2010, 'match' => ['BARRA 150 KILOS','150 KG']],
];
$capacityRows = [];
foreach ($capacityDefinitions as $def) {
    $available = 0.0;
    $matchedSku = '';
    $matchedProductIds = [];
    foreach ($inventoryRowsAll as $r) {
        $hay = strtoupper((string)$r['sku'] . ' ' . (string)$r['name']);
        foreach ($def['match'] as $m) {
            if (str_contains($hay, strtoupper($m))) {
                $available += (float)$r['on_hand'];
                $matchedSku = $matchedSku !== '' ? $matchedSku : (string)$r['sku'];
                $matchedProductIds[] = (int)$r['product_id'];
                break;
            }
        }
    }
    $matchedProductIds = array_values(array_unique($matchedProductIds));
    if ($productId > 0 && !in_array($productId, $matchedProductIds, true)) {
        continue;
    }
    $capacity = (float)$def['capacity'];
    $toProduce = max(0.0, $capacity - $available);
    $capacityRows[] = [
        'label' => $def['label'],
        'sku' => $matchedSku,
        'product_ids' => $matchedProductIds,
        'capacity' => $capacity,
        'available' => $available,
        'to_produce' => $toProduce,
        'pct' => $capacity > 0 ? min(100, round(($available / $capacity) * 100, 1)) : 0,
    ];
}


/* ============================================================
 * PDF / impresión: Programa de producción por capacidad
 * ============================================================ */
$capacityPdfUrl = '?' . http_build_query([
    'action' => 'capacity_pdf',
    'company_id' => $companyId,
    'location_id' => $locationId,
    'product_id' => $productId,
    'date_from' => $dateFrom,
    'date_to' => $dateTo,
]);

if (rpt_get_str('action') === 'capacity_pdf') {
    header('Content-Type: text/html; charset=utf-8');
    $printedAt = date('d/m/Y H:i');
    ?>
<!doctype html>
<html lang="es">
<head>
<meta charset="utf-8">
<title>Programa de producción - <?= h($selectedCompanyName) ?></title>
<style>
@page{size:letter landscape;margin:10mm}
*{box-sizing:border-box}body{font-family:Arial,Helvetica,sans-serif;color:#0f172a;margin:0;background:#fff}.head{display:flex;justify-content:space-between;align-items:flex-start;border-bottom:2px solid #1d4ed8;padding-bottom:10px;margin-bottom:14px}.title{font-size:22px;font-weight:800;color:#0b2f6b}.sub{font-size:12px;color:#475569;margin-top:4px}.badge{display:inline-block;border:1px solid #bfdbfe;background:#eff6ff;color:#1d4ed8;border-radius:999px;padding:6px 10px;font-weight:700;font-size:11px}.summary{display:grid;grid-template-columns:repeat(4,1fr);gap:8px;margin:12px 0}.box{border:1px solid #dbe5f1;border-radius:12px;padding:10px;background:#f8fafc}.box small{display:block;color:#64748b;font-weight:700}.box b{display:block;font-size:18px;margin-top:4px}table{width:100%;border-collapse:collapse;font-size:12px}th{background:#eaf2ff;color:#0f172a;text-align:left}th,td{border:1px solid #cbd5e1;padding:8px}td.num,th.num{text-align:right}.need{font-weight:800;color:#b91c1c}.ok{font-weight:800;color:#166534}.footer{margin-top:14px;font-size:11px;color:#64748b}.actions{position:fixed;right:16px;top:16px;display:flex;gap:8px}.btn{border:0;border-radius:10px;padding:9px 12px;font-weight:700;cursor:pointer}.btn-primary{background:#2563eb;color:white}.btn-light{background:#e2e8f0;color:#0f172a}@media print{.actions{display:none}.head{break-after:avoid}tr{break-inside:avoid}}
</style>
</head>
<body>
<div class="actions"><button class="btn btn-primary" onclick="window.print()">Imprimir / guardar PDF</button><button class="btn btn-light" onclick="window.close()">Cerrar</button></div>
<div class="head">
  <div>
    <div class="title">Programa de producción - Recargas / capacidad</div>
    <div class="sub"><?= h($selectedCompanyName) ?> · <?= h($selectedLocationName) ?> · <?= h($dateFrom) ?> a <?= h($dateTo) ?></div>
    <div class="sub">Generado: <?= h($printedAt) ?></div>
  </div>
  <span class="badge">Detalle disponible en almacén</span>
</div>
<?php
$totalCapacity = array_sum(array_map(fn($r)=>(float)$r['capacity'], $capacityRows));
$totalAvailable = array_sum(array_map(fn($r)=>(float)$r['available'], $capacityRows));
$totalProduce = array_sum(array_map(fn($r)=>(float)$r['to_produce'], $capacityRows));
$totalOcc = $totalCapacity > 0 ? min(100, round(($totalAvailable / $totalCapacity) * 100, 2)) : 0;
?>
<div class="summary">
  <div class="box"><small>Capacidad total</small><b><?= rpt_num0($totalCapacity) ?></b></div>
  <div class="box"><small>Disponible actual</small><b><?= rpt_num0($totalAvailable) ?></b></div>
  <div class="box"><small>Total a producir</small><b><?= rpt_num0($totalProduce) ?></b></div>
  <div class="box"><small>Ocupación</small><b><?= rpt_num2($totalOcc) ?>%</b></div>
</div>
<table>
<thead><tr><th>Artículo</th><th>SKU detectado</th><th class="num">Capacidad</th><th class="num">Disponible</th><th class="num">Total a producir</th><th class="num">Ocupación</th></tr></thead>
<tbody>
<?php if (!$capacityRows): ?>
<tr><td colspan="6" style="text-align:center;color:#64748b;padding:18px">Sin datos para los filtros seleccionados.</td></tr>
<?php else: foreach ($capacityRows as $r): ?>
<tr>
  <td><b><?= h($r['label']) ?></b></td>
  <td><?= h($r['sku'] ?: '-') ?></td>
  <td class="num"><?= rpt_num0($r['capacity']) ?></td>
  <td class="num"><?= rpt_num0($r['available']) ?></td>
  <td class="num <?= ((float)$r['to_produce'] > 0 ? 'need' : 'ok') ?>"><?= rpt_num0($r['to_produce']) ?></td>
  <td class="num"><?= rpt_num2($r['pct']) ?>%</td>
</tr>
<?php endforeach; endif; ?>
</tbody>
</table>
<div class="footer">Este reporte se genera desde Reportes > Recargas / Capacidad. El inventario disponible respeta la regla operativa: BARRA 150 KILOS = CF1 + CF2; producto terminado/bolsas = CF3.</div>
<script>window.addEventListener('load',()=>setTimeout(()=>window.print(),350));
// Cuando el usuario abre la pestaña de Calidad/Capacidad, Chart.js recalcula tamaño.
document.querySelectorAll('button[data-bs-toggle="pill"]').forEach(btn => {
  btn.addEventListener('shown.bs.tab', () => {
    Object.values(Chart.instances || {}).forEach(ch => { try { ch.resize(); ch.update('none'); } catch(e){} });
  });
});

</script>
</body>
</html>
    <?php
    exit;
}

/* ============================================================
 * Movimientos reales de inventario: entradas y salidas por artículo
 * ============================================================ */
$inventoryMovementCards = [];
$movementTotals = ['IN' => 0.0, 'OUT' => 0.0];
if (rpt_table_exists($pdo, 'inventory_moves')) {
    $inventoryMovementCards = rpt_run($pdo, "
        SELECT
            p.id AS product_id,
            p.sku,
            p.name AS product_name,
            p.uom,
            COALESCE(SUM(CASE WHEN UPPER(im.move_type) IN ('IN','ADJ') THEN im.qty ELSE 0 END),0) AS entrada_qty,
            COALESCE(SUM(CASE WHEN UPPER(im.move_type) = 'OUT' THEN im.qty ELSE 0 END),0) AS salida_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.work_date BETWEEN ? AND ?
          AND (? = 0 OR im.location_id = ?)
          AND (? = 0 OR im.product_id = ?)
          AND (
              (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')
          )
        GROUP BY p.id, p.sku, p.name, p.uom
        HAVING entrada_qty <> 0 OR salida_qty <> 0
        ORDER BY p.sku
    ", [$companyId, $dateFrom, $dateTo, $locationId, $locationId, $productId, $productId]);
    foreach ($inventoryMovementCards as $r) {
        $movementTotals['IN'] += (float)$r['entrada_qty'];
        $movementTotals['OUT'] += (float)$r['salida_qty'];
    }
}

/* ============================================================
 * Datos Chart.js
 * ============================================================ */
$chartProdLabels = []; $chartProd = []; $chartProdWarehouse = []; $chartProdMerma = []; $chartProdTarget = []; $chartEff = [];
foreach ($dailyRows as $r) {
    $dateKey = (string)$r['prod_date'];
    $prodQty = (float)$r['prod_qty'];
    $mermaQty = (float)($prodMermaByDate[$dateKey] ?? 0);
    $warehouseQty = max(0.0, $prodQty - $mermaQty);
    $chartProdLabels[] = rpt_date_label($dateKey);
    $chartProd[] = $prodQty;
    $chartProdWarehouse[] = $warehouseQty;
    $chartProdMerma[] = $mermaQty;
    $chartProdTarget[] = (float)$r['target_qty'];
    $chartEff[] = rpt_pct_value($prodQty, (float)$r['target_qty']);
}

$chartMermaLabels = []; $chartMermaProd = []; $chartMermaWh = []; $chartMermaPct = []; $chartWater = [];
$prodByDate = [];
foreach ($dailyRows as $r) { $prodByDate[(string)$r['prod_date']] = (float)$r['prod_qty']; }
foreach (array_keys($allDates) as $d) {
    $mp = (float)($prodMermaByDate[$d] ?? 0);
    $mw = (float)($whMermaByDate[$d] ?? 0);
    $chartMermaLabels[] = rpt_date_label($d);
    $chartMermaProd[] = $mp;
    $chartMermaWh[] = $mw;
    $chartMermaPct[] = rpt_pct_value($mp + $mw, (float)($prodByDate[$d] ?? 0));
    $chartWater[] = ($mp + $mw) * $litersPerBar;
}

function rpt_multi_series(array $rows): array {
    $labels = [];
    $series = [];
    foreach ($rows as $r) {
        $date = rpt_date_label((string)$r['work_date']);
        $point = (string)($r['point_name'] ?? 'Lectura');
        if (!in_array($date, $labels, true)) $labels[] = $date;
        if (!isset($series[$point])) $series[$point] = [];
        $series[$point][$date] = round((float)$r['value'], 2);
    }
    $datasets = [];
    foreach ($series as $name => $values) {
        $data = [];
        foreach ($labels as $l) $data[] = $values[$l] ?? null;
        $datasets[] = ['label' => $name, 'data' => $data];
    }
    return ['labels' => $labels, 'datasets' => $datasets];
}
$chartQualityCub = rpt_multi_series($qualityCub);
$chartQualityTds = rpt_multi_series($qualityTds);
$chartQualityCf = rpt_multi_series($qualityCf);
$chartQualityBrine = rpt_multi_series($qualityBrine);

$chartCapLabels = array_column($capacityRows, 'label');
$chartCapAvailable = array_map(fn($r) => (float)$r['available'], $capacityRows);
$chartCapMissing = array_map(fn($r) => (float)$r['to_produce'], $capacityRows);

/* ============================================================
 * Movimientos reales generados por pedidos VentasHielo y ventas
 * ============================================================ */
$salesMovementRows = [];
$salesMovementTotals = ['VENTASHIELO' => 0.0, 'VENTAS' => 0.0, 'TOTAL' => 0.0];
if (rpt_table_exists($pdo, 'inventory_moves')) {
    $salesMovementRows = rpt_run($pdo, "
        SELECT
            im.id AS move_id,
            im.ref_id AS outbound_id,
            im.work_date AS outbound_date,
            im.ref_type,
            im.notes,
            COALESCE(w.code, 'SIN-WH') AS warehouse_code,
            p.sku,
            p.name AS product_name,
            p.uom,
            im.qty,
            COALESCE(ob.reference, CONCAT('MOV-', im.id)) AS reference,
            COALESCE(NULLIF(so.sales_order_ref,''), ob.reference, CONCAT('OUT-', im.ref_id)) AS folio,
            COALESCE(so.source, im.ref_type, '') AS source,
            COALESCE(sc.business_name, '') AS business_name
        FROM inventory_moves im
        INNER JOIN products p ON p.id = im.product_id
        LEFT JOIN warehouses w ON w.id = im.warehouse_id
        LEFT JOIN outbounds ob ON ob.id = im.ref_id AND im.ref_type IN ('OUTBOUND','VENTASHIELO','SALES_ORDER')
        LEFT JOIN sales_orders so ON so.outbound_id = ob.id AND so.company_id = im.company_id
        LEFT JOIN sales_customers sc ON sc.id = so.customer_id
        WHERE im.company_id = ?
          AND im.work_date BETWEEN ? AND ?
          AND (? = 0 OR im.location_id = ?)
          AND (? = 0 OR im.product_id = ?)
          AND UPPER(im.move_type) = 'OUT'
          AND (
                UPPER(im.ref_type) IN ('VENTASHIELO','OUTBOUND','SALES_ORDER')
             OR COALESCE(so.sales_order_ref,'') LIKE 'PW-%'
             OR COALESCE(so.sales_order_ref,'') LIKE 'OSV-%'
             OR COALESCE(ob.reference,'') LIKE 'PW-%'
             OR COALESCE(ob.reference,'') LIKE 'OSV-%'
          )
        ORDER BY im.work_date DESC, im.id DESC, p.sku ASC
        LIMIT 500
    ", [$companyId, $dateFrom, $dateTo, $locationId, $locationId, $productId, $productId]);

    foreach ($salesMovementRows as $mr) {
        $folioMv = strtoupper((string)($mr['folio'] ?? ''));
        $sourceMv = strtoupper((string)($mr['source'] ?? ''));
        $refTypeMv = strtoupper((string)($mr['ref_type'] ?? ''));
        $bucket = ($refTypeMv === 'VENTASHIELO' || str_contains($sourceMv, 'VENTASHIELO') || $sourceMv === 'VH' || str_starts_with($folioMv, 'PW-')) ? 'VENTASHIELO' : 'VENTAS';
        $qtyMv = (float)($mr['qty'] ?? 0);
        $salesMovementTotals[$bucket] += $qtyMv;
        $salesMovementTotals['TOTAL'] += $qtyMv;
    }
}


?>
<!doctype html>
<html lang="es">
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>BReport · Reportes Hielo Barra</title>
    <link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700;800&display=swap" rel="stylesheet">
    <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">
    <script src="https://cdn.jsdelivr.net/npm/chart.js@4.4.1/dist/chart.umd.min.js"></script>
    <style>
        :root{--bg:#f6f8fc;--card:#fff;--line:#dbe5f1;--text:#0f172a;--muted:#64748b;--blue:#2563eb;--cyan:#0ea5e9;--green:#16a34a;--gold:#d97706;--red:#dc2626;--shadow:0 18px 42px rgba(15,23,42,.10);--radius:22px;}
        *{box-sizing:border-box} body{font-family:'Inter',system-ui,Arial,sans-serif;background:radial-gradient(circle at 10% 12%,rgba(37,99,235,.10),transparent 22%),radial-gradient(circle at 90% 80%,rgba(14,165,233,.12),transparent 24%),linear-gradient(135deg,#f8fafc 0%,#eef4fb 100%);color:var(--text);min-height:100vh;}
        .topbar{background:rgba(255,255,255,.92);border-bottom:1px solid #e2e8f0;box-shadow:0 10px 28px rgba(15,23,42,.08);backdrop-filter:blur(12px);position:sticky;top:0;z-index:1000}
        .brand{font-size:1.55rem;font-weight:800;color:#0f172a}.brand-sub{color:var(--muted);font-size:.92rem}.shell{max-width:1520px;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}.section-title{display:flex;align-items:center;justify-content:space-between;gap:12px;margin-bottom:16px}.section-title h2,.section-title h3{font-weight:800;margin:0}.section-title small{color:var(--muted)}
        .form-control,.form-select{min-height:46px;border-radius:15px;border:1px solid #cbd5e1;color:#0f172a;background:#fff}.form-label{font-weight:700;color:#334155}.btn-soft{border-radius:15px;font-weight:800}.btn-primary-soft{background:linear-gradient(135deg,#2563eb,#0ea5e9);color:#fff;border:0;box-shadow:0 12px 24px rgba(37,99,235,.22)}.toolbar-btn{background:#fff;border:1px solid #cbd5e1;color:#1e293b;border-radius:14px;font-weight:700}
        .kpi-card{padding:20px;border-radius:22px;background:linear-gradient(180deg,#fff,#f8fafc);border:1px solid #dbe5f1;height:100%;position:relative;overflow:hidden}.kpi-card:after{content:'';position:absolute;right:-35px;top:-35px;width:90px;height:90px;border-radius:50%;background:rgba(37,99,235,.08)}.kpi-label{color:var(--muted);font-weight:700}.kpi-value{font-size:2rem;font-weight:800;color:#0f172a}.kpi-note{color:#64748b;font-size:.86rem}.icon-bubble{width:42px;height:42px;border-radius:15px;display:flex;align-items:center;justify-content:center;background:#eff6ff;color:#2563eb;font-size:1.2rem}
        .chart-card{padding:20px;border-radius:22px;background:#fff;border:1px solid #dbe5f1;box-shadow:0 14px 32px rgba(15,23,42,.07);height:100%}.chart-box{height:330px}.chart-box-sm{height:290px}.table-wrap{border:1px solid #dbe5f1;border-radius:18px;overflow:hidden;background:#fff}.table{margin:0}.table thead th{background:#eff6ff;color:#0f172a;font-weight:800;border-bottom:1px solid #dbe5f1}.table tbody td{color:#1f2937;border-color:#e2e8f0}.badge-soft{display:inline-flex;align-items:center;padding:7px 11px;border-radius:999px;font-weight:800;font-size:.8rem}.badge-green{background:#dcfce7;color:#166534;border:1px solid #bbf7d0}.badge-red{background:#fee2e2;color:#991b1b;border:1px solid #fecaca}.badge-blue{background:#dbeafe;color:#1d4ed8;border:1px solid #bfdbfe}.progress{height:10px;border-radius:999px;background:#e2e8f0}.progress-bar{border-radius:999px}.nav-pills .nav-link{border-radius:16px;color:#334155;font-weight:800}.nav-pills .nav-link.active{background:linear-gradient(135deg,#2563eb,#0ea5e9);box-shadow:0 10px 22px rgba(37,99,235,.20)}
        .capacity-card{display:flex;flex-direction:column;gap:10px;padding:16px;border:1px solid #dbe5f1;border-radius:20px;background:#fff;height:100%;box-shadow:0 10px 24px rgba(15,23,42,.06)}.capacity-name{font-weight:800;color:#0f172a}.capacity-meta{color:#64748b;font-size:.86rem}.capacity-big{font-weight:800;font-size:1.35rem;color:#0f172a}
        @media(max-width:768px){.kpi-value{font-size:1.55rem}.chart-box,.chart-box-sm{height:280px}.brand{font-size:1.25rem}.panel-pad{padding:16px}}
    </style>
</head>
<body>
<nav class="navbar topbar">
    <div class="container-fluid px-3 px-lg-4">
        <div>
            <div class="brand">BReport · Reportes</div>
            <div class="brand-sub">Dashboard de producción, calidad y capacidad de almacén</div>
        </div>
        <div class="ms-auto d-flex gap-2 align-items-center flex-wrap">
            <span class="text-muted small"><?= h($u['full_name'] ?? '') ?></span>
            <a class="btn toolbar-btn btn-sm" href="dashboard.php">Dashboard</a>
        </div>
    </div>
</nav>

<div class="shell">
    <div class="glass panel-pad mb-4">
        <div class="section-title flex-wrap">
            <div>
                <h2><i class="bi bi-bar-chart-line-fill text-primary me-2"></i>Dashboard Hielo Barra</h2>
                <small><?= h($selectedCompanyName) ?> · <?= h($selectedLocationName) ?> · <?= h($dateFrom) ?> a <?= h($dateTo) ?></small>
            </div>
            <span class="badge-soft badge-blue">Diseño actualizado</span>
        </div>
        <form class="row g-3 align-items-end" method="get">
            <div class="col-12 col-md-3">
                <label class="form-label">Empresa</label>
                <select class="form-select" name="company_id" onchange="this.form.submit()">
                    <?php foreach ($companies as $c): ?>
                        <option value="<?= (int)$c['id'] ?>" <?= (int)$c['id'] === $companyId ? 'selected' : '' ?>><?= h($c['name']) ?></option>
                    <?php endforeach; ?>
                </select>
            </div>
            <div class="col-12 col-md-3">
                <label class="form-label">Planta / sucursal</label>
                <select class="form-select" name="location_id">
                    <option value="0">Todas</option>
                    <?php foreach ($locations as $l): ?>
                        <option value="<?= (int)$l['id'] ?>" <?= (int)$l['id'] === $locationId ? 'selected' : '' ?>><?= h($l['name']) ?></option>
                    <?php endforeach; ?>
                </select>
            </div>
            <div class="col-12 col-md-3">
                <label class="form-label">Artículo / presentación</label>
                <select class="form-select" name="product_id">
                    <option value="0">Todos los artículos</option>
                    <?php foreach ($products 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-1"><label class="form-label">Desde</label><input class="form-control" type="date" name="date_from" value="<?= h($dateFrom) ?>"></div>
            <div class="col-6 col-md-1"><label class="form-label">Hasta</label><input class="form-control" type="date" name="date_to" value="<?= h($dateTo) ?>"></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>

    <ul class="nav nav-pills gap-2 mb-4" id="dashTabs" role="tablist">
        <li class="nav-item"><button class="nav-link active" data-bs-toggle="pill" data-bs-target="#tabProd" type="button">Producción</button></li>
        <li class="nav-item"><button class="nav-link" data-bs-toggle="pill" data-bs-target="#tabQuality" type="button">Calidad</button></li>
        <li class="nav-item"><button class="nav-link" data-bs-toggle="pill" data-bs-target="#tabCapacity" type="button">Recargas / Capacidad</button></li>
        <li class="nav-item"><button class="nav-link" data-bs-toggle="pill" data-bs-target="#tabMovements" type="button">Movimientos Ventas</button></li>
    </ul>

    <div class="tab-content">
        <div class="tab-pane fade show active" id="tabProd">
            <div class="row g-3 mb-4">
                <div class="col-12 col-md-3"><div class="kpi-card"><div class="d-flex justify-content-between"><div><div class="kpi-label">Producción total</div><div class="kpi-value"><?= rpt_num0($totalProd) ?></div><div class="kpi-note">Piezas / barras del periodo</div></div><div class="icon-bubble"><i class="bi bi-box-seam"></i></div></div></div></div>
                <div class="col-12 col-md-3"><div class="kpi-card"><div class="d-flex justify-content-between"><div><div class="kpi-label">Cumplimiento</div><div class="kpi-value"><?= rpt_num2($compliancePct) ?>%</div><div class="kpi-note">Producción vs meta</div></div><div class="icon-bubble"><i class="bi bi-speedometer2"></i></div></div></div></div>
                <div class="col-12 col-md-3"><div class="kpi-card"><div class="d-flex justify-content-between"><div><div class="kpi-label">Merma</div><div class="kpi-value"><?= rpt_num2($mermaPct) ?>%</div><div class="kpi-note"><?= rpt_num2($totalMerma) ?> barras/pz</div></div><div class="icon-bubble"><i class="bi bi-exclamation-triangle"></i></div></div></div></div>
                <div class="col-12 col-md-3"><div class="kpi-card"><div class="d-flex justify-content-between"><div><div class="kpi-label">Agua desperdiciada</div><div class="kpi-value"><?= rpt_num0($litersLost) ?> L</div><div class="kpi-note">Merma x 150 L</div></div><div class="icon-bubble"><i class="bi bi-droplet-half"></i></div></div></div></div>
            </div>
            <div class="row g-3 mb-4">
                <div class="col-12 col-xl-6"><div class="chart-card"><div class="section-title"><div><h3>Gráfica #1 · Producción de barras</h3><small>Azul: enviado a almacén · Rojo: merma · línea verde: meta</small></div></div><div class="chart-box"><canvas id="chartProduction"></canvas></div></div></div>
                <div class="col-12 col-xl-6"><div class="chart-card"><div class="section-title"><div><h3>Gráfica #2 · Porcentaje de eficiencia</h3><small>Eficiencia diaria producción / meta</small></div></div><div class="chart-box"><canvas id="chartEfficiency"></canvas></div></div></div>
                <div class="col-12 col-xl-6"><div class="chart-card"><div class="section-title"><div><h3>Gráfica #3 · Barras scrap / recuperadas</h3><small>Merma de producción vs merma de almacén</small></div></div><div class="chart-box-sm"><canvas id="chartScrap"></canvas></div></div></div>
                <div class="col-12 col-xl-6"><div class="chart-card"><div class="section-title"><div><h3>Gráfica #4 · % de barras mermadas</h3><small>Merma total contra producción diaria</small></div></div><div class="chart-box-sm"><canvas id="chartMermaPct"></canvas></div></div></div>
                <div class="col-12"><div class="chart-card"><div class="section-title"><div><h3>Gráfica #5 · Litros de agua perdidos</h3><small>Merma por barras traducida a litros</small></div></div><div class="chart-box-sm"><canvas id="chartWater"></canvas></div></div></div>
            </div>
        </div>

        <div class="tab-pane fade" id="tabQuality">
            <div class="row g-3">
                <div class="col-12 col-xl-6"><div class="chart-card"><div class="section-title"><div><h3>Gráfica #1 · Temperatura de cubicados</h3><small>Lecturas promedio por día</small></div></div><div class="chart-box"><canvas id="chartQualityCub"></canvas></div></div></div>
                <div class="col-12 col-xl-6"><div class="chart-card"><div class="section-title"><div><h3>Gráfica #2 · TDS de agua purificada</h3><small>PPM / TDS promedio por día</small></div></div><div class="chart-box"><canvas id="chartQualityTds"></canvas></div></div></div>
                <div class="col-12 col-xl-6"><div class="chart-card"><div class="section-title"><div><h3>Gráfica #3 · Temperatura de cuartos fríos</h3><small>CF1, CF2, CF3 por día</small></div></div><div class="chart-box"><canvas id="chartQualityCf"></canvas></div></div></div>
                <div class="col-12 col-xl-6"><div class="chart-card"><div class="section-title"><div><h3>Gráfica #4 · Salmuera de tanques</h3><small>Grados de salmuera por tanque</small></div></div><div class="chart-box"><canvas id="chartQualityBrine"></canvas></div></div></div>
            </div>
        </div>

        <div class="tab-pane fade" id="tabCapacity">
            <div class="row g-3 mb-4">
                <div class="col-12"><div class="chart-card"><div class="section-title flex-wrap"><div><h3>Gráfica #1 · Capacidad por presentación</h3><small>Piezas disponibles vs piezas faltantes por producir</small></div><a class="btn btn-primary-soft btn-soft" target="_blank" href="<?= h($capacityPdfUrl) ?>"><i class="bi bi-file-earmark-pdf me-1"></i>Descargar / imprimir programa</a></div><div class="chart-box"><canvas id="chartCapacity"></canvas></div></div></div>
            </div>
            <div class="row g-3 mb-4">
                <?php foreach ($capacityRows as $r): ?>
                    <div class="col-12 col-md-6 col-xl-3">
                        <div class="capacity-card">
                            <div class="capacity-name"><?= h($r['label']) ?></div>
                            <div class="capacity-meta">Capacidad: <?= rpt_num0($r['capacity']) ?> pz · Disponible: <?= rpt_num0($r['available']) ?> pz</div>
                            <div class="progress"><div class="progress-bar bg-primary" style="width:<?= (float)$r['pct'] ?>%"></div></div>
                            <div class="d-flex justify-content-between align-items-end">
                                <div><div class="capacity-meta">Por producir</div><div class="capacity-big"><?= rpt_num0($r['to_produce']) ?> pz</div></div>
                                <span class="badge-soft <?= ((float)$r['to_produce'] <= 0 ? 'badge-green' : 'badge-red') ?>"><?= rpt_num2($r['pct']) ?>%</span>
                            </div>
                        </div>
                    </div>
                <?php endforeach; ?>
            </div>
            <div class="glass panel-pad">
                <div class="section-title flex-wrap"><div><h3>Detalle disponible en almacén</h3><small>Comparativo contra capacidad configurada para Hielo Barra</small></div><a class="btn btn-outline-primary btn-soft" target="_blank" href="<?= h($capacityPdfUrl) ?>"><i class="bi bi-printer me-1"></i>Imprimir PDF</a></div>
                <div class="table-wrap">
                    <table class="table table-hover align-middle">
                        <thead><tr><th>Artículo</th><th>SKU detectado</th><th class="text-end">Capacidad</th><th class="text-end">Disponible</th><th class="text-end">Total a producir</th><th class="text-end">Ocupación</th></tr></thead>
                        <tbody>
                        <?php foreach ($capacityRows as $r): ?>
                            <tr>
                                <td class="fw-bold"><?= h($r['label']) ?></td>
                                <td><?= h($r['sku'] ?: '-') ?></td>
                                <td class="text-end"><?= rpt_num0($r['capacity']) ?></td>
                                <td class="text-end"><?= rpt_num0($r['available']) ?></td>
                                <td class="text-end fw-bold"><?= rpt_num0($r['to_produce']) ?></td>
                                <td class="text-end"><?= rpt_num2($r['pct']) ?>%</td>
                            </tr>
                        <?php endforeach; ?>
                        </tbody>
                    </table>
                </div>
            </div>
        </div>

        <div class="tab-pane fade" id="tabMovements">
            <div class="row g-3 mb-4">
                <div class="col-12 col-md-6"><div class="kpi-card"><div class="d-flex justify-content-between"><div><div class="kpi-label">Entradas comerciales</div><div class="kpi-value text-success"><?= rpt_num0($movementTotals['IN'] ?? 0) ?></div><div class="kpi-note">BARRA solo CF1 + CF2; productos terminados solo CF3</div></div><div class="icon-bubble"><i class="bi bi-arrow-down-circle"></i></div></div></div></div>
                <div class="col-12 col-md-6"><div class="kpi-card"><div class="d-flex justify-content-between"><div><div class="kpi-label">Salidas comerciales</div><div class="kpi-value text-danger"><?= rpt_num0($movementTotals['OUT'] ?? 0) ?></div><div class="kpi-note">Periodo y artículo seleccionados</div></div><div class="icon-bubble"><i class="bi bi-arrow-up-circle"></i></div></div></div></div>
            </div>
            <div class="glass panel-pad mb-4">
                <div class="section-title"><div><h3>Indicadores de entradas y salidas por artículo</h3><small>Resumen de movimientos comerciales filtrados por fecha, planta y presentación.</small></div></div>
                <div class="row g-3">
                <?php if (!$inventoryMovementCards): ?>
                    <div class="col-12"><div class="alert alert-light border mb-0 text-center text-muted">Sin movimientos de inventario comercial en el rango seleccionado.</div></div>
                <?php else: foreach ($inventoryMovementCards as $mc): ?>
                    <div class="col-12 col-md-6 col-xl-3">
                        <div class="capacity-card">
                            <div class="capacity-name"><?= h($mc['sku']) ?></div>
                            <div class="capacity-meta"><?= h($mc['product_name']) ?></div>
                            <div class="d-flex justify-content-between gap-2 mt-1">
                                <div><div class="capacity-meta">Entradas</div><div class="capacity-big text-success"><?= rpt_is_bar_sku((string)$mc['sku']) ? rpt_num0($mc['entrada_qty']) : rpt_num3($mc['entrada_qty']) ?></div></div>
                                <div class="text-end"><div class="capacity-meta">Salidas</div><div class="capacity-big text-danger"><?= rpt_is_bar_sku((string)$mc['sku']) ? rpt_num0($mc['salida_qty']) : rpt_num3($mc['salida_qty']) ?></div></div>
                            </div>
                        </div>
                    </div>
                <?php endforeach; endif; ?>
                </div>
            </div>
            <div class="row g-3 mb-4">
                <div class="col-12 col-md-4"><div class="kpi-card"><div class="d-flex justify-content-between"><div><div class="kpi-label">Movimientos VentasHielo</div><div class="kpi-value"><?= rpt_num0($salesMovementTotals['VENTASHIELO'] ?? 0) ?></div><div class="kpi-note">Piezas surtidas desde folios PW</div></div><div class="icon-bubble"><i class="bi bi-snow2"></i></div></div></div></div>
                <div class="col-12 col-md-4"><div class="kpi-card"><div class="d-flex justify-content-between"><div><div class="kpi-label">Salidas creadas desde ventas</div><div class="kpi-value"><?= rpt_num0($salesMovementTotals['VENTAS'] ?? 0) ?></div><div class="kpi-note">Piezas surtidas desde órdenes OSV</div></div><div class="icon-bubble"><i class="bi bi-truck"></i></div></div></div></div>
                <div class="col-12 col-md-4"><div class="kpi-card"><div class="d-flex justify-content-between"><div><div class="kpi-label">Total surtido</div><div class="kpi-value"><?= rpt_num0($salesMovementTotals['TOTAL'] ?? 0) ?></div><div class="kpi-note">Periodo seleccionado</div></div><div class="icon-bubble"><i class="bi bi-clipboard2-check"></i></div></div></div></div>
            </div>
            <div class="glass panel-pad">
                <div class="section-title"><div><h3>Movimientos generados por pedidos</h3><small>Incluye pedidos VentasHielo y órdenes de salida creadas desde ventas</small></div></div>
                <div class="table-wrap">
                    <div class="table-responsive">
                        <table class="table table-hover align-middle">
                            <thead><tr><th>Fecha</th><th>Folio</th><th>Origen</th><th>Cliente / destino</th><th>Almacén</th><th>SKU</th><th>Producto</th><th class="text-end">Cantidad</th><th>UOM</th><th>Salida</th></tr></thead>
                            <tbody>
                            <?php if (!$salesMovementRows): ?>
                                <tr><td colspan="10" class="text-center text-muted py-4">Sin movimientos de VentasHielo o ventas en el rango seleccionado.</td></tr>
                            <?php else: ?>
                                <?php foreach ($salesMovementRows as $mr): ?>
                                    <?php
                                        $folioMv = strtoupper((string)($mr['folio'] ?? ''));
                                        $sourceMv = strtoupper((string)($mr['source'] ?? ''));
                                        $isVhMv = str_contains($sourceMv, 'VENTASHIELO') || $sourceMv === 'VH' || str_starts_with($folioMv, 'PW-');
                                        $originLabel = $isVhMv ? 'VentasHielo' : 'Ventas';
                                    ?>
                                    <tr>
                                        <td><?= h((string)($mr['outbound_date'] ?? '')) ?></td>
                                        <td class="fw-bold"><?= h((string)($mr['folio'] ?? '-')) ?></td>
                                        <td><span class="badge-soft <?= $isVhMv ? 'badge-blue' : 'badge-green' ?>"><?= h($originLabel) ?></span></td>
                                        <td><?= h((string)($mr['business_name'] ?? '-')) ?></td>
                                        <td><?= h((string)($mr['warehouse_code'] ?? '-')) ?></td>
                                        <td><?= h((string)($mr['sku'] ?? '')) ?></td>
                                        <td><?= h((string)($mr['product_name'] ?? '')) ?></td>
                                        <td class="text-end fw-bold"><?= rpt_is_bar_sku((string)($mr['sku'] ?? '')) ? rpt_num0($mr['qty'] ?? 0) : rpt_num2($mr['qty'] ?? 0) ?></td>
                                        <td><?= h((string)($mr['uom'] ?? '')) ?></td>
                                        <td class="text-end">#<?= (int)($mr['outbound_id'] ?? 0) ?></td>
                                    </tr>
                                <?php endforeach; ?>
                            <?php endif; ?>
                            </tbody>
                        </table>
                    </div>
                </div>
            </div>
        </div>
    </div>
</div>

<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js"></script>
<script>
const palette = ['#2563eb','#16a34a','#d97706','#dc2626','#7c3aed','#0891b2','#f97316','#0f766e'];
Chart.defaults.color = '#334155';
Chart.defaults.borderColor = '#e2e8f0';
Chart.defaults.font.family = 'Inter, system-ui, Arial, sans-serif';

function fmtValue(v, percent=false){
  const n = Number(v || 0);
  if (!Number.isFinite(n)) return '';
  return percent ? `${n.toFixed(1)}%` : n.toLocaleString('es-MX', {maximumFractionDigits:0});
}

const valueLabelPlugin = {
  id: 'valueLabelPlugin',
  afterDatasetsDraw(chart, args, opts){
    if (!opts || opts.enabled === false) return;
    const {ctx} = chart;
    ctx.save();
    ctx.font = '700 11px Inter, system-ui, Arial';
    ctx.textAlign = 'center';
    ctx.textBaseline = 'bottom';
    ctx.fillStyle = opts.color || '#0f172a';
    const percent = !!opts.percent;
    const totalOnlyStacked = !!opts.totalOnlyStacked;
    const totalDatasetIndex = Number.isInteger(opts.totalDatasetIndex) ? opts.totalDatasetIndex : 1;
    const totalIndexes = Array.isArray(opts.totalIndexes) ? opts.totalIndexes : [0, 1];

    chart.data.datasets.forEach((dataset, datasetIndex) => {
      if (!chart.isDatasetVisible(datasetIndex)) return;
      const meta = chart.getDatasetMeta(datasetIndex);
      meta.data.forEach((el, i) => {
        const raw = Number((dataset.data || [])[i] || 0);
        if (!Number.isFinite(raw) || raw === 0) return;
        const pos = el.tooltipPosition();
        let labelValue = raw;
        if (totalOnlyStacked && datasetIndex !== totalDatasetIndex && (dataset.type || chart.config.type) === 'bar') return;
        if (totalOnlyStacked && datasetIndex === totalDatasetIndex) {
          labelValue = totalIndexes.reduce((sum, idx) => sum + Number((chart.data.datasets[idx]?.data || [])[i] || 0), 0);
        }
        ctx.fillText(fmtValue(labelValue, percent), pos.x, pos.y - 6);
      });
    });
    ctx.restore();
  }
};
Chart.register(valueLabelPlugin);

function baseOptions(percent=false){return {responsive:true,maintainAspectRatio:false,interaction:{mode:'index',intersect:false},plugins:{legend:{labels:{usePointStyle:true,boxWidth:8}},valueLabelPlugin:{enabled:true,percent}},scales:{x:{grid:{display:false},ticks:{color:'#64748b'}},y:{beginAtZero:true,ticks:{color:'#64748b',callback:v=>percent? v+'%': v},grid:{color:'#edf2f7'}}}};}
function makeDatasets(series){return (series.datasets||[]).map((d,i)=>({label:d.label,data:d.data,borderColor:palette[i%palette.length],backgroundColor:palette[i%palette.length]+'22',tension:.25,spanGaps:true,pointRadius:3,pointHoverRadius:5}));}

new Chart(document.getElementById('chartProduction'),{
  type:'bar',
  data:{
    labels:<?= json_encode($chartProdLabels, JSON_UNESCAPED_UNICODE|JSON_UNESCAPED_SLASHES) ?>,
    datasets:[
      {label:'Producido enviado a almacén',data:<?= json_encode($chartProdWarehouse) ?>,backgroundColor:'#2563eb',borderColor:'#1d4ed8',borderWidth:1,borderRadius:8,stack:'prod'},
      {label:'Merma',data:<?= json_encode($chartProdMerma) ?>,backgroundColor:'#dc2626',borderColor:'#991b1b',borderWidth:1,borderRadius:8,stack:'prod'},
      {label:'Meta',type:'line',data:<?= json_encode($chartProdTarget) ?>,borderColor:'#16a34a',backgroundColor:'#16a34a22',tension:.25,pointRadius:4,pointHoverRadius:6}
    ]
  },
  options:{
    ...baseOptions(),
    plugins:{
      ...baseOptions().plugins,
      valueLabelPlugin:{enabled:true,totalOnlyStacked:true,totalDatasetIndex:1,totalIndexes:[0,1]},
      tooltip:{callbacks:{footer:(items)=>{const total=(items||[]).filter(x=>['Producido enviado a almacén','Merma'].includes(x.dataset.label)).reduce((s,x)=>s+Number(x.raw||0),0);return total>0?'Total producido: '+total.toLocaleString('es-MX',{maximumFractionDigits:0}):'';}}}
    },
    scales:{x:{stacked:true,grid:{display:false},ticks:{color:'#64748b'}},y:{stacked:true,beginAtZero:true,ticks:{color:'#64748b'},grid:{color:'#edf2f7'}}}
  }
});
new Chart(document.getElementById('chartEfficiency'),{type:'line',data:{labels:<?= json_encode($chartProdLabels, JSON_UNESCAPED_UNICODE|JSON_UNESCAPED_SLASHES) ?>,datasets:[{label:'Eficiencia %',data:<?= json_encode($chartEff) ?>,borderColor:'#16a34a',backgroundColor:'#16a34a22',tension:.25,fill:true,pointRadius:4,pointHoverRadius:6}]},options:baseOptions(true)});
new Chart(document.getElementById('chartScrap'),{type:'bar',data:{labels:<?= json_encode($chartMermaLabels, JSON_UNESCAPED_UNICODE|JSON_UNESCAPED_SLASHES) ?>,datasets:[{label:'Merma producción',data:<?= json_encode($chartMermaProd) ?>,backgroundColor:'#fbbf24',borderColor:'#d97706',borderWidth:1,borderRadius:8},{label:'Merma almacén',data:<?= json_encode($chartMermaWh) ?>,backgroundColor:'#fdba74',borderColor:'#f97316',borderWidth:1,borderRadius:8}]},options:baseOptions()});
new Chart(document.getElementById('chartMermaPct'),{type:'line',data:{labels:<?= json_encode($chartMermaLabels, JSON_UNESCAPED_UNICODE|JSON_UNESCAPED_SLASHES) ?>,datasets:[{label:'% merma',data:<?= json_encode($chartMermaPct) ?>,borderColor:'#dc2626',backgroundColor:'#fecaca55',fill:true,tension:.25,pointRadius:4,pointHoverRadius:6}]},options:baseOptions(true)});
new Chart(document.getElementById('chartWater'),{type:'bar',data:{labels:<?= json_encode($chartMermaLabels, JSON_UNESCAPED_UNICODE|JSON_UNESCAPED_SLASHES) ?>,datasets:[{label:'Litros perdidos',data:<?= json_encode($chartWater) ?>,backgroundColor:'#67e8f9',borderColor:'#0891b2',borderWidth:1,borderRadius:8}]},options:baseOptions()});
const qCub=<?= json_encode($chartQualityCub, JSON_UNESCAPED_UNICODE|JSON_UNESCAPED_SLASHES) ?>, qTds=<?= json_encode($chartQualityTds, JSON_UNESCAPED_UNICODE|JSON_UNESCAPED_SLASHES) ?>, qCf=<?= json_encode($chartQualityCf, JSON_UNESCAPED_UNICODE|JSON_UNESCAPED_SLASHES) ?>, qBrine=<?= json_encode($chartQualityBrine, JSON_UNESCAPED_UNICODE|JSON_UNESCAPED_SLASHES) ?>;
new Chart(document.getElementById('chartQualityCub'),{type:'line',data:{labels:qCub.labels,datasets:makeDatasets(qCub)},options:baseOptions()});
new Chart(document.getElementById('chartQualityTds'),{type:'line',data:{labels:qTds.labels,datasets:makeDatasets(qTds)},options:baseOptions()});
new Chart(document.getElementById('chartQualityCf'),{type:'line',data:{labels:qCf.labels,datasets:makeDatasets(qCf)},options:baseOptions()});
new Chart(document.getElementById('chartQualityBrine'),{type:'line',data:{labels:qBrine.labels,datasets:makeDatasets(qBrine)},options:baseOptions()});
new Chart(document.getElementById('chartCapacity'),{type:'bar',data:{labels:<?= json_encode($chartCapLabels, JSON_UNESCAPED_UNICODE|JSON_UNESCAPED_SLASHES) ?>,datasets:[{label:'Pz disponibles',data:<?= json_encode($chartCapAvailable) ?>,backgroundColor:'#93c5fd',borderColor:'#2563eb',borderWidth:1,borderRadius:8},{label:'Pz faltantes (Por producir)',data:<?= json_encode($chartCapMissing) ?>,backgroundColor:'#fecaca',borderColor:'#dc2626',borderWidth:1,borderRadius:8}]},options:{...baseOptions(),scales:{x:{stacked:true,grid:{display:false},ticks:{color:'#64748b'}},y:{stacked:true,beginAtZero:true,ticks:{color:'#64748b'},grid:{color:'#edf2f7'}}}}});

// Cuando el usuario abre la pestaña de Calidad/Capacidad, Chart.js recalcula tamaño.
document.querySelectorAll('button[data-bs-toggle="pill"]').forEach(btn => {
  btn.addEventListener('shown.bs.tab', () => {
    Object.values(Chart.instances || {}).forEach(ch => { try { ch.resize(); ch.update('none'); } catch(e){} });
  });
});

</script>
</body>
</html>
