<?php
/**
 * Site Builder API Router
 *
 * Handles asset uploads/management and project storage.
 * All assets are stored as files on disk (no base64, no localStorage).
 *
 * Endpoints:
 *   GET    /api/health               - Health check
 *   POST   /api/assets/upload        - Upload file (multipart/form-data)
 *   GET    /api/assets               - List all stored assets
 *   DELETE /api/assets/<filename>    - Delete an asset
 *   POST   /api/projects/save        - Save project data (JSON body)
 *   GET    /api/projects/list        - List all saved projects
 *   GET    /api/projects/<id>        - Load a specific project
 *   DELETE /api/projects/<id>        - Delete a project
 */

// --- Configuration ---
define('STORAGE_DIR', __DIR__ . '/../storage');
define('ASSETS_DIR', STORAGE_DIR . '/assets');
define('PROJECTS_DIR', STORAGE_DIR . '/projects');
define('TMP_DIR', STORAGE_DIR . '/tmp');
define('MAX_UPLOAD_SIZE', 500 * 1024 * 1024); // 500MB

// --- CORS & Headers ---
header('Content-Type: application/json');
header('Access-Control-Allow-Origin: *');
header('Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS');
header('Access-Control-Allow-Headers: Content-Type');

if ($_SERVER['REQUEST_METHOD'] === 'OPTIONS') {
    http_response_code(204);
    exit;
}

// --- Ensure storage directories ---
foreach ([STORAGE_DIR, ASSETS_DIR, PROJECTS_DIR, TMP_DIR] as $dir) {
    if (!is_dir($dir)) {
        mkdir($dir, 0755, true);
    }
}

// --- Routing ---
// Determine the API path from the request URI
$requestUri = $_SERVER['REQUEST_URI'] ?? '';
$path = parse_url($requestUri, PHP_URL_PATH);

// Strip trailing slash for consistency
$path = rtrim($path, '/');

$method = $_SERVER['REQUEST_METHOD'];

// Route the request
if ($path === '/api/health') {
    handleHealth();
} elseif ($path === '/api/assets/upload' && $method === 'POST') {
    handleUpload();
} elseif ($path === '/api/assets' && $method === 'GET') {
    handleListAssets();
} elseif (preg_match('#^/api/assets/(.+)$#', $path, $m) && $method === 'DELETE') {
    handleDeleteAsset(urldecode($m[1]));
} elseif ($path === '/api/projects/save' && ($method === 'POST' || $method === 'PUT')) {
    handleSaveProject();
} elseif ($path === '/api/projects/list' && $method === 'GET') {
    handleListProjects();
} elseif (preg_match('#^/api/projects/(.+)$#', $path, $m) && $method === 'GET') {
    handleGetProject(urldecode($m[1]));
} elseif (preg_match('#^/api/projects/(.+)$#', $path, $m) && $method === 'DELETE') {
    handleDeleteProject(urldecode($m[1]));
} else {
    sendError('Not Found', 404);
}

// ===========================================
// Helper Functions
// ===========================================

function sendJson($data, $status = 200) {
    http_response_code($status);
    echo json_encode($data);
    exit;
}

function sendError($message, $status = 400) {
    sendJson(['success' => false, 'error' => $message], $status);
}

function generateUniqueFilename($originalName) {
    $timestamp = round(microtime(true) * 1000);
    $rand = substr(str_shuffle('abcdefghijklmnopqrstuvwxyz0123456789'), 0, 6);
    // Sanitize original name
    $safeName = preg_replace('/[^\w.\-]/', '_', $originalName);
    $ext = pathinfo($safeName, PATHINFO_EXTENSION);
    $name = pathinfo($safeName, PATHINFO_FILENAME);
    if (empty($ext)) {
        $ext = 'bin';
    }
    return "{$timestamp}_{$rand}_{$name}.{$ext}";
}

