<?php
/**
 * Baskit price-comparison viewer.
 *
 * Live HTML view over the localhost `baskit` MySQL database (catalogue +
 * mvp_catalogue), served by WAMP. Browse the curated MVP catalogue or all
 * barcode-matched products, with search, bucket filters and per-row cheapest
 * retailer highlighting.
 *
 * Open at: http://localhost/baskit_products/view.php
 */

// ---- connection (matches load_mysql.py defaults; override via env) ----
$DB_HOST = getenv('BASKIT_MYSQL_HOST') ?: 'medmin.co.za';
$DB_PORT = getenv('BASKIT_MYSQL_PORT') ?: '3306';
$DB_USER = getenv('BASKIT_MYSQL_USER') ?: 'medminco_baskit';
$DB_PASS = getenv('BASKIT_MYSQL_PASSWORD') ?: '1vdtXNG64fld89o5&5Y_w1Hy';
$DB_NAME = getenv('BASKIT_MYSQL_DB') ?: 'medminco_baskit';

try {
    $pdo = new PDO(
        "mysql:host=$DB_HOST;port=$DB_PORT;dbname=$DB_NAME;charset=utf8mb4",
        $DB_USER, $DB_PASS,
        [PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
         PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC]
    );
} catch (PDOException $e) {
    http_response_code(500);
    die('<p style="font-family:sans-serif;padding:2rem">Cannot connect to MySQL <code>'
        . htmlspecialchars($DB_NAME) . '</code>: ' . htmlspecialchars($e->getMessage())
        . '<br>Is WAMP MySQL running, and have you run <code>python pipeline/load_mysql.py</code>?</p>');
}

$RETAILERS = ['pnp' => 'Pick n Pay', 'checkers' => 'Checkers', 'woolworths' => 'Woolworths'];

// ---- inputs ----
$mode   = ($_GET['mode'] ?? 'mvp') === 'all' ? 'all' : 'mvp';
$q      = trim($_GET['q'] ?? '');
$bucket = trim($_GET['bucket'] ?? '');
$page   = max(1, (int)($_GET['page'] ?? 1));
$perPage = 60;
$offset = ($page - 1) * $perPage;

// ---- header stats ----
$stats = $pdo->query("SELECT
    (SELECT COUNT(*) FROM catalogue) AS catalogue_rows,
    (SELECT COUNT(*) FROM mvp_catalogue) AS mvp_rows,
    (SELECT COUNT(*) FROM mvp_catalogue WHERE n_retailers>=3) AS mvp_all3
")->fetch();

$buckets = $pdo->query("SELECT bucket, COUNT(*) c FROM mvp_catalogue GROUP BY bucket ORDER BY bucket")
               ->fetchAll();

// ---- main query ----
$rows = [];
$totalRows = 0;

if ($mode === 'mvp') {
    $where = [];
    $args = [];
    if ($q !== '') {
        $where[] = "(CONVERT(m.name USING utf8mb4) LIKE :q OR CONVERT(m.brand USING utf8mb4) LIKE :q "
                 . "OR CONVERT(m.barcode USING utf8mb4) LIKE :q)";
        $args[':q'] = "%$q%";
    }
    if ($bucket !== '') { $where[] = "CONVERT(m.bucket USING utf8mb4) = :bucket"; $args[':bucket'] = $bucket; }
    $whereSql = $where ? ('WHERE ' . implode(' AND ', $where)) : '';

    $cnt = $pdo->prepare("SELECT COUNT(*) c FROM mvp_catalogue m $whereSql");
    $cnt->execute($args); $totalRows = (int)$cnt->fetch()['c'];

    // image via a single grouped join (CONVERT keeps it collation-safe across latin1/utf8mb4)
    $sql = "SELECT m.*, img.image_url
            FROM mvp_catalogue m
            LEFT JOIN (
                SELECT barcode_norm, MIN(image_url) AS image_url
                FROM catalogue
                WHERE image_url IS NOT NULL AND image_url <> ''
                GROUP BY barcode_norm
            ) img ON CONVERT(img.barcode_norm USING utf8mb4) = CONVERT(m.barcode USING utf8mb4)
            $whereSql
            ORDER BY m.bucket, m.n_retailers DESC, m.name
            LIMIT $perPage OFFSET $offset";
    $stmt = $pdo->prepare($sql);
    $stmt->execute($args);
    $rows = $stmt->fetchAll();
} else {
    // all barcode-matched products, pivoted by barcode
    $having = "HAVING COUNT(DISTINCT retailer) >= 2";
    $where = ["barcode_norm IS NOT NULL", "is_instore_bc = 0", "price IS NOT NULL"];
    $args = [];
    if ($q !== '') {
        $where[] = "(CONVERT(name USING utf8mb4) LIKE :q OR CONVERT(brand USING utf8mb4) LIKE :q "
                 . "OR CONVERT(barcode_norm USING utf8mb4) LIKE :q)";
        $args[':q'] = "%$q%";
    }
    $whereSql = 'WHERE ' . implode(' AND ', $where);

    $cntSql = "SELECT COUNT(*) c FROM (
                 SELECT barcode_norm FROM catalogue $whereSql
                 GROUP BY barcode_norm $having) t";
    $cnt = $pdo->prepare($cntSql); $cnt->execute($args); $totalRows = (int)$cnt->fetch()['c'];

    $sql = "SELECT barcode_norm AS barcode,
                   MAX(name) AS name, MAX(brand) AS brand,
                   COUNT(DISTINCT retailer) AS n_retailers,
                   MAX(CASE WHEN retailer='pnp' THEN price END) AS pnp_price,
                   MAX(CASE WHEN retailer='checkers' THEN price END) AS checkers_price,
                   MAX(CASE WHEN retailer='woolworths' THEN price END) AS woolworths_price,
                   MIN(price) AS min_price, MAX(price) AS max_price,
                   (SELECT image_url FROM catalogue c2
                      WHERE c2.barcode_norm = catalogue.barcode_norm AND c2.image_url IS NOT NULL
                      LIMIT 1) AS image_url
            FROM catalogue
            $whereSql
            GROUP BY barcode_norm
            $having
            ORDER BY (MAX(price)-MIN(price)) DESC
            LIMIT $perPage OFFSET $offset";
    $stmt = $pdo->prepare($sql);
    $stmt->execute($args);
    $rows = $stmt->fetchAll();
}

