<?php
// api/menu.php  –  Public read-only API consumed by menu/index.html
//
// This version returns Arabic fields alongside English ones so the
// customer-facing page can switch languages on the fly without making
// a second network request. The client is responsible for choosing
// which language to display — the server just ships both.

require_once __DIR__ . '/../config.php';

header('Access-Control-Allow-Origin: *');
header('Content-Type: application/json');
// No browser/proxy caching — the customer menu is served fresh on
// every request. The showcase tablet's silentRefresh() polls every
// 5 minutes; without these headers an aggressive proxy could serve
// stale data, hiding admin's price/visibility changes.
header('Cache-Control: no-store, no-cache, must-revalidate, max-age=0');
header('Pragma: no-cache');
header('Expires: 0');

$action = $_GET['action'] ?? 'full';

try {
    if ($action === 'full') {

        // Determine which "mode" we're serving — ordering or showcase.
        // The customer HTML tells us via ?mode=showcase or ?mode=ordering.
        // Default is 'ordering' for safety.
        // Mode → visibility column:
        //   ordering → show_in_ordering = 1
        //   showcase → show_in_showcase = 1
        $mode = $_GET['mode'] ?? '';
        if (!in_array($mode, ['ordering', 'showcase'], true)) {
            $mode = defined('SITE_MODE') ? SITE_MODE : 'ordering';
            if (!in_array($mode, ['ordering', 'showcase'], true)) $mode = 'ordering';
        }
        $visibilityCol = ($mode === 'showcase') ? 'show_in_showcase' : 'show_in_ordering';

        // 1. Fetch active categories. We now include name_ar so the
        //    menu page can label tabs in either language.
        $cats = db()->query(
            'SELECT id, name, name_ar, slug, header_image_url, header_video_url
             FROM categories
             WHERE is_active = 1
             ORDER BY sort_order'
        )->fetchAll();

        // ── Branch + fulfilment-mode filtering (Brand B) ─────────
        // ?branch=<id|slug> scopes the menu to one branch's items.
        // ?fmode=delivery|pickup|dinein hides items not available
        // for that fulfilment mode. Both are optional — when
        // absent (e.g. single_location installs, or the showcase),
        // no extra filtering is applied and the menu behaves as
        // before. We resolve a branch slug to its id up front.
        $branchId   = null;
        $branchParam = trim($_GET['branch'] ?? '');
        if ($branchParam !== '') {
            if (ctype_digit($branchParam)) {
                $branchId = (int)$branchParam;
            } else {
                try {
                    $bs = db()->prepare('SELECT id FROM branches WHERE slug = ? LIMIT 1');
                    $bs->execute([$branchParam]);
                    $found = $bs->fetchColumn();
                    if ($found !== false) $branchId = (int)$found;
                } catch (PDOException $e) { /* no branches table — ignore */ }
            }
        }
        $fmode = $_GET['fmode'] ?? '';
        if (!in_array($fmode, ['delivery', 'pickup', 'dinein'], true)) {
            $fmode = '';
        }
        // Map the fulfilment mode to its items column.
        $fmodeCol = [
            'delivery' => 'mode_delivery',
            'pickup'   => 'mode_pickup',
            'dinein'   => 'mode_dinein',
        ][$fmode] ?? null;

        // Build the extra WHERE fragment + params shared by both
        // the main and fallback item queries.
        $branchClause = '';
        if ($branchId !== null) {
            // Item must be assigned to this branch via item_branches.
            $branchClause .= ' AND id IN (SELECT item_id FROM item_branches WHERE branch_id = :branch)';
        }
        $fmodeClause = '';
        if ($fmodeCol !== null) {
            $fmodeClause = " AND $fmodeCol = 1";
        }

        // 2. For each category, fetch its active items filtered by
        //    the appropriate visibility flag for this mode.
        //    An item belongs to a category if EITHER its primary
        //    category_id matches OR it's linked via item_categories
        //    (the multi-category join table).
        //
        //    The whole thing is wrapped in try/catch: if the
        //    item_categories table doesn't exist yet (API deployed
        //    before the migration ran), we fall back to the simple
        //    primary-category-only query so the menu still works.
        foreach ($cats as &$cat) {
            try {
                $params = [':cat' => $cat['id'], ':cat2' => $cat['id']];
                if ($branchId !== null) $params[':branch'] = $branchId;
                $stmt = db()->prepare(
                    "SELECT id, name, name_ar, description, description_ar,
                            category_id, base_price, photo_url, photo_position, badge
                     FROM items
                     WHERE is_active = 1 AND $visibilityCol = 1
                       AND (
                         category_id = :cat
                         OR id IN (
                           SELECT item_id FROM item_categories WHERE category_id = :cat2
                         )
                       )
                       $branchClause
                       $fmodeClause
                     ORDER BY sort_order"
                );
                $stmt->execute($params);
                $items = $stmt->fetchAll();
            } catch (PDOException $e) {
                // item_categories (or item_branches) table missing —
                // fall back to the simple primary-category query.
                // The branch/fmode clauses are dropped in the
                // fallback since their tables may be what's missing.
                $stmt = db()->prepare(
                    "SELECT id, name, name_ar, description, description_ar,
                            category_id, base_price, photo_url, photo_position, badge
                     FROM items
                     WHERE category_id = ? AND is_active = 1 AND $visibilityCol = 1
                     ORDER BY sort_order"
                );
                $stmt->execute([$cat['id']]);
                $items = $stmt->fetchAll();
            }

            // 3. For each item, attach its sizes, extras, and gallery
            //    photos (all in both languages where applicable).
            foreach ($items as &$item) {
                $s = db()->prepare(
                    'SELECT label, label_ar, price_add
                     FROM sizes WHERE item_id = ? ORDER BY sort_order'
                );
                $s->execute([$item['id']]);
                $item['sizes'] = $s->fetchAll();

                $e = db()->prepare(
                    'SELECT name, name_ar, price
                     FROM extras WHERE item_id = ? ORDER BY sort_order'
                );
                $e->execute([$item['id']]);
                $item['extras'] = $e->fetchAll();

                // Gallery media — URLs plus an is_video flag so the
                // client knows which entries to render as <video>
                // vs. <img>. Empty array if the item has no extra
                // media; the client falls back to just photo_url.
                //
                // Wrapped in try/catch so a missing item_photos
                // table or missing is_video column doesn't break
                // the whole menu API. The customer just sees no
                // gallery extras until the schema migration is run.
                try {
                    $p = db()->prepare(
                        'SELECT url, is_video FROM item_photos WHERE item_id = ? ORDER BY sort_order'
                    );
                    $p->execute([$item['id']]);
                    $rows = $p->fetchAll();
                    foreach ($rows as &$row) { $row['is_video'] = (int)$row['is_video']; }
                    $item['photos'] = $rows;
                } catch (PDOException $e) {
                    // Table doesn't exist or column missing.
                    // Try the older schema (just url, no is_video).
                    try {
                        $p = db()->prepare(
                            'SELECT url FROM item_photos WHERE item_id = ? ORDER BY sort_order'
                        );
                        $p->execute([$item['id']]);
                        $rows = $p->fetchAll();
                        foreach ($rows as &$row) { $row['is_video'] = 0; }
                        $item['photos'] = $rows;
                    } catch (PDOException $e2) {
                        // Table doesn't exist at all — return empty.
                        $item['photos'] = [];
                    }
                }
            }
            $cat['items'] = $items;
        }

        // 4. Settings. Whitelist now includes the popup_* keys so the
        //    welcome popup can be configured entirely from admin.
        //    $mode was resolved at the top of this action — reuse it
        //    so popups + visibility filtering use the same value.
        $siteMode = $mode;

        // Pick the right popup setting keys for this site. The
        // showcase site has its own popup so admin can use it to
        // feature new items, separate from the QR site's "Welcome"
        // popup.
        if ($siteMode === 'showcase') {
            $popupKeys = "'popup_showcase_enabled', 'popup_showcase_media_type',
                          'popup_showcase_media_url', 'popup_showcase_title_en',
                          'popup_showcase_title_ar', 'popup_showcase_body_en',
                          'popup_showcase_body_ar', 'popup_showcase_button_en',
                          'popup_showcase_button_ar'";
        } else {
            $popupKeys = "'popup_enabled', 'popup_media_type',
                          'popup_media_url', 'popup_title_en',
                          'popup_title_ar', 'popup_body_en',
                          'popup_body_ar', 'popup_button_en',
                          'popup_button_ar'";
        }

        $settings = db()->query(
            "SELECT key_name, value FROM settings WHERE key_name IN
             ('restaurant_name',       'restaurant_name_ar',
              'restaurant_tagline',    'restaurant_tagline_ar',
              'currency_code',         'currency_decimals',
              'primary_color',         'accent_color',
              'logo_url',              'default_language',
              'layout',
              $popupKeys,
              'whatsapp_number',       'min_order_amount',
              'order_placement_mode',
              'payment_cash_enabled',  'payment_card_enabled',
              'payment_counter_enabled')"
        )->fetchAll(PDO::FETCH_KEY_PAIR);

        // Normalize the popup keys — if showcase, alias them to
        // the standard popup_* names the menu HTML expects, so
        // the front-end doesn't need site-specific code paths
        // for popup rendering.
        if ($siteMode === 'showcase') {
            $aliased = [];
            foreach ($settings as $k => $v) {
                if (str_starts_with($k, 'popup_showcase_')) {
                    $aliased[str_replace('popup_showcase_', 'popup_', $k)] = $v;
                } else {
                    $aliased[$k] = $v;
                }
            }
            $settings = $aliased;
        }

        // Expose the site mode to the client so the menu HTML
        // can hide the cart bar and ordering UI on showcase mode.
        $settings['site_mode'] = $siteMode;

        // Country-of-origin master data. Wrapped in a try/catch
        // so a missing table on older DBs doesn't break the menu
        // — the client just sees an empty array and hides the
        // origins UI accordingly.
        $origins = [];
        try {
            $origins = db()->query(
                'SELECT id, item_en, item_ar, country_en, country_ar
                 FROM item_origins ORDER BY sort_order, id'
            )->fetchAll();
        } catch (PDOException $e) {
            // Table doesn't exist — return empty list, no error.
        }

        // Operating mode (Brand B multi-branch vs La Tarte single).
        // NOTE: this is a DIFFERENT setting from $settings['site_mode']
        // above, which is the legacy ordering/showcase flag. We expose
        // ours under 'operating_mode' to avoid clobbering that.
        $operatingMode = 'single_location';
        try {
            $om = db()->query("SELECT value FROM settings WHERE key_name='site_mode' LIMIT 1")
                ->fetchColumn();
            if ($om !== false && $om !== null && $om !== '') $operatingMode = $om;
        } catch (PDOException $e) { /* default stays single_location */ }
        $settings['operating_mode'] = $operatingMode;

        // Active branches — for the customer branch picker. Empty
        // list on single_location installs (no branches table) so
        // the client simply never shows a picker.
        $branches = [];
        try {
            $branches = db()->query(
                'SELECT id, name, name_ar, slug, address, address_ar, phone
                 FROM branches WHERE is_active = 1 ORDER BY sort_order, id'
            )->fetchAll();
        } catch (PDOException $e) {
            // No branches table — return empty list, no error.
        }

        json_out([
            'settings'   => $settings,
            'categories' => $cats,
            'origins'    => $origins,
            'branches'   => $branches,
        ]);
    }

    json_out(['error' => 'Unknown action'], 400);

} catch (Throwable $e) {
    json_out(['error' => 'Server error'], 500);
}
