<?php
declare(strict_types=1);
session_start();
if (!is_file(__DIR__.'/config.php')) {
  if (basename($_SERVER['SCRIPT_NAME'] ?? '') !== 'install.php') { header('Location: install.php'); exit; }
  return;
}
$config = require __DIR__.'/config.php';
try {
  $pdo = new PDO('mysql:host='.$config['db_host'].';dbname='.$config['db_name'].';charset=utf8mb4', $config['db_user'], $config['db_pass'], [
    PDO::ATTR_ERRMODE=>PDO::ERRMODE_EXCEPTION, PDO::ATTR_DEFAULT_FETCH_MODE=>PDO::FETCH_ASSOC, PDO::ATTR_EMULATE_PREPARES=>false
  ]);
} catch (Throwable $e) { http_response_code(500); exit('Database connection failed. Check config.php.'); }
$pdo->exec("CREATE TABLE IF NOT EXISTS production_books (id VARCHAR(64) PRIMARY KEY,order_id VARCHAR(64) NOT NULL,theme VARCHAR(190) NOT NULL,language ENUM('en','bn') NOT NULL DEFAULT 'en',book_json LONGTEXT NOT NULL,created_by INT UNSIGNED NULL,updated_by INT UNSIGNED NULL,created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,INDEX(order_id),INDEX(updated_at)) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4");
$pdo->exec("CREATE TABLE IF NOT EXISTS store_products (id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,title VARCHAR(190) NOT NULL,slug VARCHAR(190) NOT NULL UNIQUE,theme VARCHAR(190) NOT NULL,summary TEXT NOT NULL,price DECIMAL(12,2) NOT NULL DEFAULT 0,cover_image VARCHAR(255) DEFAULT NULL,gallery_json TEXT DEFAULT NULL,active TINYINT(1) NOT NULL DEFAULT 1,created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,INDEX(active,updated_at)) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4");
try{$pdo->exec("ALTER TABLE store_products ADD COLUMN title_bn VARCHAR(190) NOT NULL DEFAULT '' AFTER title");}catch(Throwable $e){}
try{$pdo->exec("ALTER TABLE store_products ADD COLUMN summary_bn TEXT NULL AFTER summary");}catch(Throwable $e){}
try{$pdo->exec("ALTER TABLE store_products ADD COLUMN sort_order INT NOT NULL DEFAULT 0 AFTER active");}catch(Throwable $e){}
$pdo->exec("CREATE TABLE IF NOT EXISTS store_coupons (id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,code VARCHAR(60) NOT NULL UNIQUE,discount_type ENUM('fixed','percent') NOT NULL DEFAULT 'fixed',discount_value DECIMAL(12,2) NOT NULL DEFAULT 0,active TINYINT(1) NOT NULL DEFAULT 1,expires_at DATE DEFAULT NULL,created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4");
$pdo->exec("CREATE TABLE IF NOT EXISTS store_settings (setting_key VARCHAR(80) PRIMARY KEY,setting_value TEXT NOT NULL) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4");
$pdo->exec("CREATE TABLE IF NOT EXISTS store_sliders (id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,title VARCHAR(190) NOT NULL DEFAULT '',subtitle TEXT,desktop_image VARCHAR(255) DEFAULT NULL,mobile_image VARCHAR(255) DEFAULT NULL,button_text VARCHAR(80) NOT NULL DEFAULT '',button_url VARCHAR(255) NOT NULL DEFAULT '',sort_order INT NOT NULL DEFAULT 0,active TINYINT(1) NOT NULL DEFAULT 1,created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,INDEX(active,sort_order)) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4");
$pdo->exec("CREATE TABLE IF NOT EXISTS store_orders (id VARCHAR(64) PRIMARY KEY,product_id INT UNSIGNED NOT NULL,customer_name VARCHAR(160) NOT NULL,phone VARCHAR(40) NOT NULL,delivery_address TEXT NOT NULL,delivery_zone ENUM('inside','outside') NOT NULL,delivery_fee DECIMAL(12,2) NOT NULL,notes TEXT,character_name VARCHAR(120) NOT NULL,character_age VARCHAR(20) NOT NULL,character_gender ENUM('girl','boy') NOT NULL,subtotal DECIMAL(12,2) NOT NULL,discount DECIMAL(12,2) NOT NULL DEFAULT 0,coupon_code VARCHAR(60) DEFAULT NULL,total DECIMAL(12,2) NOT NULL,status VARCHAR(30) NOT NULL DEFAULT 'placed',created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,INDEX(status,created_at),FOREIGN KEY(product_id) REFERENCES store_products(id)) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4");
try{$pdo->exec("ALTER TABLE store_orders ADD COLUMN customer_email VARCHAR(190) NULL AFTER phone");}catch(Throwable $e){}
try{$pdo->exec("ALTER TABLE store_orders ADD COLUMN book_language ENUM('en','bn') NOT NULL DEFAULT 'en' AFTER character_gender");}catch(Throwable $e){}
try{$pdo->exec("ALTER TABLE store_orders ADD COLUMN baby_photo VARCHAR(255) NULL AFTER book_language");}catch(Throwable $e){}
try{$pdo->exec("ALTER TABLE store_orders ADD COLUMN extra_photos_json TEXT NULL AFTER baby_photo");}catch(Throwable $e){}
$pdo->exec("CREATE TABLE IF NOT EXISTS store_email_log (id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,order_id VARCHAR(64) NOT NULL,recipient VARCHAR(190) NOT NULL,email_type ENUM('admin','customer') NOT NULL,sent TINYINT(1) NOT NULL DEFAULT 0,error_message VARCHAR(255) NULL,created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,INDEX(order_id,created_at)) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4");
$seedFile=__DIR__.'/data/store-products.json';if(is_file($seedFile)){$seed=json_decode((string)file_get_contents($seedFile),true);if(is_array($seed)){$exists=$pdo->prepare('SELECT id FROM store_products WHERE theme=? LIMIT 1');$insert=$pdo->prepare('INSERT INTO store_products(title,title_bn,slug,theme,summary,summary_bn,price,active,sort_order) VALUES(?,?,?,?,?,?,?,1,?)');foreach($seed as $p){$exists->execute([$p['theme']]);if(!$exists->fetchColumn())try{$insert->execute([$p['title'],$p['title_bn'],$p['slug'],$p['theme'],$p['summary'],$p['summary_bn'],$p['price'],$p['sort_order']]);}catch(Throwable $e){}}}}
foreach(['site_name'=>'Personalized StoryBook by WindowMind','site_logo'=>'assets/brand-mark.png','topbar_text'=>'Your child. Their story. Their unforgettable adventure.','topbar_text_bn'=>'আপনার শিশু। তার নিজের গল্প। তার অবিস্মরণীয় অভিযান।','notification_email'=>'','mail_from_email'=>'','mail_from_name'=>'Personalized StoryBook by WindowMind'] as $k=>$v){$s=$pdo->prepare("INSERT INTO store_settings(setting_key,setting_value) VALUES(?,?) ON DUPLICATE KEY UPDATE setting_value=IF(setting_value='',VALUES(setting_value),setting_value)");$s->execute([$k,$v]);}
$pdo->exec("UPDATE store_settings SET setting_value='assets/brand-mark.png' WHERE setting_key='site_logo' AND (setting_value='' OR setting_value='assets/brand-logo-header.png')");
$bannerCheck=$pdo->prepare('SELECT id FROM store_sliders WHERE desktop_image=? LIMIT 1');$bannerCheck->execute(['assets/storefront-banner.jpg']);if(!$bannerCheck->fetchColumn()){$pdo->prepare('INSERT INTO store_sliders(title,subtitle,desktop_image,button_text,button_url,sort_order,active) VALUES(?,?,?,?,?,-100,1)')->execute(['','','assets/storefront-banner.jpg','','#books']);}
function e(?string $v): string { return htmlspecialchars((string)$v, ENT_QUOTES, 'UTF-8'); }
function csrf(): string { if(empty($_SESSION['csrf'])) $_SESSION['csrf']=bin2hex(random_bytes(32)); return $_SESSION['csrf']; }
function check_csrf(): void { if(!hash_equals($_SESSION['csrf']??'', $_POST['csrf']??'')) { http_response_code(419); exit('Session expired. Please retry.'); } }
function user(): ?array { return $_SESSION['user']??null; }
function require_login(): void { if(!user()){ header('Location: cms.php?page=login'); exit; } }
function require_admin(): void { require_login(); if((user()['role']??'')!=='admin'){ http_response_code(403); exit('Admin access required.'); } }
function go(string $url='cms.php'): void { header('Location: '.$url); exit; }
function store_settings(PDO $pdo): array { $out=[]; foreach($pdo->query('SELECT setting_key,setting_value FROM store_settings') as $r)$out[$r['setting_key']]=$r['setting_value']; return $out; }
function save_store_setting(PDO $pdo,string $key,string $value): void { $s=$pdo->prepare('INSERT INTO store_settings(setting_key,setting_value) VALUES(?,?) ON DUPLICATE KEY UPDATE setting_value=VALUES(setting_value)');$s->execute([$key,$value]); }
function money($n): string { return '৳'.number_format((float)$n, 0); }
function upload_image(string $field, string $prefix): ?string {
  if(empty($_FILES[$field]['tmp_name'])) return null;
  if($_FILES[$field]['error']!==UPLOAD_ERR_OK || $_FILES[$field]['size']>15*1024*1024) throw new RuntimeException('Image must be under 15MB.');
  $finfo=new finfo(FILEINFO_MIME_TYPE); $mime=$finfo->file($_FILES[$field]['tmp_name']);
  $ext=['image/jpeg'=>'jpg','image/png'=>'png','image/webp'=>'webp'][$mime]??null;
  if(!$ext) throw new RuntimeException('Only JPG, PNG or WebP images are allowed.');
  $dir=__DIR__.'/uploads/'.date('Y/m'); if(!is_dir($dir)) mkdir($dir,0755,true);
  $name=$prefix.'-'.bin2hex(random_bytes(8)).'.'.$ext; $path=$dir.'/'.$name;
  if(!move_uploaded_file($_FILES[$field]['tmp_name'],$path)) throw new RuntimeException('Upload failed.');
  return str_replace(__DIR__.'/', '', $path);
}
const STATUSES=['placed','production','review','confirmed','delivery','delivered','canceled'];
const STATUS_LABELS=['placed'=>'Order Placed','production'=>'Production','review'=>'Review','confirmed'=>'Confirm + Advance','delivery'=>'Delivery List','delivered'=>'Delivered','canceled'=>'Canceled'];
