<?php
/**
 * timeline-api.php  –  Backend für den Mobirise Timeline Block
 * SQLite · JSON · Bildupload
 */

// ─── CORS & Headers ────────────────────────────────────────────────────────
header('Content-Type: application/json; charset=UTF-8');
header('Access-Control-Allow-Origin: *');
header('Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS');
header('Access-Control-Allow-Headers: Content-Type, X-Requested-With');
if ($_SERVER['REQUEST_METHOD'] === 'OPTIONS') { http_response_code(200); exit; }

// ─── Config ────────────────────────────────────────────────────────────────
define('DB_PATH',     __DIR__ . '/data/timeline.db');
define('UPLOAD_DIR',  __DIR__ . '/uploads/');
define('UPLOAD_URL',  'uploads/');
define('MAX_IMG_SIZE', 8 * 1024 * 1024); // 8 MB
define('ALLOWED_TYPES', ['image/jpeg','image/png','image/gif','image/webp','image/svg+xml']);

// ─── Bootstrap ─────────────────────────────────────────────────────────────
if (!is_dir(dirname(DB_PATH))) mkdir(dirname(DB_PATH), 0755, true);
if (!is_dir(UPLOAD_DIR))       mkdir(UPLOAD_DIR,       0755, true);

$pdo = new PDO('sqlite:' . DB_PATH);
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$pdo->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC);
$pdo->exec("PRAGMA journal_mode=WAL; PRAGMA foreign_keys=ON;");

