<?php
// public/dashboard.php
require_once __DIR__ . '/../app/bootstrap.php';
require_once __DIR__ . '/../app/db.php';
require_once __DIR__ . '/../app/auth.php';
require_once __DIR__ . '/../app/services/bcu_cotizaciones.php';
require_once __DIR__ . '/../app/services/brou_cotizaciones.php';

session_start();
if (!isset($_SESSION['auth']) || $_SESSION['auth'] !== true) {
  header('Location: index.php');
  exit;
}
require_page_access();

$pdo = db();

$mensajeCotizacion = '';
$errorCotizacion = '';

if (isset($_GET['actualizar_cotizaciones']) && $_GET['actualizar_cotizaciones'] === '1') {
  $actualizadas = [];
  $errores = [];

  try {
    $cot = obtenerUltimaCotizacionDisponibleBCU(2225, 3);
    if (!empty($cot['ok'])) {
      guardarCotizacionBCU($pdo, $cot);
      $actualizadas[] = 'BCU';
    } else {
      $errores[] = 'BCU sin datos';
    }
  } catch (Throwable $e) {
    $errores[] = 'BCU: ' . $e->getMessage();
  }

  try {
    brou_guardar_cotizacion($pdo);
    $actualizadas[] = 'BROU';
  } catch (Throwable $e) {
    $errores[] = 'BROU: ' . $e->getMessage();
  }

  $qs = [];
  if ($actualizadas) {
    $qs['cot_ok'] = 'Actualizado: ' . implode(', ', $actualizadas);
  }
  if ($errores) {
    $qs['cot_error'] = implode(' | ', $errores);
  }

  header('Location: dashboard.php' . ($qs ? '?' . http_build_query($qs) : ''));
  exit;
}

if (isset($_GET['cot_ok'])) {
  $mensajeCotizacion = trim((string)$_GET['cot_ok']);
}
if (isset($_GET['cot_error'])) {
  $errorCotizacion = trim((string)$_GET['cot_error']);
}

/* FILTROS PARA GRAFICOS */
$filtroCaravana = trim((string)($_GET['caravana'] ?? ''));
$filtroEstablecimiento = trim((string)($_GET['establecimiento'] ?? ''));

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

/* OPTIMIZADO: leer esquema una sola vez */
function dash_schema(PDO $pdo): array {
  static $schema = null;
  if ($schema !== null) return $schema;

  $schema = [];
  try {
    $sql = "SELECT table_name, column_name
            FROM information_schema.columns
            WHERE table_schema = DATABASE()";
    $st = $pdo->query($sql);
    foreach (($st ? $st->fetchAll(PDO::FETCH_ASSOC) : []) as $r) {
      $t = $r['table_name'] ?? null;
      $c = $r['column_name'] ?? null;
      if (!$t || !$c) continue;
      if (!isset($schema[$t])) $schema[$t] = [];
      $schema[$t][] = $c;
    }
  } catch (Throwable $e) {
    $schema = [];
  }
  return $schema;
}

function dash_table_exists(PDO $pdo, string $table): bool {
  $schema = dash_schema($pdo);
  return isset($schema[$table]);
}

function dash_cols(PDO $pdo, string $table): array {
  $schema = dash_schema($pdo);
  return $schema[$table] ?? [];
}

function dash_has_col(array $cols, string $name): bool {
  return in_array($name, $cols, true);
}

function dash_first_col(array $cols, array $candidates): ?string {
  foreach ($candidates as $c) {
    if (in_array($c, $cols, true)) return $c;
  }
  return null;
}

function dash_fetch_one(PDO $pdo, string $sql, array $params = []) {
  try {
    $st = $pdo->prepare($sql);
    $st->execute($params);
    return $st->fetchColumn();
  } catch (Throwable $e) {
    return null;
  }
}

function dash_fetch_one_cached(PDO $pdo, string $key, string $sql, array $params = []) {
  static $cache = [];
  if (array_key_exists($key, $cache)) return $cache[$key];
  $cache[$key] = dash_fetch_one($pdo, $sql, $params);
  return $cache[$key];
}

