<?php
declare(strict_types=1);
if (!defined('STORE_ROOT')) { http_response_code(403); exit; }

function productHandler(string $action, array $in): void {
    Security::sendHeaders();
    Security::enforceRateLimit('products_api', 60, 60);

    $host = $_SERVER['HTTP_HOST'] ?? '';
    $storeId = 0;
    try {
        $row = DB::one("SELECT id FROM store_domains WHERE domain = :d AND is_active = 1", [':d' => $host]);
        if ($row) $storeId = (int) $row['id'];
    } catch (\Throwable $e) {}

    $sidParam = [':sid' => $storeId];

    if ($action === 'list') {
        $catId = (int) ($in['cat'] ?? 0);
        $where = "status_code = 3002 AND visibility_code = 3050 AND (store_id = :sid OR store_id = 0)";
        $params = $sidParam;
        if ($catId > 0) {
            $where .= " AND category_id = :cid";
            $params[':cid'] = $catId;
        }
        $rows = DB::all("SELECT id, product_code, display_order, title, short_desc, price, sale_price, image_url, unit_pricing_code, unit_label, unit_increment, unit_price_per, unit_tiers FROM products WHERE {$where}", $params);
        $rows = Crypt::rows($rows, ['title', 'short_desc', 'unit_label', 'unit_increment', 'unit_price_per', 'unit_tiers', 'price', 'sale_price', 'display_order']);
        usort($rows, function($a, $b) {
            $oa = is_numeric($a['display_order']) ? (int)$a['display_order'] : 0;
            $ob = is_numeric($b['display_order']) ? (int)$b['display_order'] : 0;
            if ($oa !== $ob) return $oa <=> $ob;
            return $a['id'] <=> $b['id'];
        });
        App::ok(['data' => $rows]);
    }

    if ($action === 'detail') {
        $id = (int) ($in['id'] ?? 0);
        $item = DB::one("SELECT id, product_code, title, slug, short_desc, description, price, sale_price, image_url, unit_pricing_code, unit_label, unit_increment, unit_price_per, unit_min_qty, unit_tiers, category_id FROM products WHERE id = :id AND status_code = 3002 AND visibility_code = 3050 AND (store_id = :sid OR store_id = 0)", [':id' => $id, ':sid' => $storeId]);
        if (!$item) App::err('Not found', 404);
        $item = Crypt::rows([$item], ['title', 'short_desc', 'description', 'unit_label', 'unit_increment', 'unit_price_per', 'unit_min_qty', 'unit_tiers', 'price', 'sale_price'])[0];

        $blocks = DB::all("SELECT id, display_order, title, body, slot_size, bg_color, text_color FROM storefront_blocks WHERE category_id = :cid AND status_code = 6001", [':cid' => $item['category_id']]);
        $blocks = Crypt::rows($blocks, ['title', 'body', 'bg_color', 'text_color', 'display_order']);
        usort($blocks, function($a, $b) {
            $oa = is_numeric($a['display_order']) ? (int)$a['display_order'] : 0;
            $ob = is_numeric($b['display_order']) ? (int)$b['display_order'] : 0;
            if ($oa !== $ob) return $oa <=> $ob;
            return $a['id'] <=> $b['id'];
        });

        App::ok(['data' => $item, 'blocks' => $blocks]);
    }

    if ($action === 'categories') {
        $rows = DB::all("SELECT id, name, slug, display_order FROM categories WHERE status_code = 6001 AND (store_id = :sid OR store_id = 0)", $sidParam);
        $rows = Crypt::rows($rows, ['name', 'display_order']);
        usort($rows, function($a, $b) {
            $oa = is_numeric($a['display_order']) ? (int)$a['display_order'] : 0;
            $ob = is_numeric($b['display_order']) ? (int)$b['display_order'] : 0;
            if ($oa !== $ob) return $oa <=> $ob;
            return $a['id'] <=> $b['id'];
        });
        App::ok(['data' => $rows]);
    }

    App::err('Unknown product action');
}