<?php
declare(strict_types=1);
require_once __DIR__ . '/config.php';
header('Content-Type: application/json');
$pdo = getDB();
ensureCalcBuilderTable($pdo);
$method = $_SERVER['REQUEST_METHOD'];
if ($method === 'GET') {
$category = isset($_GET['category']) ? trim((string) $_GET['category']) : '';
if ($category !== '') {
$stmt = $pdo->prepare('SELECT cb.*, pc.label AS category_label FROM calc_builders cb LEFT JOIN product_categories pc ON pc.id = cb.category_id WHERE cb.active = 1 AND cb.category_id = ? LIMIT 1');
$stmt->execute([$category]);
$row = $stmt->fetch();
echo json_encode(['success' => true, 'configurator' => $row ? hydrateCalcBuilderRow($row) : null]);
exit;
}
$rows = $pdo->query('SELECT cb.*, pc.label AS category_label FROM calc_builders cb LEFT JOIN product_categories pc ON pc.id = cb.category_id WHERE cb.active = 1 ORDER BY cb.title ASC, cb.category_id ASC')->fetchAll();
echo json_encode(['success' => true, 'configurators' => array_map('hydrateCalcBuilderRow', $rows)]);
exit;
}
if ($method === 'POST' || $method === 'PUT') {
$body = json_decode((string) file_get_contents('php://input'), true);
if (!is_array($body)) {
echo json_encode(['success' => false, 'error' => 'Invalid JSON']);
exit;
}
$category = trim((string) ($body['category'] ?? ''));
$title = trim((string) ($body['title'] ?? ''));
$version = trim((string) ($body['version'] ?? '1.0.0'));
$notes = trim((string) ($body['notes'] ?? ''));
$builderMode = trim((string) ($body['builder_mode'] ?? 'simple'));
$headPreset = trim((string) ($body['head_preset'] ?? 'current-default'));
$sidebarModule = trim((string) ($body['sidebar_module'] ?? 'price-summary'));
$footerMode = trim((string) ($body['footer_mode'] ?? 'none'));
$baseSource = trim((string) ($body['base_source'] ?? 'product-catalog'));
$sidebarPosition = trim((string) ($body['sidebar_position'] ?? 'right'));
$regions = $body['regions'] ?? ['head' => [], 'content' => [], 'sidebar' => []];
$blocks = $body['blocks'] ?? [];
if ($category === '' || $title === '') {
echo json_encode(['success' => false, 'error' => 'Missing title or category']);
exit;
}
if (!is_array($blocks)) {
echo json_encode(['success' => false, 'error' => 'Blocks must be an array']);
exit;
}
if (!is_array($regions)) {
$regions = ['head' => [], 'content' => [], 'sidebar' => []];
}
$schema = json_encode([
'version' => $version,
'title' => $title,
'category' => $category,
'builder_mode' => $builderMode,
'head_preset' => $headPreset,
'sidebar_module' => $sidebarModule,
'footer_mode' => $footerMode,
'base_source' => $baseSource,
'sidebar_position' => $sidebarPosition,
'regions' => $regions,
'blocks' => array_values($blocks),
], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
$stmt = $pdo->prepare('INSERT INTO calc_builders (category_id, title, version, notes, schema_json, active, created_at, updated_at) VALUES (?, ?, ?, ?, ?, 1, NOW(), NOW())
ON DUPLICATE KEY UPDATE title = VALUES(title), version = VALUES(version), notes = VALUES(notes), schema_json = VALUES(schema_json), active = 1, updated_at = NOW()');
$stmt->execute([$category, $title, $version, $notes, $schema]);
$idStmt = $pdo->prepare('SELECT id FROM calc_builders WHERE category_id = ? LIMIT 1');
$idStmt->execute([$category]);
$id = (int) ($idStmt->fetchColumn() ?: 0);
echo json_encode(['success' => true, 'id' => $id]);
exit;
}
if ($method === 'DELETE') {
$category = isset($_GET['category']) ? trim((string) $_GET['category']) : '';
if ($category !== '') {
$stmt = $pdo->prepare('UPDATE calc_builders SET active = 0, updated_at = NOW() WHERE category_id = ?');
$stmt->execute([$category]);
}
echo json_encode(['success' => true]);
exit;
}
echo json_encode(['success' => false, 'error' => 'Method not allowed']);
function ensureCalcBuilderTable(PDO $pdo): void
{
$pdo->exec('CREATE TABLE IF NOT EXISTS calc_builders (
id INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
category_id VARCHAR(120) NOT NULL,
title VARCHAR(190) NOT NULL,
version VARCHAR(32) NOT NULL DEFAULT "1.0.0",
notes VARCHAR(255) NOT NULL DEFAULT "",
schema_json LONGTEXT NOT NULL,
active TINYINT(1) NOT NULL DEFAULT 1,
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
UNIQUE KEY uniq_calc_builders_category (category_id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci');
}
function hydrateCalcBuilderRow(array $row): array
{
$schema = json_decode((string) ($row['schema_json'] ?? ''), true);
if (!is_array($schema)) {
$schema = ['blocks' => []];
}
return [
'id' => (int) ($row['id'] ?? 0),
'category' => (string) ($row['category_id'] ?? ''),
'category_label' => (string) ($row['category_label'] ?? ''),
'title' => (string) ($row['title'] ?? ''),
'version' => (string) ($row['version'] ?? '1.0.0'),
'notes' => (string) ($row['notes'] ?? ''),
'builder_mode' => (string) ($schema['builder_mode'] ?? 'simple'),
'head_preset' => (string) ($schema['head_preset'] ?? 'current-default'),
'sidebar_module' => (string) ($schema['sidebar_module'] ?? 'price-summary'),
'footer_mode' => (string) ($schema['footer_mode'] ?? 'none'),
'base_source' => (string) ($schema['base_source'] ?? 'product-catalog'),
'sidebar_position' => (string) ($schema['sidebar_position'] ?? 'right'),
'regions' => is_array($schema['regions'] ?? null) ? $schema['regions'] : ['head' => [], 'content' => [], 'sidebar' => []],
'blocks' => is_array($schema['blocks'] ?? null) ? $schema['blocks'] : [],
'block_count' => is_array($schema['blocks'] ?? null) ? count($schema['blocks']) : 0,
];
}