function getAssetType($filename) {
    $ext = strtolower(pathinfo($filename, PATHINFO_EXTENSION));
    $imageExts = ['jpg', 'jpeg', 'png', 'gif', 'webp', 'svg', 'ico', 'bmp', 'tiff'];
    $videoExts = ['mp4', 'webm', 'ogg', 'mov', 'avi', 'mkv'];
    $cssExts = ['css'];
    $jsExts = ['js'];

    if (in_array($ext, $imageExts)) return 'image';
    if (in_array($ext, $videoExts)) return 'video';
    if (in_array($ext, $cssExts)) return 'css';
    if (in_array($ext, $jsExts)) return 'js';
    return 'file';
}

function getAssetInfo($filename) {
    $filepath = ASSETS_DIR . '/' . $filename;
    if (!is_file($filepath)) return null;

    $stat = stat($filepath);
    // Extract original name from naming scheme: timestamp_random_originalname
    $originalName = $filename;
    $parts = explode('_', $filename, 3);
    if (count($parts) >= 3) {
        $originalName = $parts[2];
    }

    return [
        'id' => $filename,
        'name' => $originalName,
        'filename' => $filename,
        'url' => '/storage/assets/' . rawurlencode($filename),
        'type' => getAssetType($filename),
        'size' => $stat['size'],
        'added' => intval($stat['mtime'] * 1000)
    ];
}

// ===========================================
// Endpoint Handlers
// ===========================================

function handleHealth() {
    sendJson(['status' => 'ok', 'server' => 'site-builder']);
}

function handleUpload() {
    $contentLength = intval($_SERVER['CONTENT_LENGTH'] ?? 0);
    if ($contentLength > MAX_UPLOAD_SIZE) {
        sendError('File too large. Maximum size is 500MB.', 413);
    }

    if (empty($_FILES)) {
        sendError('No files uploaded. Expected multipart/form-data with a "file" field.', 400);
    }

    $uploaded = [];

    // Handle single file field named 'file' or multiple files
    $files = [];
    if (isset($_FILES['file'])) {
        // Could be single or array upload
        if (is_array($_FILES['file']['name'])) {
            for ($i = 0; $i < count($_FILES['file']['name']); $i++) {
                $files[] = [
                    'name' => $_FILES['file']['name'][$i],
                    'tmp_name' => $_FILES['file']['tmp_name'][$i],
                    'error' => $_FILES['file']['error'][$i],
                    'size' => $_FILES['file']['size'][$i],
                ];
            }
        } else {
            $files[] = $_FILES['file'];
        }
    } else {
        // Accept any file field name
        foreach ($_FILES as $fileField) {
            if (is_array($fileField['name'])) {
                for ($i = 0; $i < count($fileField['name']); $i++) {
                    $files[] = [
                        'name' => $fileField['name'][$i],
                        'tmp_name' => $fileField['tmp_name'][$i],
                        'error' => $fileField['error'][$i],
                        'size' => $fileField['size'][$i],
                    ];
                }
            } else {
                $files[] = $fileField;
            }
        }
    }

    foreach ($files as $file) {
        if ($file['error'] !== UPLOAD_ERR_OK) {
            continue;
        }
        if (empty($file['name'])) {
            continue;
        }

        $uniqueName = generateUniqueFilename($file['name']);
        $destPath = ASSETS_DIR . '/' . $uniqueName;

        if (move_uploaded_file($file['tmp_name'], $destPath)) {
            $info = getAssetInfo($uniqueName);
            if ($info) {
                $uploaded[] = $info;
            }
        }
    }

    if (!empty($uploaded)) {
        sendJson(['success' => true, 'assets' => $uploaded]);
    } else {
        sendError('No files were uploaded', 400);
    }
}

function handleListAssets() {
    $assets = [];
    if (is_dir(ASSETS_DIR)) {
        $entries = scandir(ASSETS_DIR);
        sort($entries);
        foreach ($entries as $filename) {
            if ($filename === '.' || $filename === '..') continue;
            $info = getAssetInfo($filename);
            if ($info) {
                $assets[] = $info;
            }
        }
    }
    sendJson(['success' => true, 'assets' => $assets]);
}