// ─── Schema ────────────────────────────────────────────────────────────────
$pdo->exec("
CREATE TABLE IF NOT EXISTS tl_config (
    key   TEXT PRIMARY KEY,
    value TEXT
);
CREATE TABLE IF NOT EXISTS tl_entries (
    id          INTEGER PRIMARY KEY AUTOINCREMENT,
    sort_order  INTEGER NOT NULL DEFAULT 0,
    icon        TEXT    NOT NULL DEFAULT 'mbri-star',
    title       TEXT    NOT NULL,
    content     TEXT    NOT NULL DEFAULT '',   -- HTML from TinyMCE
    image_url   TEXT,                          -- optional image
    image_alt   TEXT,
    tag         TEXT,                          -- optional badge/date label
    is_reverse  INTEGER NOT NULL DEFAULT 0,
    active      INTEGER NOT NULL DEFAULT 1,
    created_at  TEXT    NOT NULL DEFAULT (datetime('now')),
    updated_at  TEXT    NOT NULL DEFAULT (datetime('now'))
);
");

// ─── Seed defaults ─────────────────────────────────────────────────────────
$pdo->exec("
INSERT OR IGNORE INTO tl_config (key, value) VALUES
  ('title',           'Unsere Geschichte'),
  ('subtitle',        'Die wichtigsten Meilensteine im Überblick.'),
  ('timeline_color',  '#133996'),
  ('hover_color',     '#fc643f'),
  ('hover_effect',    '1'),
  ('reverse_timeline','0'),
  ('bg_color',        '#ffffff'),
  ('overlay_color',   '#cccccc'),
  ('overlay_opacity', '0.9');
");

if (!$pdo->query("SELECT COUNT(*) FROM tl_entries")->fetchColumn()) {
    $seed = [
        [1,'mbri-sites',       'Multi Homepages',    '<p>Donec eget ex porttitor, <strong>iaculis dolor</strong> sed, vehicula urna. Pellentesque finibus nisl ipsum.</p>',         null,'',1,'2024'],
        [2,'mbri-touch-swipe', 'Responsive Design',  '<p>Ut nec dui scelerisque, porta neque dictum, fringilla mi. Quisque pulvinar iaculis elit.</p>',                           null,'',0,'2022'],
        [3,'mbri-cash',        'Smart Watch',         '<p>Proin sollicitudin, neque et <em>ullamcorper mollis</em>, elit eros fermentum purus, id hendrerit sapien vel massa.</p>', null,'',1,'2020'],
        [4,'mbri-shopping-cart','Design out of the box','<p>Quisque ut convallis turpis, ac dignissim ipsum. Curabitur pulvinar, felis sit amet interdum finibus.</p>',           null,'',0,'2018'],
        [5,'mbri-file',        'Awesome Reports',     '<p>Nam rutrum, lacus eget varius sodales, massa erat rutrum velit, vitae dictum tellus ligula id orci.</p>',               null,'',1,'2016'],
        [6,'mbri-error',       'Hotmail launched',    '<p>Sed eu ex vel tortor sollicitudin luctus. Aenean sit amet volutpat tellus, eu porttitor dolor.</p>',                    null,'',0,'2010'],
    ];
    $s = $pdo->prepare("INSERT INTO tl_entries (sort_order,icon,title,content,image_url,image_alt,is_reverse,tag) VALUES(?,?,?,?,?,?,?,?)");
    foreach ($seed as $r) $s->execute($r);
}

// ─── Router ────────────────────────────────────────────────────────────────
$method  = $_SERVER['REQUEST_METHOD'];
$action  = $_GET['action'] ?? '';
$id      = isset($_GET['id']) ? (int)$_GET['id'] : null;

function ok($data, int $code = 200): never {
    http_response_code($code);
    echo json_encode($data, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT);
    exit;
}
function err(string $msg, int $code = 400): never {
    http_response_code($code);
    echo json_encode(['error' => $msg]);
    exit;
}
function body(): array {
    $raw = file_get_contents('php://input');
    return json_decode($raw, true) ?? [];
}
function cfg(PDO $pdo): array {
    $rows = $pdo->query("SELECT key,value FROM tl_config")->fetchAll();
    $out = [];
    foreach ($rows as $r) $out[$r['key']] = $r['value'];
    return $out;
}

// ────────────────────────────────────────────────────────────────────────────
// GET  /api.php?action=json   →  komplettes JSON für den Frontend-Block
// ────────────────────────────────────────────────────────────────────────────
if ($method === 'GET' && $action === 'json') {
    $entries = $pdo->query("SELECT * FROM tl_entries WHERE active=1 ORDER BY sort_order ASC")->fetchAll();
    // cast integers
    foreach ($entries as &$e) {
        $e['id']         = (int)$e['id'];
        $e['sort_order'] = (int)$e['sort_order'];
        $e['is_reverse'] = (bool)$e['is_reverse'];
        $e['active']     = (bool)$e['active'];
    }
    ok(['config' => cfg($pdo), 'entries' => $entries]);
}

// GET config
if ($method === 'GET' && $action === 'config') ok(cfg($pdo));

// GET all entries (admin, incl. inactive)
if ($method === 'GET' && $action === 'entries') {
    $entries = $pdo->query("SELECT * FROM tl_entries ORDER BY sort_order ASC")->fetchAll();
    foreach ($entries as &$e) {
        $e['id'] = (int)$e['id'];
        $e['is_reverse'] = (bool)$e['is_reverse'];
        $e['active'] = (bool)$e['active'];
    }
    ok($entries);
}

// GET single entry
if ($method === 'GET' && $action === 'entry' && $id) {
    $s = $pdo->prepare("SELECT * FROM tl_entries WHERE id=?");
    $s->execute([$id]);
    $e = $s->fetch();
    if (!$e) err('Not found', 404);
    $e['id'] = (int)$e['id'];
    $e['is_reverse'] = (bool)$e['is_reverse'];
    ok($e);
}

// ────────────────────────────────────────────────────────────────────────────
// POST /api.php?action=entry  →  neuen Eintrag anlegen
// ────────────────────────────────────────────────────────────────────────────
if ($method === 'POST' && $action === 'entry') {
    $b = body();
    if (empty($b['title'])) err('title required');
    $count = (int)$pdo->query("SELECT COUNT(*) FROM tl_entries")->fetchColumn();
    $s = $pdo->prepare("
        INSERT INTO tl_entries (sort_order,icon,title,content,image_url,image_alt,tag,is_reverse,active)
        VALUES (:so,:icon,:title,:content,:img,:alt,:tag,:rev,:active)
    ");
    $s->execute([
        ':so'      => $b['sort_order'] ?? $count + 1,
        ':icon'    => $b['icon']       ?? 'mbri-star',
        ':title'   => $b['title'],
        ':content' => $b['content']    ?? '',
        ':img'     => $b['image_url']  ?? null,
        ':alt'     => $b['image_alt']  ?? '',
        ':tag'     => $b['tag']        ?? '',
        ':rev'     => (int)($b['is_reverse'] ?? ($count % 2 !== 0)),
        ':active'  => (int)($b['active'] ?? 1),
    ]);
    ok(['id' => (int)$pdo->lastInsertId(), 'message' => 'created'], 201);
}

// ────────────────────────────────────────────────────────────────────────────
// PUT /api.php?action=entry&id=X  →  Eintrag aktualisieren
// ────────────────────────────────────────────────────────────────────────────
if ($method === 'PUT' && $action === 'entry' && $id) {
    $b = body();
    $allowed = ['sort_order','icon','title','content','image_url','image_alt','tag','is_reverse','active'];
    $set = []; $params = [':id' => $id];
    foreach ($allowed as $f) {
        if (array_key_exists($f, $b)) {
            $set[] = "$f=:$f";
            $params[":$f"] = $b[$f];
        }
    }
    if (empty($set)) err('nothing to update');
    $set[] = "updated_at=datetime('now')";
    $pdo->prepare("UPDATE tl_entries SET " . implode(',', $set) . " WHERE id=:id")->execute($params);
    ok(['message' => 'updated']);
}

// PUT config
if ($method === 'PUT' && $action === 'config') {
    $b = body();
    $s = $pdo->prepare("INSERT OR REPLACE INTO tl_config (key,value) VALUES (?,?)");
    foreach ($b as $k => $v) $s->execute([$k, $v]);
    ok(['message' => 'config saved']);
}

// PUT reorder  [{ id, sort_order }, ...]
if ($method === 'PUT' && $action === 'reorder') {
    $items = body();
    $s = $pdo->prepare("UPDATE tl_entries SET sort_order=:o WHERE id=:id");
    foreach ($items as $item) $s->execute([':o' => $item['sort_order'], ':id' => $item['id']]);
    ok(['message' => 'reordered']);
}

// ────────────────────────────────────────────────────────────────────────────
// DELETE /api.php?action=entry&id=X
// ────────────────────────────────────────────────────────────────────────────
if ($method === 'DELETE' && $action === 'entry' && $id) {
    // also delete associated image
    $e = $pdo->prepare("SELECT image_url FROM tl_entries WHERE id=?")->execute([$id]);
    $row = $pdo->query("SELECT image_url FROM tl_entries WHERE id=$id")->fetch();
    if ($row && $row['image_url'] && file_exists(__DIR__.'/'.$row['image_url'])) {
        @unlink(__DIR__.'/'.$row['image_url']);
    }
    $pdo->prepare("DELETE FROM tl_entries WHERE id=?")->execute([$id]);
    ok(['message' => 'deleted']);
}

// ────────────────────────────────────────────────────────────────────────────
// POST /api.php?action=upload  →  Bildupload
// ────────────────────────────────────────────────────────────────────────────
if ($method === 'POST' && $action === 'upload') {
    if (empty($_FILES['image'])) err('no file');
    $file = $_FILES['image'];
    if ($file['error'] !== UPLOAD_ERR_OK) err('upload error: ' . $file['error']);
    if ($file['size'] > MAX_IMG_SIZE) err('file too large (max 8MB)');

    $finfo = finfo_open(FILEINFO_MIME_TYPE);
    $mime  = finfo_file($finfo, $file['tmp_name']);
    finfo_close($finfo);
    if (!in_array($mime, ALLOWED_TYPES)) err('file type not allowed: ' . $mime);

    $ext  = pathinfo($file['name'], PATHINFO_EXTENSION) ?: 'jpg';
    $name = uniqid('img_', true) . '.' . strtolower($ext);
    $dest = UPLOAD_DIR . $name;
    if (!move_uploaded_file($file['tmp_name'], $dest)) err('could not save file');

    ok(['url' => UPLOAD_URL . $name, 'filename' => $name]);
}

err('unknown action or method', 404);