$totalPages = max(1, (int)ceil($totalRows / $perPage));

function money($v) { return $v === null ? null : 'R' . number_format((float)$v, 2); }
function qs($overrides = []) {
    $base = ['mode' => $_GET['mode'] ?? 'mvp', 'q' => $_GET['q'] ?? '',
             'bucket' => $_GET['bucket'] ?? '', 'page' => $_GET['page'] ?? 1];
    return htmlspecialchars(http_build_query(array_merge($base, $overrides)));
}
function h($s) { return htmlspecialchars((string)$s, ENT_QUOTES); }
?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Baskit — Price Comparison</title>
<style>
  :root {
    --bg:#f4f6f8; --card:#fff; --ink:#1c2733; --muted:#6b7886; --line:#e4e9ee;
    --accent:#1f9d55; --accent-soft:#e7f6ee; --cheap:#1f9d55; --cheap-bg:#e7f6ee;
    --pnp:#e3122b; --checkers:#00a14b; --woolies:#0b0b0b;
  }
  * { box-sizing:border-box; }
  body { margin:0; background:var(--bg); color:var(--ink);
         font-family:-apple-system,Segoe UI,Roboto,Helvetica,Arial,sans-serif; font-size:14px; }
  header { background:var(--card); border-bottom:1px solid var(--line); padding:16px 24px;
           position:sticky; top:0; z-index:10; }
  .brand { display:flex; align-items:baseline; gap:12px; }
  .brand h1 { margin:0; font-size:20px; letter-spacing:-.3px; }
  .brand .sub { color:var(--muted); font-size:13px; }
  .stats { display:flex; gap:20px; margin-top:10px; flex-wrap:wrap; }
  .stat { font-size:12px; color:var(--muted); }
  .stat b { display:block; font-size:18px; color:var(--ink); }
  .wrap { padding:20px 24px 60px; max-width:1280px; margin:0 auto; }
  .toolbar { display:flex; gap:10px; align-items:center; flex-wrap:wrap; margin-bottom:16px; }
  .tabs { display:flex; gap:4px; background:var(--card); padding:4px; border-radius:10px; border:1px solid var(--line); }
  .tabs a { padding:7px 14px; border-radius:7px; text-decoration:none; color:var(--muted); font-weight:600; }
  .tabs a.on { background:var(--accent); color:#fff; }
  form.search { display:flex; gap:8px; flex:1; min-width:240px; }
  input[type=search], select { padding:9px 12px; border:1px solid var(--line); border-radius:8px;
         background:var(--card); font-size:14px; color:var(--ink); }
  input[type=search] { flex:1; }
  button { padding:9px 16px; border:0; border-radius:8px; background:var(--accent); color:#fff;
           font-weight:600; cursor:pointer; }
  .pills { display:flex; gap:6px; flex-wrap:wrap; margin-bottom:14px; }
  .pill { padding:5px 11px; border-radius:999px; background:var(--card); border:1px solid var(--line);
          text-decoration:none; color:var(--muted); font-size:12px; }
  .pill.on { background:var(--ink); color:#fff; border-color:var(--ink); }
  .count { color:var(--muted); margin-bottom:10px; }
  table { width:100%; border-collapse:collapse; background:var(--card); border-radius:12px; overflow:hidden;
          box-shadow:0 1px 2px rgba(0,0,0,.04); }
  th, td { padding:10px 12px; text-align:left; border-bottom:1px solid var(--line); vertical-align:middle; }
  th { font-size:11px; text-transform:uppercase; letter-spacing:.4px; color:var(--muted); background:#fafbfc;
       position:sticky; top:0; }
  td.num, th.num { text-align:right; font-variant-numeric:tabular-nums; white-space:nowrap; }
  tr:hover td { background:#fbfdfc; }
  .thumb { width:42px; height:42px; object-fit:contain; border-radius:6px; background:#fff; border:1px solid var(--line); }
  .pname { font-weight:600; line-height:1.25; }
  .pmeta { color:var(--muted); font-size:12px; margin-top:2px; }
  .bk { display:inline-block; font-size:10.5px; text-transform:uppercase; letter-spacing:.3px;
        color:var(--accent); background:var(--accent-soft); padding:2px 7px; border-radius:5px; }
  .price { font-weight:600; }
  .price.cheap { color:var(--cheap); background:var(--cheap-bg); border-radius:6px; padding:4px 8px; display:inline-block; }
  .price.none { color:#c2cad2; font-weight:400; }
  .save { font-weight:700; color:var(--accent); }
  .save small { display:block; font-weight:500; color:var(--muted); }
  .pager { display:flex; gap:8px; align-items:center; justify-content:center; margin-top:18px; }
  .pager a, .pager span { padding:7px 12px; border-radius:8px; border:1px solid var(--line); background:var(--card);
        text-decoration:none; color:var(--ink); }
  .pager .disabled { color:#c2cad2; }
  .empty { padding:40px; text-align:center; color:var(--muted); }
  .dot { display:inline-block; width:7px; height:7px; border-radius:50%; margin-right:5px; }
</style>
</head>
<body>
<header>
  <div class="brand">
    <h1>🧺 Baskit</h1>
    <span class="sub">cross-retailer grocery price comparison · live from MySQL</span>
  </div>
  <div class="stats">
    <div class="stat"><b><?= number_format($stats['catalogue_rows']) ?></b> products scraped</div>
    <div class="stat"><b><?= number_format($stats['mvp_rows']) ?></b> MVP catalogue SKUs</div>
    <div class="stat"><b><?= number_format($stats['mvp_all3']) ?></b> priced in all 3 retailers</div>
    <div class="stat"><b>3</b> retailers · PnP · Checkers · Woolworths</div>
  </div>
</header>

<div class="wrap">
  <div class="toolbar">
    <div class="tabs">
      <a class="<?= $mode==='mvp'?'on':'' ?>" href="?<?= qs(['mode'=>'mvp','page'=>1]) ?>">MVP Catalogue</a>
      <a class="<?= $mode==='all'?'on':'' ?>" href="?<?= qs(['mode'=>'all','bucket'=>'','page'=>1]) ?>">All Matched</a>
    </div>
    <form class="search" method="get">
      <input type="hidden" name="mode" value="<?= h($mode) ?>">
      <?php if ($mode==='mvp' && $bucket!==''): ?><input type="hidden" name="bucket" value="<?= h($bucket) ?>"><?php endif; ?>
      <input type="search" name="q" placeholder="Search name, brand or barcode…" value="<?= h($q) ?>">
      <button type="submit">Search</button>
    </form>
  </div>

  <?php if ($mode === 'mvp'): ?>
  <div class="pills">
    <a class="pill <?= $bucket===''?'on':'' ?>" href="?<?= qs(['bucket'=>'','page'=>1]) ?>">All buckets</a>
    <?php foreach ($buckets as $b): ?>
      <a class="pill <?= $bucket===$b['bucket']?'on':'' ?>" href="?<?= qs(['bucket'=>$b['bucket'],'page'=>1]) ?>">
        <?= h(ucwords(str_replace('_',' ',$b['bucket']))) ?> <?= $b['c'] ?></a>
    <?php endforeach; ?>
  </div>
  <?php endif; ?>

  <div class="count"><?= number_format($totalRows) ?> products<?= $q!=='' ? ' matching “'.h($q).'”' : '' ?>
    · page <?= $page ?> of <?= $totalPages ?></div>

  <table>
    <thead>
      <tr>
        <th colspan="2">Product</th>
        <?php foreach ($RETAILERS as $key=>$label): ?>
          <th class="num"><span class="dot" style="background:var(--<?= $key==='pnp'?'pnp':($key==='checkers'?'checkers':'woolies') ?>)"></span><?= $label ?></th>
        <?php endforeach; ?>
        <th class="num">Cheapest</th>
        <th class="num">You save</th>
      </tr>
    </thead>
    <tbody>
    <?php if (!$rows): ?>
      <tr><td colspan="7" class="empty">No products found. Try a different search or bucket.</td></tr>
    <?php endif; ?>
    <?php foreach ($rows as $r):
        $prices = ['pnp'=>$r['pnp_price'], 'checkers'=>$r['checkers_price'], 'woolworths'=>$r['woolworths_price']];
        $valid = array_filter($prices, fn($v)=>$v!==null);
        $min = $valid ? min($valid) : null;
        $max = $valid ? max($valid) : null;
        $save = ($min!==null && $max!==null) ? ($max-$min) : 0;
        $savePct = $min>0 ? round($save/$max*100) : 0;
        $cheapest = null;
        foreach ($prices as $k=>$v) { if ($v!==null && (float)$v==(float)$min) { $cheapest=$k; break; } }
    ?>
      <tr>
        <td style="width:42px">
          <?php if (!empty($r['image_url'])): ?>
            <img class="thumb" src="<?= h($r['image_url']) ?>" alt="" loading="lazy"
                 onerror="this.style.visibility='hidden'">
          <?php endif; ?>
        </td>
        <td>
          <div class="pname"><?= h($r['name']) ?></div>
          <div class="pmeta">
            <?php if (!empty($r['bucket'])): ?><span class="bk"><?= h(str_replace('_',' ',$r['bucket'])) ?></span> <?php endif; ?>
            <?= !empty($r['brand']) ? h($r['brand']).' · ' : '' ?>barcode <?= h($r['barcode']) ?>
          </div>
        </td>
        <?php foreach ($RETAILERS as $key=>$label):
            $v = $prices[$key];
            $isCheap = ($v!==null && $cheapest===$key && count($valid)>1);
        ?>
          <td class="num">
            <?php if ($v===null): ?><span class="price none">—</span>
            <?php else: ?><span class="price <?= $isCheap?'cheap':'' ?>"><?= money($v) ?></span><?php endif; ?>
          </td>
        <?php endforeach; ?>
        <td class="num"><?= $cheapest ? '<b>'.h($RETAILERS[$cheapest]).'</b>' : '—' ?></td>
        <td class="num">
          <?php if ($save > 0): ?><span class="save"><?= money($save) ?><small><?= $savePct ?>%</small></span>
          <?php else: ?>—<?php endif; ?>
        </td>
      </tr>
    <?php endforeach; ?>
    </tbody>
  </table>

  <?php if ($totalPages > 1): ?>
  <div class="pager">
    <?php if ($page>1): ?><a href="?<?= qs(['page'=>$page-1]) ?>">‹ Prev</a>
    <?php else: ?><span class="disabled">‹ Prev</span><?php endif; ?>
    <span>Page <?= $page ?> / <?= $totalPages ?></span>
    <?php if ($page<$totalPages): ?><a href="?<?= qs(['page'=>$page+1]) ?>">Next ›</a>
    <?php else: ?><span class="disabled">Next ›</span><?php endif; ?>
  </div>
  <?php endif; ?>
</div>
</body>
</html>