function dash_fetch_all(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 dash_fmt_int($n): string {
  return ($n === null || $n === '') ? '--' : number_format((int)$n, 0, ',', '.');
}

function dash_fmt_num($n, int $dec = 1): string {
  return ($n === null || $n === '') ? '--' : number_format((float)$n, $dec, ',', '.');
}

function dash_fmt_date(?string $v, bool $time = false): string {
  if (!$v) return '--';
  try {
    return (new DateTime($v))->format($time ? 'd/m/Y H:i' : 'd/m/Y');
  } catch (Throwable $e) {
    return h($v);
  }
}

function dash_time_ago(?string $v): string {
  if (!$v) return '--';
  try {
    $dt = new DateTime($v);
    $now = new DateTime();
    $sec = max(0, $now->getTimestamp() - $dt->getTimestamp());
    if ($sec < 3600) return floor($sec / 60) . ' min';
    if ($sec < 86400) return floor($sec / 3600) . ' h';
    return floor($sec / 86400) . ' días';
  } catch (Throwable $e) {
    return '--';
  }
}


function dash_num($n, float $default = 0.0): float {
  return is_numeric($n) ? (float)$n : $default;
}

function dash_que_revisar_hoy(PDO $pdo): array {
  $items = [];

  if (dash_table_exists($pdo, 'collares')) {
    $cols = dash_cols($pdo, 'collares');
    $teidCol = dash_first_col($cols, ['teid','imei','id_collar']);
    $caravanaCol = dash_first_col($cols, ['caravana','caravana_visual']);
    $estCol = dash_first_col($cols, ['establecimiento','establecimiento_ref']);
    $potCol = dash_first_col($cols, ['potrero','potrero_nombre']);
    $batCol = dash_first_col($cols, ['bateria_pct','bateria','battery_pct','battery']);
    $lastCol = dash_first_col($cols, ['last_report_at','ultima_lectura','fecha_ultima_lectura','updated_at','created_at']);

    if ($lastCol) {
      $rows = dash_fetch_all($pdo,
        "SELECT "
        . ($teidCol ? "`$teidCol` AS teid," : "NULL AS teid,")
        . ($caravanaCol ? "`$caravanaCol` AS caravana," : "NULL AS caravana,")
        . ($estCol ? "`$estCol` AS establecimiento," : "NULL AS establecimiento,")
        . ($potCol ? "`$potCol` AS potrero," : "NULL AS potrero,")
        . "`$lastCol` AS ultima_lectura
         FROM collares
         WHERE `$lastCol` IS NULL OR `$lastCol` < (NOW() - INTERVAL 24 HOUR)
         ORDER BY (`$lastCol` IS NULL) DESC, `$lastCol` ASC
         LIMIT 6"
      );
      foreach ($rows as $r) {
        $items[] = [
          'tipo' => 'conectividad',
          'nivel' => 'alto',
          'titulo' => 'Sin reporte reciente',
          'detalle' => trim('Caravana '.(($r['caravana'] ?? '') ?: '--').' · '.(($r['establecimiento'] ?? '') ?: 'Sin establecimiento')),
          'meta' => !empty($r['ultima_lectura']) ? 'Última lectura: '.dash_fmt_date((string)$r['ultima_lectura'], true).' · hace '.dash_time_ago((string)$r['ultima_lectura']) : 'Sin fecha de última lectura',
          'accion' => 'Revisar collar',
          'link' => 'collares.php'
        ];
      }
    }

    if ($batCol) {
      $rows = dash_fetch_all($pdo,
        "SELECT "
        . ($teidCol ? "`$teidCol` AS teid," : "NULL AS teid,")
        . ($caravanaCol ? "`$caravanaCol` AS caravana," : "NULL AS caravana,")
        . ($estCol ? "`$estCol` AS establecimiento," : "NULL AS establecimiento,")
        . "`$batCol` AS bateria
         FROM collares
         WHERE `$batCol` IS NOT NULL AND `$batCol` <= 20
         ORDER BY `$batCol` ASC
         LIMIT 6"
      );
      foreach ($rows as $r) {
        $items[] = [
          'tipo' => 'bateria',
          'nivel' => 'medio',
          'titulo' => 'Batería crítica',
          'detalle' => trim('Caravana '.(($r['caravana'] ?? '') ?: '--').' · '.dash_fmt_num($r['bateria'] ?? null, 0).'%' ),
          'meta' => (($r['establecimiento'] ?? '') ?: 'Sin establecimiento').' · Programar revisión o recarga',
          'accion' => 'Ver collares',
          'link' => 'collares.php'
        ];
      }
    }
  }

  if (dash_table_exists($pdo, 'health_flags')) {
    $cols = dash_cols($pdo, 'health_flags');
    $estadoCol = dash_first_col($cols, ['estado','severity','nivel']);
    $fechaCol = dash_first_col($cols, ['fecha','created_at','fecha_alerta','detected_at']);
    $nombreCol = dash_first_col($cols, ['nombre_vaca','animal','descripcion','flag','tipo']);
    $teidCol = dash_first_col($cols, ['teid','imei','id_collar']);
    $where = $estadoCol ? "WHERE `$estadoCol` NOT IN ('cerrada','resuelta','ok')" : "";
    $rows = dash_fetch_all($pdo,
      "SELECT "
      . ($teidCol ? "`$teidCol` AS teid," : "NULL AS teid,")
      . ($nombreCol ? "`$nombreCol` AS nombre," : "'Alerta sanitaria' AS nombre,")
      . ($estadoCol ? "`$estadoCol` AS estado," : "'activa' AS estado,")
      . ($fechaCol ? "`$fechaCol` AS fecha" : "NULL AS fecha")
      . " FROM health_flags $where "
      . ($fechaCol ? "ORDER BY `$fechaCol` DESC " : "")
      . "LIMIT 6"
    );
    foreach ($rows as $r) {
      $estadoTxt = (string)(($r['estado'] ?? '') ?: 'activa');
      $items[] = [
        'tipo' => 'salud',
        'nivel' => (stripos($estadoTxt, 'crit') !== False or stripos($estadoTxt, 'alto') !== False) and 'critico' or 'alto',
        'titulo' => 'Alerta sanitaria',
        'detalle' => (($r['nombre'] ?? '') ?: 'Evento sanitario').' · '.(($r['teid'] ?? '') ?: 'Sin collar'),
        'meta' => !empty($r['fecha']) ? 'Detectada: '.dash_fmt_date((string)$r['fecha'], true) : 'Pendiente de revisión',
        'accion' => 'Ir a salud',
        'link' => 'salud.php'
      ];
    }
  }

  if (dash_table_exists($pdo, 'potrero_pasto')) {
    $cols = dash_cols($pdo, 'potrero_pasto');
    $valorCol = dash_first_col($cols, ['kg_ms_ha','pasto_kg_ms_ha','disponibilidad_kg_ms_ha','disponibilidad','kgmsha']);
    $potCol = dash_first_col($cols, ['potrero','potrero_nombre','nombre']);
    $fechaCol = dash_first_col($cols, ['fecha','created_at','fecha_medicion']);
    if ($valorCol) {
      $rows = dash_fetch_all($pdo,
        "SELECT "
        . ($potCol ? "`$potCol` AS potrero," : "'Potrero' AS potrero,")
        . "`$valorCol` AS valor "
        . ($fechaCol ? ", `$fechaCol` AS fecha " : ", NULL AS fecha ")
        . "FROM potrero_pasto
           WHERE `$valorCol` IS NOT NULL AND `$valorCol` <= 1500
           ORDER BY `$valorCol` ASC
           LIMIT 6"
      );
      foreach ($rows as $r) {
        $items[] = [
          'tipo' => 'pastoreo',
          'nivel' => 'alto',
          'titulo' => 'Disponibilidad baja de pasto',
          'detalle' => (($r['potrero'] ?? '') ?: 'Potrero').' · '.dash_fmt_num($r['valor'] ?? null, 0).' kg MS/ha',
          'meta' => !empty($r['fecha']) ? 'Última medición: '.dash_fmt_date((string)$r['fecha']) : 'Conviene revisar carga o movimiento',
          'accion' => 'Ver pastoreo',
          'link' => 'pastoreo.php'
        ];
      }
    }
  }

  $priority = ['critico' => 0, 'alto' => 1, 'medio' => 2, 'bajo' => 3];
  usort($items, function($a, $b) use ($priority){
    $pa = $priority[$a['nivel'] ?? 'medio'] ?? 9;
    $pb = $priority[$b['nivel'] ?? 'medio'] ?? 9;
    if ($pa === $pb) return strcmp((string)($a['titulo'] ?? ''), (string)($b['titulo'] ?? ''));
    return $pa <=> $pb;
  });

  return array_slice($items, 0, 8);
}

function dash_estado_operativo(array $kpi): array {
  $online = (int)($kpi['online_24h'] ?? 0);
  $offline = (int)($kpi['sin_reporte_24h'] ?? 0);
  $battery = (int)($kpi['bateria_critica'] ?? 0);
  $health = (int)($kpi['alertas'] ?? 0);
  $risk = ($offline * 2) + ($battery * 2) + ($health * 3);

  $estado = 'Estable';
  $detalle = 'Operación bajo control';
  if ($risk >= 20) {
    $estado = 'Crítico';
    $detalle = 'Hay varias alertas que requieren atención inmediata';
  } elseif ($risk >= 8) {
    $estado = 'Atención';
    $detalle = 'Se detectaron eventos que conviene priorizar hoy';
  }

  return [
    'estado' => $estado,
    'detalle' => $detalle,
    'cobertura' => max(0, $online),
    'riesgo' => $risk,
  ];
}

function dash_resumen_ejecutivo(PDO $pdo, array $kpi): array {
  $animalesBase = null;
  if (dash_table_exists($pdo, 'animales_maestro')) {
    $animalesBase = (int)(dash_fetch_one_cached($pdo, 'animales_maestro_total_dash', "SELECT COUNT(*) FROM animales_maestro") ?? 0);
  }
  $animalesMonitoreados = (int)($kpi['animales'] ?? 0);
  $coberturaPct = ($animalesBase && $animalesBase > 0) ? round(($animalesMonitoreados / $animalesBase) * 100, 1) : null;

  return [
    'animales_base' => $animalesBase,
    'animales_monitoreados' => $animalesMonitoreados,
    'cobertura_pct' => $coberturaPct,
    'animales_riesgo' => (int)($kpi['alertas'] ?? 0) + (int)($kpi['bateria_critica'] ?? 0) + (int)($kpi['sin_reporte_24h'] ?? 0),
    'establecimientos_alerta' => null,
  ];
}

function dash_establecimientos_resumen(PDO $pdo): array {
  if (!dash_table_exists($pdo, 'collares')) return [];
  $cols = dash_cols($pdo, 'collares');
  $estCol = dash_first_col($cols, ['establecimiento','establecimiento_ref']);
  if (!$estCol) return [];

  $lastCol = dash_first_col($cols, ['last_report_at','ultima_lectura','fecha_ultima_lectura','updated_at','created_at']);
  $batCol = dash_first_col($cols, ['bateria_pct','bateria','battery_pct','battery']);
  $pesoCol = dash_first_col($cols, ['peso','peso_kg','peso_actual','kg']);

  $selects = [
    "`$estCol` AS establecimiento",
    "COUNT(*) AS total_collares",
  ];
  if ($lastCol) {
    $selects[] = "SUM(CASE WHEN `$lastCol` >= (NOW() - INTERVAL 1 DAY) THEN 1 ELSE 0 END) AS online_24h";
    $selects[] = "MAX(`$lastCol`) AS ultima_lectura";
  } else {
    $selects[] = "0 AS online_24h";
    $selects[] = "NULL AS ultima_lectura";
  }
  if ($batCol) {
    $selects[] = "SUM(CASE WHEN `$batCol` IS NOT NULL AND `$batCol` <= 20 THEN 1 ELSE 0 END) AS bateria_critica";
  } else {
    $selects[] = "0 AS bateria_critica";
  }
  if ($pesoCol) {
    $selects[] = "ROUND(AVG(CASE WHEN `$pesoCol` > 0 THEN `$pesoCol` END),1) AS peso_promedio";
  } else {
    $selects[] = "NULL AS peso_promedio";
  }

  $sql = "SELECT ".implode(", ", $selects)."
          FROM collares
          WHERE `$estCol` IS NOT NULL AND `$estCol` <> ''
          GROUP BY `$estCol`
          ORDER BY total_collares DESC, establecimiento ASC
          LIMIT 8";
  return dash_fetch_all($pdo, $sql);
}


$kpi = [
  'animales' => null,
  'collares' => null,
  'establecimientos' => null,
  'alertas' => null,
  'online_24h' => null,
  'sin_reporte_24h' => null,
  'celos_7d' => null,
  'bateria_critica' => null,
  'peso_promedio' => null,
  'pasto_promedio' => null,
  'consumo_diario' => null,
  'potreros_activos' => null,
  'racion_baja' => null,
  'costos_mes' => null,
];

$usd = [
  'moneda' => 'USD BCU',
  'etiqueta' => 'Dólar interbancario',
  'compra' => null,
  'venta' => null,
  'fecha' => null,
  'estado' => 'Sin datos',
];

$usdBrou = [
  'moneda' => 'USD BROU',
  'etiqueta' => 'Dólar pizarra',
  'compra' => null,
  'venta' => null,
  'fecha' => null,
  'estado' => 'Sin datos',
];

$actividad = [];
$alertas = [];
$potreros = [];
$ultimaLectura = null;
$alertasRacionActivas = 0;

$grafPesosRecientes = [];
$grafEvolucion = [];
$grafCurva = [];
$resumenPesos = [
  'total_historial' => 0,
  'animales_con_historial' => 0,
  'ultima_pesada' => null,
];
$establecimientosFiltro = [];

if (dash_table_exists($pdo, 'collares')) {
  $cols = dash_cols($pdo, 'collares');

  $kpi['collares'] = (int)(dash_fetch_one_cached($pdo, 'collares_total', "SELECT COUNT(*) FROM collares") ?? 0);

  if (dash_has_col($cols, 'activo')) {
    $kpi['animales'] = (int)(dash_fetch_one_cached($pdo, 'collares_activos_total', "SELECT COUNT(*) FROM collares WHERE COALESCE(activo,1)=1") ?? 0);
  } else {
    $kpi['animales'] = $kpi['collares'];
  }

  $lastCol = dash_first_col($cols, ['last_report_at','ultima_lectura','fecha_ultima_lectura','updated_at','created_at']);
  if ($lastCol) {
    $kpi['online_24h'] = (int)(dash_fetch_one_cached($pdo, 'collares_online_24h_'.$lastCol, "SELECT COUNT(*) FROM collares WHERE `$lastCol` >= (NOW() - INTERVAL 1 DAY)") ?? 0);
    $kpi['sin_reporte_24h'] = (int)(dash_fetch_one_cached($pdo, 'collares_offline_24h_'.$lastCol, "SELECT COUNT(*) FROM collares WHERE `$lastCol` IS NULL OR `$lastCol` < (NOW() - INTERVAL 1 DAY)") ?? 0);
    $ultimaLectura = dash_fetch_one_cached($pdo, 'collares_ultima_lectura_'.$lastCol, "SELECT MAX(`$lastCol`) FROM collares");
  }

  $battCol = dash_first_col($cols, ['bateria_pct','bateria','battery_pct','battery']);
  if ($battCol) {
    $kpi['bateria_critica'] = (int)(dash_fetch_one_cached($pdo, 'collares_bateria_critica_'.$battCol, "SELECT COUNT(*) FROM collares WHERE `$battCol` IS NOT NULL AND `$battCol` <= 20") ?? 0);
  }

  $pesoCol = dash_first_col($cols, ['peso','peso_kg','peso_actual','kg']);
  if ($pesoCol) {
    $kpi['peso_promedio'] = dash_fetch_one_cached($pdo, 'collares_peso_promedio_'.$pesoCol, "SELECT AVG(`$pesoCol`) FROM collares WHERE `$pesoCol` IS NOT NULL AND `$pesoCol` > 0");
  }

  $teidCol = dash_first_col($cols, ['teid','imei','id_collar']);
  $nombreCol = dash_first_col($cols, ['nombre_vaca','nombre','animal_nombre']);
  $caravanaCol = dash_first_col($cols, ['caravana','caravana_visual']);
  $estCol = dash_first_col($cols, ['establecimiento','establecimiento_ref']);
  $potCol = dash_first_col($cols, ['potrero','potrero_nombre']);
  $lastShowCol = $lastCol;
  $battShowCol = $battCol;

  $select = [];
  $select[] = $teidCol ? "`$teidCol` AS teid" : "NULL AS teid";
  $select[] = $nombreCol ? "`$nombreCol` AS nombre" : "NULL AS nombre";
  $select[] = $caravanaCol ? "`$caravanaCol` AS caravana" : "NULL AS caravana";
  $select[] = $estCol ? "`$estCol` AS establecimiento" : "NULL AS establecimiento";
  $select[] = $potCol ? "`$potCol` AS potrero" : "NULL AS potrero";
  $select[] = $lastShowCol ? "`$lastShowCol` AS ultima_lectura" : "NULL AS ultima_lectura";
  $select[] = $battShowCol ? "`$battShowCol` AS bateria" : "NULL AS bateria";

  $actividad = dash_fetch_all(
    $pdo,
    "SELECT ".implode(", ", $select)."
     FROM collares
     ORDER BY ".($lastShowCol ? "`$lastShowCol` DESC" : ($teidCol ? "`$teidCol` ASC" : "1"))."
     LIMIT 8"
  );
}

if (dash_table_exists($pdo, 'establecimientos')) {
  $kpi['establecimientos'] = (int)(dash_fetch_one_cached($pdo, 'establecimientos_total', "SELECT COUNT(*) FROM establecimientos") ?? 0);
}

if (dash_table_exists($pdo, 'health_flags')) {
  $cols = dash_cols($pdo, 'health_flags');
  $estadoCol = dash_first_col($cols, ['estado','severity','nivel']);
  $fechaCol = dash_first_col($cols, ['fecha','created_at','fecha_alerta','detected_at']);
  $nombreCol = dash_first_col($cols, ['nombre_vaca','animal','descripcion','flag']);
  $teidCol = dash_first_col($cols, ['teid','imei','id_collar']);

  if ($estadoCol) {
    $kpi['alertas'] = (int)(dash_fetch_one($pdo, "SELECT COUNT(*) FROM health_flags WHERE `$estadoCol` NOT IN ('cerrada','resuelta','ok')") ?? 0);
  } else {
    $kpi['alertas'] = (int)(dash_fetch_one_cached($pdo, 'health_flags_total', "SELECT COUNT(*) FROM health_flags") ?? 0);
  }

  $sel = [];
  $sel[] = $teidCol ? "`$teidCol` AS teid" : "NULL AS teid";
  $sel[] = $nombreCol ? "`$nombreCol` AS nombre" : "NULL AS nombre";
  $sel[] = $estadoCol ? "`$estadoCol` AS estado" : "'activa' AS estado";
  $sel[] = $fechaCol ? "`$fechaCol` AS fecha" : "NULL AS fecha";

  $order = $fechaCol ? "`$fechaCol` DESC" : "1";
  $alertas = dash_fetch_all($pdo, "SELECT ".implode(", ", $sel)." FROM health_flags ORDER BY {$order} LIMIT 8");
}

if ($kpi['alertas'] === null && dash_table_exists($pdo, 'alertas_activas')) {
  $kpi['alertas'] = (int)(dash_fetch_one_cached($pdo, 'alertas_activas_total', "SELECT COUNT(*) FROM alertas_activas") ?? 0);
}

if (dash_table_exists($pdo, 'alertas_racion')) {
  $colsAr = dash_cols($pdo, 'alertas_racion');
  if (dash_has_col($colsAr, 'estado')) {
    $alertasRacionActivas = (int)(dash_fetch_one_cached($pdo, 'alertas_racion_activas_total', "SELECT COUNT(*) FROM alertas_racion WHERE estado = 'activa'") ?? 0);
  } else {
    $alertasRacionActivas = (int)(dash_fetch_one_cached($pdo, 'alertas_racion_total', "SELECT COUNT(*) FROM alertas_racion") ?? 0);
  }

  if ($kpi['alertas'] === null) {
    $kpi['alertas'] = $alertasRacionActivas;
  } else {
    $kpi['alertas'] += $alertasRacionActivas;
  }
}

if (dash_table_exists($pdo, 'celos_detectados')) {
  $cols = dash_cols($pdo, 'celos_detectados');
  $fechaCol = dash_first_col($cols, ['fecha','created_at','detected_at','fecha_celo']);
  if ($fechaCol) {
    $kpi['celos_7d'] = (int)(dash_fetch_one($pdo, "SELECT COUNT(*) FROM celos_detectados WHERE `$fechaCol` >= (NOW() - INTERVAL 7 DAY)") ?? 0);
  } else {
    $kpi['celos_7d'] = (int)(dash_fetch_one_cached($pdo, 'celos_detectados_total', "SELECT COUNT(*) FROM celos_detectados") ?? 0);
  }
}

if (dash_table_exists($pdo, 'potreros')) {
  $cols = dash_cols($pdo, 'potreros');
  if (dash_has_col($cols, 'activo')) {
    $kpi['potreros_activos'] = (int)(dash_fetch_one_cached($pdo, 'potreros_activos_total', "SELECT COUNT(*) FROM potreros WHERE COALESCE(activo,1)=1") ?? 0);
  } else {
    $kpi['potreros_activos'] = (int)(dash_fetch_one_cached($pdo, 'potreros_total', "SELECT COUNT(*) FROM potreros") ?? 0);
  }
}

if (dash_table_exists($pdo, 'potrero_pasto')) {
  $cols = dash_cols($pdo, 'potrero_pasto');
  $valorCol = dash_first_col($cols, ['kg_ms_ha','pasto_kg_ms_ha','disponibilidad_kg_ms_ha','disponibilidad','kgmsha']);
  $potCol = dash_first_col($cols, ['potrero','potrero_nombre','nombre']);
  $fechaCol = dash_first_col($cols, ['fecha','created_at','fecha_medicion']);
  if ($valorCol) {
    $kpi['pasto_promedio'] = dash_fetch_one($pdo, "SELECT AVG(`$valorCol`) FROM potrero_pasto WHERE `$valorCol` IS NOT NULL AND `$valorCol` > 0");
    $potreros = dash_fetch_all(
      $pdo,
      "SELECT ".($potCol ? "`$potCol` AS potrero," : "NULL AS potrero,")."
              `$valorCol` AS valor
              ".($fechaCol ? ", `$fechaCol` AS fecha " : ", NULL AS fecha ")."
       FROM potrero_pasto
       WHERE `$valorCol` IS NOT NULL
       ORDER BY `$valorCol` DESC
       LIMIT 8"
    );
  }
}

if (dash_table_exists($pdo, 'consumo_actual')) {
  $cols = dash_cols($pdo, 'consumo_actual');
  $valorCol = dash_first_col($cols, ['consumo_kg_dia','consumo_diario','kg_dia','consumo']);
  if ($valorCol) {
    $kpi['consumo_diario'] = dash_fetch_one($pdo, "SELECT AVG(`$valorCol`) FROM consumo_actual WHERE `$valorCol` IS NOT NULL AND `$valorCol` > 0");
  }
}

if (dash_table_exists($pdo, 'racion_stock')) {
  $colsRs = dash_cols($pdo, 'racion_stock');
  if (dash_has_col($colsRs, 'stock_actual') && dash_has_col($colsRs, 'stock_minimo_alerta')) {
    $kpi['racion_baja'] = (int)(dash_fetch_one_cached(
      $pdo,
      'racion_stock_baja_total',
      "SELECT COUNT(*)
       FROM racion_stock
       WHERE stock_minimo_alerta IS NOT NULL
         AND stock_minimo_alerta > 0
         AND stock_actual IS NOT NULL
         AND stock_actual <= stock_minimo_alerta"
    ) ?? 0);
  }
}

if (dash_table_exists($pdo, 'costos_campo')) {
  $colsCc = dash_cols($pdo, 'costos_campo');
  $importeColCc = dash_first_col($colsCc, ['importe','monto','valor']);
  $fechaColCc = dash_first_col($colsCc, ['fecha','created_at','fecha_costo']);

  if ($importeColCc && $fechaColCc) {
    $kpi['costos_mes'] = dash_fetch_one_cached(
      $pdo,
      'costos_campo_mes_actual',
      "SELECT COALESCE(SUM(`$importeColCc`),0)
       FROM costos_campo
       WHERE `$fechaColCc` >= DATE_FORMAT(CURDATE(), '%Y-%m-01')
         AND `$fechaColCc` < DATE_FORMAT(DATE_ADD(CURDATE(), INTERVAL 1 MONTH), '%Y-%m-01')"
    );
  }
}

/* OPTIMIZADO: cotización BCU */
if (dash_table_exists($pdo, 'cotizaciones_bcu')) {
  $cols = dash_cols($pdo, 'cotizaciones_bcu');
  $fechaCol = dash_first_col($cols, ['fecha','fecha_cotizacion','created_at']);
  $ventaCol = dash_first_col($cols, ['venta','valor_venta']);
  $compraCol = dash_first_col($cols, ['compra','valor_compra']);
  $monedaCol = dash_first_col($cols, ['moneda','iso','codigo_iso']);
  $codigoCol = dash_first_col($cols, ['moneda_codigo','codigo']);

  $whereSql = '';
  $paramsCot = [];

  if ($codigoCol) {
    $whereSql = "WHERE `$codigoCol` = :codigo_usd";
    $paramsCot[':codigo_usd'] = 2225;
  } elseif ($monedaCol) {
    $whereSql = "WHERE (`$monedaCol` LIKE :usd1 OR `$monedaCol` LIKE :usd2)";
    $paramsCot[':usd1'] = '%USD%';
    $paramsCot[':usd2'] = '%DLS%';
  }

  $sql = "SELECT "
       . ($monedaCol ? "`$monedaCol` AS moneda," : "'USD BCU' AS moneda,")
       . ($compraCol ? "`$compraCol` AS compra," : "NULL AS compra,")
       . ($ventaCol ? "`$ventaCol` AS venta," : "NULL AS venta,")
       . ($fechaCol ? "`$fechaCol` AS fecha" : "NULL AS fecha")
       . " FROM cotizaciones_bcu {$whereSql} "
       . ($fechaCol ? "ORDER BY `$fechaCol` DESC, id DESC " : "")
       . "LIMIT 1";

  try {
    $st = $pdo->prepare($sql);
    $st->execute($paramsCot);
    $row = $st->fetchAll(PDO::FETCH_ASSOC);
  } catch (Throwable $e) {
    $row = [];
  }

  if ($row) {
    $usd = array_merge($usd, $row[0]);
    if (!empty($usd['fecha'])) {
      try {
        $f = (new DateTime((string)$usd['fecha']))->format('Y-m-d');
        $usd['estado'] = ($f === date('Y-m-d')) ? 'Actualizado hoy' : 'Última carga';
      } catch (Throwable $e) {
        $usd['estado'] = 'Cargado';
      }
    }
  }
}

/* OPTIMIZADO: cotización BROU */
if (dash_table_exists($pdo, 'cotizaciones_referencia')) {
  $cols = dash_cols($pdo, 'cotizaciones_referencia');
  $fechaCol = dash_first_col($cols, ['fecha','fecha_cotizacion','created_at']);
  $ventaCol = dash_first_col($cols, ['venta','valor_venta']);
  $compraCol = dash_first_col($cols, ['compra','valor_compra']);
  $monedaCol = dash_first_col($cols, ['moneda','moneda_codigo','codigo_iso']);
  $fuenteCol = dash_first_col($cols, ['fuente','emisor']);

  $wherePartes = [];
  $paramsBrou = [];

  if ($fuenteCol) {
    $wherePartes[] = "`$fuenteCol` = :fuente";
    $paramsBrou[':fuente'] = 'BROU';
  }
  if ($monedaCol) {
    $wherePartes[] = "(`$monedaCol` = :moneda_exacta OR `$monedaCol` LIKE :moneda_like)";
    $paramsBrou[':moneda_exacta'] = 'USD';
    $paramsBrou[':moneda_like'] = '%USD%';
  }

  $whereSql = $wherePartes ? "WHERE " . implode(" AND ", $wherePartes) : "";

  $sql = "SELECT "
       . ($monedaCol ? "`$monedaCol` AS moneda," : "'USD BROU' AS moneda,")
       . ($compraCol ? "`$compraCol` AS compra," : "NULL AS compra,")
       . ($ventaCol ? "`$ventaCol` AS venta," : "NULL AS venta,")
       . ($fechaCol ? "`$fechaCol` AS fecha" : "NULL AS fecha")
       . " FROM cotizaciones_referencia {$whereSql} "
       . ($fechaCol ? "ORDER BY `$fechaCol` DESC, id DESC " : "")
       . "LIMIT 1";

  try {
    $st = $pdo->prepare($sql);
    $st->execute($paramsBrou);
    $row = $st->fetchAll(PDO::FETCH_ASSOC);
  } catch (Throwable $e) {
    $row = [];
  }

  if ($row) {
    $usdBrou = array_merge($usdBrou, $row[0]);
    if (!empty($usdBrou['fecha'])) {
      try {
        $f = (new DateTime((string)$usdBrou['fecha']))->format('Y-m-d');
        $usdBrou['estado'] = ($f === date('Y-m-d')) ? 'Actualizado hoy' : 'Última carga';
      } catch (Throwable $e) {
        $usdBrou['estado'] = 'Cargado';
      }
    }
  }
}

/* Opciones de filtro por establecimiento */
$colsAmFiltro = dash_table_exists($pdo, 'animales_maestro') ? dash_cols($pdo, 'animales_maestro') : [];
$estFiltroColAm = dash_first_col($colsAmFiltro, ['establecimiento_ref','establecimiento']);
if ($estFiltroColAm && dash_table_exists($pdo, 'animales_maestro')) {
  $establecimientosFiltro = dash_fetch_all(
    $pdo,
    "SELECT DISTINCT `$estFiltroColAm` AS establecimiento
     FROM animales_maestro
     WHERE `$estFiltroColAm` IS NOT NULL
       AND `$estFiltroColAm` <> ''
     ORDER BY `$estFiltroColAm` ASC"
  );
}

/* OPTIMIZADO: gráficos de historial de pesos */
if (dash_table_exists($pdo, 'historial_pesos')) {
  $colsHp = dash_cols($pdo, 'historial_pesos');
  $colsAm = dash_table_exists($pdo, 'animales_maestro') ? dash_cols($pdo, 'animales_maestro') : [];

  $pesoColHp = dash_first_col($colsHp, ['peso_kg','peso','kg']);
  $fechaColHp = dash_first_col($colsHp, ['fecha_dato','fecha','created_at']);
  $caravanaColHp = dash_first_col($colsHp, ['caravana']);

  $caravanaColAm = dash_first_col($colsAm, ['id_rp']);
  $nacColAm = dash_first_col($colsAm, ['fecha_nacimiento']);
  $estColAm = dash_first_col($colsAm, ['establecimiento_ref','establecimiento']);

  $hayFiltro = ($filtroCaravana !== '' || $filtroEstablecimiento !== '');

  if ($pesoColHp && $fechaColHp && $caravanaColHp) {
    $joinAm = '';
    $whereExtra = '';
    $paramsExtra = [];

    if ($filtroEstablecimiento !== '' && $caravanaColAm && $estColAm) {
      $joinAm = " INNER JOIN animales_maestro am ON am.`$caravanaColAm` = hp.`$caravanaColHp` ";
      $whereExtra .= " AND am.`$estColAm` = :establecimiento ";
      $paramsExtra[':establecimiento'] = $filtroEstablecimiento;
    }

    if ($filtroCaravana !== '') {
      $whereExtra .= " AND hp.`$caravanaColHp` = :caravana ";
      $paramsExtra[':caravana'] = $filtroCaravana;
    }

    $resumenPesos['ultima_pesada'] = dash_fetch_one($pdo, "
      SELECT MAX(hp.`$fechaColHp`)
      FROM historial_pesos hp
      $joinAm
      WHERE hp.`$fechaColHp` IS NOT NULL
      $whereExtra
    ", $paramsExtra);

    if ($hayFiltro) {
      $resumenPesos['total_historial'] = (int)(dash_fetch_one($pdo, "
        SELECT COUNT(*)
        FROM historial_pesos hp
        $joinAm
        WHERE hp.`$pesoColHp` IS NOT NULL
          AND hp.`$pesoColHp` > 0
          $whereExtra
      ", $paramsExtra) ?? 0);

      $resumenPesos['animales_con_historial'] = (int)(dash_fetch_one($pdo, "
        SELECT COUNT(DISTINCT hp.`$caravanaColHp`)
        FROM historial_pesos hp
        $joinAm
        WHERE hp.`$caravanaColHp` IS NOT NULL
          AND hp.`$caravanaColHp` <> ''
          $whereExtra
      ", $paramsExtra) ?? 0);
    } else {
      $resumenPesos['total_historial'] = (int)(dash_fetch_one_cached(
        $pdo,
        'historial_pesos_total_fast',
        "SELECT COUNT(*) FROM historial_pesos"
      ) ?? 0);

      $resumenPesos['animales_con_historial'] = (int)(dash_fetch_one_cached(
        $pdo,
        'historial_pesos_animales_fast',
        "SELECT COUNT(DISTINCT `$caravanaColHp`)
         FROM historial_pesos
         WHERE `$caravanaColHp` IS NOT NULL
           AND `$caravanaColHp` <> ''"
      ) ?? 0);
    }

    $grafPesosRecientes = dash_fetch_all($pdo, "
      SELECT
        hp.`$caravanaColHp` AS caravana,
        hp.`$fechaColHp` AS fecha,
        hp.`$pesoColHp` AS peso
      FROM historial_pesos hp
      $joinAm
      WHERE hp.`$pesoColHp` IS NOT NULL
        AND hp.`$pesoColHp` > 0
        $whereExtra
      ORDER BY hp.`$fechaColHp` DESC
      LIMIT 12
    ", $paramsExtra);

    $grafPesosRecientes = array_reverse($grafPesosRecientes);

    $grafEvolucion = dash_fetch_all($pdo, "
      SELECT
        DATE_FORMAT(hp.`$fechaColHp`, '%Y-%m') AS periodo,
        ROUND(AVG(hp.`$pesoColHp`), 2) AS promedio,
        COUNT(*) AS muestras
      FROM historial_pesos hp
      $joinAm
      WHERE hp.`$pesoColHp` IS NOT NULL
        AND hp.`$pesoColHp` > 0
        AND hp.`$fechaColHp` IS NOT NULL
        AND hp.`$fechaColHp` >= (CURDATE() - INTERVAL 12 MONTH)
        $whereExtra
      GROUP BY DATE_FORMAT(hp.`$fechaColHp`, '%Y-%m')
      ORDER BY periodo ASC
    ", $paramsExtra);
  }

  if ($pesoColHp && $fechaColHp && $caravanaColHp && $caravanaColAm && $nacColAm) {
    $whereCurva = '';
    $paramsCurva = [];

    if ($filtroCaravana !== '') {
      $whereCurva .= " AND hp.`$caravanaColHp` = :caravana_curva ";
      $paramsCurva[':caravana_curva'] = $filtroCaravana;
    }

    if ($filtroEstablecimiento !== '' && $estColAm) {
      $whereCurva .= " AND am.`$estColAm` = :establecimiento_curva ";
      $paramsCurva[':establecimiento_curva'] = $filtroEstablecimiento;
    }

    $whereCurva .= " AND hp.`$fechaColHp` >= DATE_SUB(CURDATE(), INTERVAL 24 MONTH) ";

    $grafCurva = dash_fetch_all($pdo, "
      SELECT
        TIMESTAMPDIFF(MONTH, am.`$nacColAm`, hp.`$fechaColHp`) AS edad_meses,
        ROUND(AVG(hp.`$pesoColHp`), 2) AS peso_promedio,
        COUNT(*) AS muestras
      FROM historial_pesos hp
      INNER JOIN animales_maestro am
        ON am.`$caravanaColAm` = hp.`$caravanaColHp`
      WHERE am.`$nacColAm` IS NOT NULL
        AND hp.`$fechaColHp` IS NOT NULL
        AND hp.`$pesoColHp` IS NOT NULL
        AND hp.`$pesoColHp` > 0
        AND TIMESTAMPDIFF(MONTH, am.`$nacColAm`, hp.`$fechaColHp`) BETWEEN 0 AND 36
        $whereCurva
      GROUP BY TIMESTAMPDIFF(MONTH, am.`$nacColAm`, hp.`$fechaColHp`)
      ORDER BY edad_meses ASC
      LIMIT 24
    ", $paramsCurva);
  }
}


$queRevisarHoy = dash_que_revisar_hoy($pdo);
$estadoOperativo = dash_estado_operativo($kpi);
$resumenEjecutivo = dash_resumen_ejecutivo($pdo, $kpi);
$establecimientosResumen = dash_establecimientos_resumen($pdo);

$chartPesosLabels = [];
$chartPesosData = [];
foreach ($grafPesosRecientes as $r) {
  $chartPesosLabels[] = ($r['caravana'] ?: '--') . ' · ' . dash_fmt_date($r['fecha'] ?? null);
  $chartPesosData[] = isset($r['peso']) ? (float)$r['peso'] : null;
}

$chartEvolucionLabels = [];
$chartEvolucionData = [];
foreach ($grafEvolucion as $r) {
  $chartEvolucionLabels[] = (string)$r['periodo'];
  $chartEvolucionData[] = isset($r['promedio']) ? (float)$r['promedio'] : null;
}

$chartCurvaLabels = [];
$chartCurvaData = [];
foreach ($grafCurva as $r) {
  $chartCurvaLabels[] = (string)$r['edad_meses'] . ' m';
  $chartCurvaData[] = isset($r['peso_promedio']) ? (float)$r['peso_promedio'] : null;
}
?>
<!doctype html>
<html lang="es">
<head>
<meta charset="utf-8">
<title>Bovintel | Dashboard</title>
<meta name="viewport" content="width=device-width,initial-scale=1">
<script src="https://cdn.jsdelivr.net/npm/chart.js" defer></script>
<style>
:root{
  --brand:#0f172a;
  --brand2:#020617;
  --accent:#16a34a;
  --bg:#f3f4f6;
  --b:#e5e7eb;
  --mut:#6b7280;
  --card:#fff;
  --danger:#b91c1c;
  --warn:#b45309;
  --ok:#166534;
}
*{box-sizing:border-box}
body{margin:0;font-family:system-ui,Segoe UI,Roboto,Arial;background:var(--bg);color:#111827}
.app{display:flex;min-height:100vh}
.main{flex:1;display:flex;flex-direction:column;min-width:0}
.topbar{
  background:#fff;border-bottom:1px solid var(--b);padding:10px 18px;
  display:flex;align-items:center;justify-content:space-between;gap:14px;
  position:sticky;top:0;z-index:10;
}
.topbar-left{display:flex;align-items:center;gap:12px;min-width:0}
.hamb{
  display:none;border:1px solid var(--b);background:#fff;border-radius:10px;
  padding:8px 10px;cursor:pointer
}
.topbar-title{font-weight:800;font-size:18px;color:var(--brand);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.topbar-sub{font-size:12px;color:var(--mut)}
.topbar-right{display:flex;align-items:center;gap:10px;flex-wrap:wrap;justify-content:flex-end}
.currency-wrap{display:flex;align-items:stretch;gap:10px;flex-wrap:wrap}
.currency-tools{
  display:flex;
  align-items:center;
  justify-content:center;
}
.btn-refresh-cot{
  display:inline-flex;
  align-items:center;
  justify-content:center;
  height:28px;
  padding:0 10px;
  border-radius:999px;
  border:1px solid #bbf7d0;
  background:#fff;
  color:#166534;
  text-decoration:none;
  font-size:11px;
  font-weight:800;
  line-height:1;
  white-space:nowrap;
  box-shadow:0 4px 10px rgba(22,163,74,.08);
}
.btn-refresh-cot:hover{
  background:#f0fdf4;
}
.currency-card{
  min-width:230px;background:#f0fdf4;border:1px solid #bbf7d0;border-radius:16px;
  padding:10px 12px;box-shadow:0 8px 20px rgba(22,163,74,.08)
}
.currency-head{display:flex;justify-content:space-between;gap:8px;align-items:center}
.currency-title{font-size:12px;font-weight:800;color:var(--ok);text-transform:uppercase;letter-spacing:.04em}
.currency-state{font-size:11px;color:var(--ok);background:#dcfce7;border-radius:999px;padding:3px 8px}
.currency-label{font-size:11px;color:var(--mut);margin-top:4px}
.currency-body{display:flex;gap:16px;margin-top:8px}
.currency-item small{display:block;color:var(--mut);font-size:11px}
.currency-item strong{font-size:20px;line-height:1.15}
.flash-msg{
  margin:12px 18px 0;
  padding:10px 12px;
  border-radius:12px;
  font-size:13px;
  border:1px solid var(--b);
  background:#fff;
}
.flash-ok{
  color:#166534;
  background:#dcfce7;
  border-color:#bbf7d0;
}
.flash-error{
  color:#991b1b;
  background:#fee2e2;
  border-color:#fecaca;
}
.layout{padding:16px 18px 28px;max-width:1400px}
.kpi-grid{display:grid;grid-template-columns:repeat(4,1fr);gap:14px}
.hero-grid{display:grid;grid-template-columns:1.35fr .95fr;gap:16px;margin-bottom:16px}
.hero-card,.hero-side,.review-card{
  background:var(--card);border-radius:18px;border:1px solid var(--b);
  box-shadow:0 10px 25px rgba(15,23,42,.06)
}
.hero-card{padding:18px}
.hero-eyebrow{display:inline-flex;align-items:center;gap:8px;padding:6px 10px;border-radius:999px;background:#ecfdf5;color:var(--ok);font-size:12px;font-weight:800}
.hero-title{font-size:30px;font-weight:900;line-height:1.05;color:var(--brand);margin-top:12px}
.hero-sub{font-size:14px;color:var(--mut);margin-top:8px;max-width:60ch}
.executive-grid{display:grid;grid-template-columns:repeat(4,1fr);gap:12px;margin-top:16px}
.executive-pill{background:#f8fafc;border:1px solid var(--b);border-radius:14px;padding:12px}
.executive-pill .label{font-size:11px;color:var(--mut);margin-bottom:6px}
.executive-pill .value{font-size:22px;font-weight:900;color:var(--brand);line-height:1.1}
.executive-pill .note{font-size:12px;color:var(--mut);margin-top:4px}
.hero-side{padding:18px;display:flex;flex-direction:column;gap:12px}
.status-chip{display:inline-flex;align-items:center;gap:8px;padding:7px 10px;border-radius:999px;font-size:12px;font-weight:800}
.status-chip.ok{background:#dcfce7;color:#166534}
.status-chip.warn{background:#fef3c7;color:#92400e}
.status-chip.danger{background:#fee2e2;color:#991b1b}
.side-card{background:#f8fafc;border:1px solid var(--b);border-radius:14px;padding:12px}
.side-card-title{font-size:12px;color:var(--mut);margin-bottom:6px}
.side-card-value{font-size:24px;font-weight:900;color:var(--brand)}
.review-grid{display:grid;grid-template-columns:repeat(4,1fr);gap:12px}
.review-card{padding:14px}
.review-top{display:flex;justify-content:space-between;align-items:flex-start;gap:8px;margin-bottom:8px}
.review-title{font-size:14px;font-weight:800;color:var(--brand)}
.review-detail{font-size:13px;color:#111827;min-height:38px}
.review-meta{font-size:12px;color:var(--mut);margin-top:8px;min-height:32px}
.review-action{margin-top:12px;display:inline-flex;align-items:center;justify-content:center;padding:9px 12px;border-radius:10px;text-decoration:none;font-weight:800;border:1px solid var(--b);background:#fff;color:#111827}
.review-card.critico{border-color:#fecaca;background:#fff7f7}
.review-card.alto{border-color:#fde68a;background:#fffdf5}
.review-card.medio{border-color:#bfdbfe;background:#f8fbff}
.review-card.bajo{border-color:#d1fae5;background:#f6fffb}
.review-tag{font-size:11px;font-weight:800;padding:4px 8px;border-radius:999px}
.review-card.critico .review-tag{background:#fee2e2;color:#991b1b}
.review-card.alto .review-tag{background:#fef3c7;color:#92400e}
.review-card.medio .review-tag{background:#dbeafe;color:#1d4ed8}
.review-card.bajo .review-tag{background:#dcfce7;color:#166534}
.kpi-card,.panel{
  background:var(--card);border-radius:16px;border:1px solid var(--b);
  box-shadow:0 10px 25px rgba(15,23,42,.06)
}
.kpi-card{padding:14px}
.kpi-label{font-size:12px;color:var(--mut);margin-bottom:8px}
.kpi-value{font-size:28px;font-weight:900;line-height:1.05}
.kpi-note{font-size:12px;color:var(--mut);margin-top:6px}
.content-grid{display:grid;grid-template-columns:1.5fr 1fr;gap:16px;margin-top:16px}
.panel-head{display:flex;justify-content:space-between;align-items:center;gap:10px;padding:14px 16px;border-bottom:1px solid var(--b)}
.panel-title{font-size:15px;font-weight:800}
.panel-body{padding:14px 16px}
.table-wrap{overflow:auto}
table{width:100%;border-collapse:collapse}
th,td{padding:10px 8px;border-bottom:1px solid var(--b);font-size:13px;text-align:left;vertical-align:top}
th{font-size:12px;color:var(--mut);text-transform:uppercase;letter-spacing:.03em}
.badge{display:inline-block;padding:3px 8px;border-radius:999px;font-size:11px;font-weight:700}
.badge-ok{background:#dcfce7;color:#166534}
.badge-warn{background:#fef3c7;color:#92400e}
.badge-danger{background:#fee2e2;color:#991b1b}
.quick-grid{display:grid;grid-template-columns:repeat(4,1fr);gap:12px}
.quick-link{
  display:flex;align-items:center;justify-content:center;min-height:72px;padding:12px;
  border-radius:14px;border:1px solid var(--b);background:#f9fafb;text-decoration:none;
  color:#0f172a;font-weight:700
}
.quick-link:hover{background:#eef2ff}
.muted{color:var(--mut)}
.overlay{display:none;position:fixed;inset:0;background:rgba(0,0,0,.35);z-index:40}
.charts-grid{
  display:grid;
  grid-template-columns:repeat(3,1fr);
  gap:16px;
  margin-top:16px;
}
.chart-card{
  background:var(--card);
  border-radius:16px;
  border:1px solid var(--b);
  box-shadow:0 10px 25px rgba(15,23,42,.06);
  overflow:hidden;
}
.chart-head{
  display:flex;
  justify-content:space-between;
  align-items:flex-start;
  gap:10px;
  padding:14px 16px;
  border-bottom:1px solid var(--b);
}
.chart-title{
  font-size:15px;
  font-weight:800;
}
.chart-sub{
  font-size:12px;
  color:var(--mut);
  margin-top:3px;
}
.chart-body{
  padding:14px 16px 10px;
}
.chart-box{
  position:relative;
  height:300px;
}
.chart-kpis{
  display:grid;
  grid-template-columns:repeat(3,1fr);
  gap:10px;
  margin-top:12px;
}
.mini-kpi{
  background:#f9fafb;
  border:1px solid var(--b);
  border-radius:12px;
  padding:10px;
}
.mini-kpi-label{
  font-size:11px;
  color:var(--mut);
  margin-bottom:4px;
}
.mini-kpi-value{
  font-size:18px;
  font-weight:800;
  color:var(--brand);
}
.filter-grid{
  display:grid;
  grid-template-columns:1fr 1fr auto auto;
  gap:12px;
  align-items:end;
}
.filter-field label{
  display:block;
  font-size:12px;
  color:var(--mut);
  margin-bottom:6px;
}
.filter-input,
.filter-select{
  width:100%;
  padding:10px 12px;
  border:1px solid var(--b);
  border-radius:10px;
  background:#fff;
  font-size:14px;
}
.btn-filter,
.btn-clear{
  display:inline-flex;
  align-items:center;
  justify-content:center;
  min-height:42px;
  padding:0 16px;
  border-radius:10px;
  text-decoration:none;
  font-weight:700;
  border:1px solid var(--b);
}
.btn-filter{
  background:#16a34a;
  color:#fff;
  border-color:#16a34a;
}
.btn-clear{
  background:#fff;
  color:#111827;
}

@media(max-width:1180px){
  .hero-grid{grid-template-columns:1fr}
  .executive-grid{grid-template-columns:repeat(2,1fr)}
  .review-grid{grid-template-columns:repeat(2,1fr)}
  .kpi-grid{grid-template-columns:repeat(3,1fr)}
  .quick-grid{grid-template-columns:repeat(2,1fr)}
  .charts-grid{grid-template-columns:1fr 1fr}
}
@media(max-width:980px){
  .hamb{display:inline-flex;align-items:center;gap:8px}
  .sidebar{position:fixed;left:-280px;height:100vh;z-index:50;transition:.2s}
  .sidebar.open{left:0}
  .overlay.show{display:block}
  .content-grid{grid-template-columns:1fr}
  .topbar{align-items:flex-start}
  .topbar-right{width:100%;justify-content:flex-start}
  .charts-grid{grid-template-columns:1fr}
  .filter-grid{grid-template-columns:1fr}
  .review-grid,.executive-grid{grid-template-columns:1fr}
}
@media(max-width:760px){
  .layout{padding:12px}
  .kpi-grid{grid-template-columns:repeat(2,1fr)}
  .chart-kpis{grid-template-columns:1fr}
}
</style>
</head>
<body>
<div class="app">
  <?php include __DIR__ . '/partials/sidebar.php'; ?>
  <div class="overlay" id="overlay" onclick="toggleSidebar(false)"></div>

  <div class="main">
    <header class="topbar">
      <div class="topbar-left">
        <button class="hamb" type="button" onclick="toggleSidebar(true)">☰ Menú</button>
        <div style="min-width:0">
          <div class="topbar-title">Dashboard general</div>
          <div class="topbar-sub">
            Resumen operativo de Bovintel
            <?php if ($ultimaLectura): ?> · Última lectura: <?= h(dash_fmt_date((string)$ultimaLectura, true)) ?><?php endif; ?>
          </div>
        </div>
      </div>

      <div class="topbar-right">
        <div class="currency-wrap">
          <div class="currency-card">
            <div class="currency-head">
              <div class="currency-title"><?= h((string)($usd['moneda'] ?: 'USD BCU')) ?></div>
              <div class="currency-state"><?= h((string)$usd['estado']) ?></div>
            </div>
            <div class="currency-label"><?= h((string)$usd['etiqueta']) ?></div>
            <div class="currency-body">
              <div class="currency-item">
                <small>Compra</small>
                <strong><?= dash_fmt_num($usd['compra'], 2) ?></strong>
              </div>
              <div class="currency-item">
                <small>Venta</small>
                <strong><?= dash_fmt_num($usd['venta'], 2) ?></strong>
              </div>
              <div class="currency-item">
                <small>Fecha</small>
                <strong style="font-size:14px"><?= h(dash_fmt_date($usd['fecha'])) ?></strong>
              </div>
            </div>
          </div>

          <div class="currency-card">
            <div class="currency-head">
              <div class="currency-title"><?= h((string)($usdBrou['moneda'] ?: 'USD BROU')) ?></div>
              <div class="currency-state"><?= h((string)$usdBrou['estado']) ?></div>
            </div>
            <div class="currency-label"><?= h((string)$usdBrou['etiqueta']) ?></div>
            <div class="currency-body">
              <div class="currency-item">
                <small>Compra</small>
                <strong><?= dash_fmt_num($usdBrou['compra'], 2) ?></strong>
              </div>
              <div class="currency-item">
                <small>Venta</small>
                <strong><?= dash_fmt_num($usdBrou['venta'], 2) ?></strong>
              </div>
              <div class="currency-item">
                <small>Fecha</small>
                <strong style="font-size:14px"><?= h(dash_fmt_date($usdBrou['fecha'])) ?></strong>
              </div>
            </div>
          </div>

          <div class="currency-tools">
            <a class="btn-refresh-cot" href="dashboard.php?actualizar_cotizaciones=1" title="Actualizar cotizaciones">↻ Actualizar</a>
          </div>
        </div>
      </div>
    </header>

    <?php if ($mensajeCotizacion !== ''): ?>
      <div class="flash-msg flash-ok"><?= h($mensajeCotizacion) ?></div>
    <?php endif; ?>

    <?php if ($errorCotizacion !== ''): ?>
      <div class="flash-msg flash-error"><?= h($errorCotizacion) ?></div>
    <?php endif; ?>

    <main class="layout">
      <section class="hero-grid">
        <?php
          $statusClass = 'ok';
          if (($estadoOperativo['estado'] ?? '') === 'Crítico') $statusClass = 'danger';
          elseif (($estadoOperativo['estado'] ?? '') === 'Atención') $statusClass = 'warn';
        ?>
        <div class="hero-card">
          <div class="hero-eyebrow">Panel ejecutivo Bovintel</div>
          <div class="hero-title">Prioridades del día para el productor</div>
          <div class="hero-sub">
            Este resumen concentra lo más importante para decidir rápido: conectividad, riesgo operativo, cobertura del monitoreo y foco inmediato de revisión.
          </div>

          <div class="executive-grid">
            <div class="executive-pill">
              <div class="label">Rodeo monitoreado</div>
              <div class="value"><?= dash_fmt_int($resumenEjecutivo['animales_monitoreados']) ?></div>
              <div class="note">
                <?php if ($resumenEjecutivo['animales_base']): ?>
                  <?= h(dash_fmt_int($resumenEjecutivo['animales_base'])) ?> animales base · cobertura <?= h(dash_fmt_num($resumenEjecutivo['cobertura_pct'], 1)) ?>%
                <?php else: ?>
                  Total tomado desde collares activos
                <?php endif; ?>
              </div>
            </div>

            <div class="executive-pill">
              <div class="label">Animales / eventos en riesgo</div>
              <div class="value"><?= dash_fmt_int($resumenEjecutivo['animales_riesgo']) ?></div>
              <div class="note">Suma operativa de alertas, baterías críticas y sin reporte</div>
            </div>

            <div class="executive-pill">
              <div class="label">Conectividad hoy</div>
              <div class="value"><?= dash_fmt_int($kpi['online_24h']) ?></div>
              <div class="note"><?= dash_fmt_int($kpi['sin_reporte_24h']) ?> sin reporte &gt; 24 h</div>
            </div>

            <div class="executive-pill">
              <div class="label">Pasto promedio</div>
              <div class="value"><?= dash_fmt_num($kpi['pasto_promedio'], 0) ?></div>
              <div class="note">kg MS/ha promedio cargado</div>
            </div>
          </div>
        </div>

        <div class="hero-side">
          <div>
            <div class="status-chip <?= h($statusClass) ?>">Estado operativo: <?= h((string)$estadoOperativo['estado']) ?></div>
            <div class="hero-sub" style="margin-top:10px"><?= h((string)$estadoOperativo['detalle']) ?></div>
          </div>

          <div class="side-card">
            <div class="side-card-title">Riesgo operativo</div>
            <div class="side-card-value"><?= dash_fmt_int($estadoOperativo['riesgo']) ?></div>
            <div class="muted">Índice simple para priorizar el día</div>
          </div>

          <div class="side-card">
            <div class="side-card-title">Última lectura global</div>
            <div class="side-card-value" style="font-size:20px"><?= h(dash_fmt_date((string)$ultimaLectura, true)) ?></div>
            <div class="muted"><?php if ($ultimaLectura): ?>Hace <?= h(dash_time_ago((string)$ultimaLectura)) ?><?php else: ?>Sin datos<?php endif; ?></div>
          </div>

          <div class="side-card">
            <div class="side-card-title">Batería crítica</div>
            <div class="side-card-value"><?= dash_fmt_int($kpi['bateria_critica']) ?></div>
            <div class="muted">Collares por debajo del 20%</div>
          </div>
        </div>
      </section>

      <section class="panel" style="margin-bottom:16px;">
        <div class="panel-head">
          <div class="panel-title">Qué revisar hoy</div>
          <div class="muted">Problemas priorizados con acción directa</div>
        </div>
        <div class="panel-body">
          <?php if ($queRevisarHoy): ?>
            <div class="review-grid">
              <?php foreach ($queRevisarHoy as $item): ?>
                <div class="review-card <?= h((string)($item['nivel'] ?? 'medio')) ?>">
                  <div class="review-top">
                    <div class="review-title"><?= h((string)($item['titulo'] ?? 'Revisión')) ?></div>
                    <span class="review-tag"><?= h(strtoupper((string)($item['nivel'] ?? 'medio'))) ?></span>
                  </div>
                  <div class="review-detail"><?= h((string)($item['detalle'] ?? '--')) ?></div>
                  <div class="review-meta"><?= h((string)($item['meta'] ?? '')) ?></div>
                  <a class="review-action" href="<?= h((string)($item['link'] ?? '#')) ?>"><?= h((string)($item['accion'] ?? 'Ver')) ?></a>
                </div>
              <?php endforeach; ?>
            </div>
          <?php else: ?>
            <div class="muted">No se detectaron eventos priorizados para hoy. La operación se ve estable con los datos disponibles.</div>
          <?php endif; ?>
        </div>
      </section>

      <section class="panel" style="margin-bottom:16px;">
        <div class="panel-head">
          <div class="panel-title">Comparativo por establecimiento</div>
          <div class="muted">Vista ejecutiva por campo</div>
        </div>
        <div class="panel-body">
          <div class="table-wrap">
            <table>
              <thead>
                <tr>
                  <th>Establecimiento</th>
                  <th>Collares</th>
                  <th>Online 24 h</th>
                  <th>Batería crítica</th>
                  <th>Peso promedio</th>
                  <th>Última lectura</th>
                </tr>
              </thead>
              <tbody>
              <?php if ($establecimientosResumen): ?>
                <?php foreach ($establecimientosResumen as $er): ?>
                  <tr>
                    <td><?= h((string)($er['establecimiento'] ?? '--')) ?></td>
                    <td><?= dash_fmt_int($er['total_collares'] ?? null) ?></td>
                    <td><?= dash_fmt_int($er['online_24h'] ?? null) ?></td>
                    <td><?= dash_fmt_int($er['bateria_critica'] ?? null) ?></td>
                    <td><?= dash_fmt_num($er['peso_promedio'] ?? null, 1) ?></td>
                    <td><?= h(dash_fmt_date($er['ultima_lectura'] ?? null, true)) ?></td>
                  </tr>
                <?php endforeach; ?>
              <?php else: ?>
                <tr><td colspan="6" class="muted">No hay suficiente información para comparar establecimientos todavía.</td></tr>
              <?php endif; ?>
              </tbody>
            </table>
          </div>
        </div>
      </section>

      <section class="kpi-grid">
        <div class="kpi-card"><div class="kpi-label">Animales monitoreados</div><div class="kpi-value"><?= dash_fmt_int($kpi['animales']) ?></div><div class="kpi-note">Tomado desde collares activos</div></div>
        <div class="kpi-card"><div class="kpi-label">Establecimientos</div><div class="kpi-value"><?= dash_fmt_int($kpi['establecimientos']) ?></div><div class="kpi-note">Campos registrados</div></div>
        <div class="kpi-card"><div class="kpi-label">Con reporte en 24 h</div><div class="kpi-value"><?= dash_fmt_int($kpi['online_24h']) ?></div><div class="kpi-note">Actividad reciente</div></div>
        <div class="kpi-card"><div class="kpi-label">Sin reporte &gt; 24 h</div><div class="kpi-value"><?= dash_fmt_int($kpi['sin_reporte_24h']) ?></div><div class="kpi-note">Para revisar conectividad</div></div>
        <div class="kpi-card"><div class="kpi-label">Celos últimos 7 días</div><div class="kpi-value"><?= dash_fmt_int($kpi['celos_7d']) ?></div><div class="kpi-note">Detectados por sistema</div></div>
        <div class="kpi-card"><div class="kpi-label">Batería crítica</div><div class="kpi-value"><?= dash_fmt_int($kpi['bateria_critica']) ?></div><div class="kpi-note">20% o menos</div></div>

        <div class="kpi-card"><div class="kpi-label">Peso promedio</div><div class="kpi-value"><?= dash_fmt_num($kpi['peso_promedio'], 1) ?></div><div class="kpi-note">kg</div></div>
        <div class="kpi-card"><div class="kpi-label">Pasto promedio</div><div class="kpi-value"><?= dash_fmt_num($kpi['pasto_promedio'], 0) ?></div><div class="kpi-note">kg MS/ha</div></div>
        <div class="kpi-card"><div class="kpi-label">Consumo diario</div><div class="kpi-value"><?= dash_fmt_num($kpi['consumo_diario'], 2) ?></div><div class="kpi-note">estimado</div></div>
        <div class="kpi-card"><div class="kpi-label">Potreros activos</div><div class="kpi-value"><?= dash_fmt_int($kpi['potreros_activos']) ?></div><div class="kpi-note">Disponibles para gestión</div></div>
        <div class="kpi-card"><div class="kpi-label">Stock bajo de ración</div><div class="kpi-value"><?= dash_fmt_int($kpi['racion_baja']) ?></div><div class="kpi-note">Stock actual por debajo del mínimo</div></div>
        <div class="kpi-card"><div class="kpi-label">Costos del mes</div><div class="kpi-value"><?= dash_fmt_num($kpi['costos_mes'], 2) ?></div><div class="kpi-note">Total mensual registrado</div></div>
      </section>

      <section class="panel" style="margin-top:16px;">
        <div class="panel-head">
          <div class="panel-title">Filtros de evolución de peso</div>
          <div class="muted">Caravana o establecimiento</div>
        </div>
        <div class="panel-body">
          <form method="get" class="filter-grid">
            <div class="filter-field">
              <label for="caravana">Caravana</label>
              <input id="caravana" class="filter-input" type="text" name="caravana" value="<?= h($filtroCaravana) ?>" placeholder="Ej: 0041650230">
            </div>

            <div class="filter-field">
              <label for="establecimiento">Establecimiento</label>
              <select id="establecimiento" class="filter-select" name="establecimiento">
                <option value="">Todos</option>
                <?php foreach ($establecimientosFiltro as $ef): ?>
                  <?php $valEst = (string)($ef['establecimiento'] ?? ''); ?>
                  <option value="<?= h($valEst) ?>" <?= ($filtroEstablecimiento === $valEst ? 'selected' : '') ?>>
                    <?= h($valEst) ?>
                  </option>
                <?php endforeach; ?>
              </select>
            </div>

            <button type="submit" class="btn-filter">Filtrar</button>
            <a href="dashboard.php" class="btn-clear">Limpiar</a>
          </form>
        </div>
      </section>

      <section class="charts-grid">
        <div class="chart-card">
          <div class="chart-head">
            <div>
              <div class="chart-title">Pesos anteriores</div>
              <div class="chart-sub">
                <?php if ($filtroCaravana !== '' || $filtroEstablecimiento !== ''): ?>
                  Vista filtrada del historial
                <?php else: ?>
                  Últimas 12 pesadas registradas en historial
                <?php endif; ?>
              </div>
            </div>
            <div class="muted">Histórico</div>
          </div>
          <div class="chart-body">
            <div class="chart-box">
              <canvas id="chartPesosAnteriores"></canvas>
            </div>
            <div class="chart-kpis">
              <div class="mini-kpi">
                <div class="mini-kpi-label">Registros</div>
                <div class="mini-kpi-value"><?= dash_fmt_int($resumenPesos['total_historial']) ?></div>
              </div>
              <div class="mini-kpi">
                <div class="mini-kpi-label">Animales con historial</div>
                <div class="mini-kpi-value"><?= dash_fmt_int($resumenPesos['animales_con_historial']) ?></div>
              </div>
              <div class="mini-kpi">
                <div class="mini-kpi-label">Última pesada</div>
                <div class="mini-kpi-value" style="font-size:15px"><?= h(dash_fmt_date($resumenPesos['ultima_pesada'])) ?></div>
              </div>
            </div>
          </div>
        </div>

        <div class="chart-card">
          <div class="chart-head">
            <div>
              <div class="chart-title">Evolución histórica</div>
              <div class="chart-sub">Promedio mensual de peso de los últimos 12 meses</div>
            </div>
            <div class="muted">Tendencia</div>
          </div>
          <div class="chart-body">
            <div class="chart-box">
              <canvas id="chartEvolucionHistorica"></canvas>
            </div>
          </div>
        </div>

        <div class="chart-card">
          <div class="chart-head">
            <div>
              <div class="chart-title">Curva de crecimiento</div>
              <div class="chart-sub">Peso promedio por edad del animal en meses</div>
            </div>
            <div class="muted">Desarrollo</div>
          </div>
          <div class="chart-body">
            <div class="chart-box">
              <canvas id="chartCurvaCrecimiento"></canvas>
            </div>
          </div>
        </div>
      </section>

      <section class="content-grid">
        <div class="panel">
          <div class="panel-head">
            <div class="panel-title">Actividad reciente de collares</div>
            <div class="muted">Últimos 8 registros</div>
          </div>
          <div class="panel-body">
            <div class="table-wrap">
              <table>
                <thead>
                  <tr>
                    <th>Collar</th>
                    <th>Animal</th>
                    <th>Establecimiento</th>
                    <th>Potrero</th>
                    <th>Batería</th>
                    <th>Última lectura</th>
                  </tr>
                </thead>
                <tbody>
                <?php if ($actividad): ?>
                  <?php foreach ($actividad as $r): ?>
                    <tr>
                      <td><?= h((string)($r['teid'] ?: '--')) ?></td>
                      <td>
                        <?= h((string)($r['nombre'] ?: 'Sin nombre')) ?>
                        <?php if (!empty($r['caravana'])): ?><div class="muted">Caravana: <?= h((string)$r['caravana']) ?></div><?php endif; ?>
                      </td>
                      <td><?= h((string)($r['establecimiento'] ?: '--')) ?></td>
                      <td><?= h((string)($r['potrero'] ?: '--')) ?></td>
                      <td>
                        <?php
                          $bat = $r['bateria'];
                          $cls = 'badge-ok';
                          if ($bat !== null && $bat !== '') {
                            if ((float)$bat <= 20) $cls = 'badge-danger';
                            elseif ((float)$bat <= 40) $cls = 'badge-warn';
                          }
                        ?>
                        <span class="badge <?= $cls ?>"><?= ($bat === null || $bat === '') ? '--' : h(dash_fmt_num($bat, 0)).'%' ?></span>
                      </td>
                      <td>
                        <?= h(dash_fmt_date($r['ultima_lectura'] ?? null, true)) ?>
                        <?php if (!empty($r['ultima_lectura'])): ?><div class="muted">Hace <?= h(dash_time_ago((string)$r['ultima_lectura'])) ?></div><?php endif; ?>
                      </td>
                    </tr>
                  <?php endforeach; ?>
                <?php else: ?>
                  <tr><td colspan="6" class="muted">No se encontraron datos para mostrar en esta tabla.</td></tr>
                <?php endif; ?>
                </tbody>
              </table>
            </div>
          </div>
        </div>

        <div class="panel">
          <div class="panel-head">
            <div class="panel-title">Resumen sanitario</div>
            <div class="muted">Health flags</div>
          </div>
          <div class="panel-body">
            <div class="table-wrap">
              <table>
                <thead><tr><th>Collar</th><th>Detalle</th><th>Estado</th><th>Fecha</th></tr></thead>
                <tbody>
                <?php if ($alertas): ?>
                  <?php foreach ($alertas as $a): ?>
                    <?php
                      $estado = strtolower(trim((string)($a['estado'] ?? 'activa')));
                      $cls = 'badge-warn';
                      if (strpos($estado, 'crit') !== false || strpos($estado, 'alto') !== false) $cls = 'badge-danger';
                      if (strpos($estado, 'ok') !== false || strpos($estado, 'leve') !== false) $cls = 'badge-ok';
                    ?>
                    <tr>
                      <td><?= h((string)($a['teid'] ?: '--')) ?></td>
                      <td><?= h((string)($a['nombre'] ?: 'Alerta')) ?></td>
                      <td><span class="badge <?= $cls ?>"><?= h((string)($a['estado'] ?: 'activa')) ?></span></td>
                      <td><?= h(dash_fmt_date($a['fecha'] ?? null, true)) ?></td>
                    </tr>
                  <?php endforeach; ?>
                <?php else: ?>
                  <tr><td colspan="4" class="muted">No hay alertas disponibles para mostrar.</td></tr>
                <?php endif; ?>
                </tbody>
              </table>
            </div>
          </div>
        </div>
      </section>

      <section class="content-grid">
        <div class="panel">
          <div class="panel-head">
            <div class="panel-title">Ranking de potreros por disponibilidad</div>
            <div class="muted">Top de pasto</div>
          </div>
          <div class="panel-body">
            <div class="table-wrap">
              <table>
                <thead><tr><th>Potrero</th><th>Valor</th><th>Fecha</th></tr></thead>
                <tbody>
                <?php if ($potreros): ?>
                  <?php foreach ($potreros as $p): ?>
                    <tr>
                      <td><?= h((string)($p['potrero'] ?: 'Potrero')) ?></td>
                      <td><?= h(dash_fmt_num($p['valor'] ?? null, 0)) ?></td>
                      <td><?= h(dash_fmt_date($p['fecha'] ?? null)) ?></td>
                    </tr>
                  <?php endforeach; ?>
                <?php else: ?>
                  <tr><td colspan="3" class="muted">No hay registros de pasto para mostrar.</td></tr>
                <?php endif; ?>
                </tbody>
              </table>
            </div>
          </div>
        </div>

        <div class="panel">
          <div class="panel-head">
            <div class="panel-title">Accesos rápidos</div>
            <div class="muted">Ir a módulos</div>
          </div>
          <div class="panel-body">
            <div class="quick-grid">
              <a class="quick-link" href="vaca.php">Comportamiento</a>
              <a class="quick-link" href="analisis_movimiento.php">Movimiento</a>
              <a class="quick-link" href="salud.php">Salud</a>
              <a class="quick-link" href="collares.php">Collares</a>
              <a class="quick-link" href="animales.php">Animales</a>
              <a class="quick-link" href="pastoreo.php">Pastoreo</a>
              <a class="quick-link" href="potreros.php">Potreros</a>
              <a class="quick-link" href="establecimientos.php">Establecimientos</a>
              <a class="quick-link" href="racion.php">Ración</a>
              <a class="quick-link" href="costos.php">Costos</a>
              <a class="quick-link" href="alertas_racion.php">Alertas ración</a>
            </div>
          </div>
        </div>
      </section>
    </main>
  </div>
</div>

<script>
window.addEventListener('load', function () {
  window.toggleSidebar = function(open){
    var s = document.querySelector('.sidebar');
    var o = document.getElementById('overlay');
    if(!s || !o) return;
    if(open){ s.classList.add('open'); o.classList.add('show'); }
    else { s.classList.remove('open'); o.classList.remove('show'); }
  };

  const pesosLabels = <?= json_encode($chartPesosLabels, JSON_UNESCAPED_UNICODE) ?>;
  const pesosData = <?= json_encode($chartPesosData, JSON_UNESCAPED_UNICODE) ?>;

  const evolucionLabels = <?= json_encode($chartEvolucionLabels, JSON_UNESCAPED_UNICODE) ?>;
  const evolucionData = <?= json_encode($chartEvolucionData, JSON_UNESCAPED_UNICODE) ?>;

  const curvaLabels = <?= json_encode($chartCurvaLabels, JSON_UNESCAPED_UNICODE) ?>;
  const curvaData = <?= json_encode($chartCurvaData, JSON_UNESCAPED_UNICODE) ?>;

  function renderChart(id, config){
    const el = document.getElementById(id);
    if(!el || typeof Chart === 'undefined') return;
    new Chart(el, config);
  }

  renderChart('chartPesosAnteriores', {
    type: 'bar',
    data: {
      labels: pesosLabels,
      datasets: [{
        label: 'Peso kg',
        data: pesosData,
        backgroundColor: 'rgba(22, 163, 74, 0.65)',
        borderColor: 'rgba(22, 163, 74, 1)',
        borderWidth: 1,
        borderRadius: 6
      }]
    },
    options: {
      responsive: true,
      maintainAspectRatio: false,
      plugins: {
        legend: { display: false }
      },
      scales: {
        x: {
          ticks: { maxRotation: 60, minRotation: 60 }
        },
        y: {
          beginAtZero: false,
          title: { display: true, text: 'kg' }
        }
      }
    }
  });

  renderChart('chartEvolucionHistorica', {
    type: 'line',
    data: {
      labels: evolucionLabels,
      datasets: [{
        label: 'Promedio mensual kg',
        data: evolucionData,
        borderColor: 'rgba(15, 23, 42, 1)',
        backgroundColor: 'rgba(15, 23, 42, 0.12)',
        fill: true,
        tension: 0.3,
        pointRadius: 4,
        pointHoverRadius: 5
      }]
    },
    options: {
      responsive: true,
      maintainAspectRatio: false,
      plugins: {
        legend: { display: false }
      },
      scales: {
        y: {
          beginAtZero: false,
          title: { display: true, text: 'kg promedio' }
        }
      }
    }
  });

  renderChart('chartCurvaCrecimiento', {
    type: 'line',
    data: {
      labels: curvaLabels,
      datasets: [{
        label: 'Curva de crecimiento',
        data: curvaData,
        borderColor: 'rgba(180, 83, 9, 1)',
        backgroundColor: 'rgba(180, 83, 9, 0.15)',
        fill: true,
        tension: 0.25,
        pointRadius: 3,
        pointHoverRadius: 5
      }]
    },
    options: {
      responsive: true,
      maintainAspectRatio: false,
      plugins: {
        legend: { display: false }
      },
      scales: {
        y: {
          beginAtZero: false,
          title: { display: true, text: 'kg promedio' }
        }
      }
    }
  });
});
</script>
</body>
</html>