function handleDeleteAsset($filename) {
    if (empty($filename)) {
        sendError('No filename specified', 400);
    }

    // Security: prevent directory traversal
    $safeFilename = basename($filename);
    $filepath = ASSETS_DIR . '/' . $safeFilename;

    if (!is_file($filepath)) {
        sendError('Asset not found', 404);
    }

    if (unlink($filepath)) {
        sendJson(['success' => true, 'deleted' => $safeFilename]);
    } else {
        sendError('Failed to delete asset', 500);
    }
}

function handleSaveProject() {
    $body = file_get_contents('php://input');
    $data = json_decode($body, true);

    if ($data === null) {
        sendError('Invalid JSON', 400);
    }

    $projectId = $data['id'] ?? null;
    if (empty($projectId)) {
        $projectId = 'project_' . time() . '_' . rand(1000, 9999);
        $data['id'] = $projectId;
    }

    // Sanitize project ID for filesystem
    $safeId = preg_replace('/[^\w.\-]/', '_', $projectId);
    $filepath = PROJECTS_DIR . '/' . $safeId . '.json';

    // Add timestamps
    if (empty($data['created'])) {
        $data['created'] = round(microtime(true) * 1000);
    }
    $data['modified'] = round(microtime(true) * 1000);

    $json = json_encode($data, JSON_PRETTY_PRINT);
    if (file_put_contents($filepath, $json) !== false) {
        sendJson([
            'success' => true,
            'project' => [
                'id' => $projectId,
                'name' => $data['name'] ?? 'Untitled',
                'modified' => $data['modified']
            ]
        ]);
    } else {
        sendError('Failed to save project', 500);
    }
}

function handleListProjects() {
    $projects = [];
    if (is_dir(PROJECTS_DIR)) {
        $entries = scandir(PROJECTS_DIR);
        foreach ($entries as $filename) {
            if (!str_ends_with($filename, '.json')) continue;
            $filepath = PROJECTS_DIR . '/' . $filename;
            $content = @file_get_contents($filepath);
            if ($content === false) continue;
            $data = @json_decode($content, true);
            if ($data === null) continue;

            $projects[] = [
                'id' => $data['id'] ?? pathinfo($filename, PATHINFO_FILENAME),
                'name' => $data['name'] ?? 'Untitled',
                'modified' => $data['modified'] ?? 0,
                'created' => $data['created'] ?? 0,
            ];
        }
    }

    // Sort by modified date descending
    usort($projects, function($a, $b) {
        return ($b['modified'] ?? 0) - ($a['modified'] ?? 0);
    });

    sendJson(['success' => true, 'projects' => $projects]);
}

function handleGetProject($projectId) {
    if (empty($projectId)) {
        handleListProjects();
        return;
    }

    $safeId = preg_replace('/[^\w.\-]/', '_', $projectId);
    $filepath = PROJECTS_DIR . '/' . $safeId . '.json';

    if (!is_file($filepath)) {
        sendError('Project not found', 404);
    }

    $content = file_get_contents($filepath);
    $data = json_decode($content, true);

    if ($data === null) {
        sendError('Failed to parse project data', 500);
    }

    sendJson(['success' => true, 'project' => $data]);
}

function handleDeleteProject($projectId) {
    if (empty($projectId)) {
        sendError('No project ID specified', 400);
    }

    $safeId = preg_replace('/[^\w.\-]/', '_', $projectId);
    $filepath = PROJECTS_DIR . '/' . $safeId . '.json';

    if (!is_file($filepath)) {
        sendError('Project not found', 404);
    }

    if (unlink($filepath)) {
        sendJson(['success' => true, 'deleted' => $projectId]);
    } else {
        sendError('Failed to delete project', 500);
    }
}
