<?php
/**
 * Multi-Site Headless CMS - High-Performance Media Origin Engine
 * Designed for StackCP / cPanel Linux Hosting (PHP 8.1+ & Imagick)
 */

declare(strict_types=1);

header('Content-Type: application/json; charset=utf-8');
header('Access-Control-Allow-Origin: *');
header('Access-Control-Allow-Methods: GET, POST, DELETE, OPTIONS');
header('Access-Control-Allow-Headers: Authorization, Content-Type, X-Site-ID, X-API-Key');

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

// 1. Load Configuration
$configFile = __DIR__ . '/config.php';
if (file_exists($configFile)) {
    require_once $configFile;
} else {
    // Defaults if config.php is not yet created
    define('MEDIA_API_KEY', getenv('MEDIA_API_KEY') ?: 'dev_media_secret_key_123456');
    define('STORAGE_PATH', __DIR__ . '/storage');
    define('PUBLIC_URL', (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] === 'on' ? 'https' : 'http') . '://' . ($_SERVER['HTTP_HOST'] ?? 'localhost'));
}

// 2. Helper Functions
function sendJson(array $data, int $statusCode = 200): void {
    http_response_code($statusCode);
    echo json_encode($data, JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT);
    exit;
}

function verifyAuth(): void {
    $authHeader = $_SERVER['HTTP_AUTHORIZATION'] ?? $_SERVER['REDIRECT_HTTP_AUTHORIZATION'] ?? '';
    $apiKeyHeader = $_SERVER['HTTP_X_API_KEY'] ?? '';
    
    $token = '';
    if (preg_match('/Bearer\s+(.*)$/i', $authHeader, $matches)) {
        $token = $matches[1];
    } elseif (!empty($apiKeyHeader)) {
        $token = $apiKeyHeader;
    }

    if (empty($token) || !hash_equals(MEDIA_API_KEY, $token)) {
        sendJson(['error' => 'Unauthorized: Invalid or missing API key'], 401);
    }
}

// 3. Routing
$uri = parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH);
$route = trim(str_replace('/media', '', $uri), '/');

// Health check endpoint (Public)
if ($route === 'health' || $route === 'api/health') {
    $imagickAvailable = extension_loaded('imagick');
    $gdAvailable = extension_loaded('gd');
    sendJson([
        'status' => 'ok',
        'engine' => $imagickAvailable ? 'imagick' : ($gdAvailable ? 'gd' : 'none'),
        'upload_max_filesize' => ini_get('upload_max_filesize'),
        'post_max_size' => ini_get('post_max_size'),
        'memory_limit' => ini_get('memory_limit'),
        'supported_formats' => ['avif', 'webp', 'jpeg', 'png', 'svg', 'pdf'],
        'timestamp' => date('c'),
    ]);
}

// Protect all other routes
verifyAuth();

// 4. Upload Handler (POST /upload or POST /api/upload)
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    if (!isset($_FILES['file']) || $_FILES['file']['error'] !== UPLOAD_ERR_OK) {
        $errorMsg = match ($_FILES['file']['error'] ?? UPLOAD_ERR_NO_FILE) {
            UPLOAD_ERR_INI_SIZE => 'Uploaded file exceeds upload_max_filesize directive in php.ini',
            UPLOAD_ERR_FORM_SIZE => 'Uploaded file exceeds MAX_FILE_SIZE directive in HTML form',
            UPLOAD_ERR_PARTIAL => 'File was only partially uploaded',
            UPLOAD_ERR_NO_FILE => 'No file was uploaded',
            default => 'Unknown upload error occurred',
        };
        sendJson(['error' => $errorMsg], 400);
    }

    $uploadedFile = $_FILES['file']['tmp_name'];
    $originalName = basename($_FILES['file']['name']);
    $fileSize = (int)$_FILES['file']['size'];
    $siteSlug = preg_replace('/[^a-z0-9_-]/i', '', $_POST['siteSlug'] ?? 'global');

    // Security MIME validation
    $finfo = new finfo(FILEINFO_MIME_TYPE);
    $mimeType = $finfo->file($uploadedFile);

    $allowedMimes = [
        'image/jpeg', 'image/png', 'image/webp', 'image/avif', 'image/svg+xml', 'image/gif', 'application/pdf'
    ];

    if (!in_array($mimeType, $allowedMimes, true)) {
        sendJson(['error' => "Unsupported file type: {$mimeType}"], 400);
    }

    // SHA-256 for duplicate detection
    $sha256 = hash_file('sha256', $uploadedFile);

    // Directory Path (if global, use storage/originals directly)
    $pathPrefix = ($siteSlug === 'global' || empty($siteSlug)) ? '' : $siteSlug . '/';
    $originalsDir = STORAGE_PATH . '/' . ($pathPrefix ? $pathPrefix . 'originals' : 'originals');
    $variantsDir = STORAGE_PATH . '/' . ($pathPrefix ? $pathPrefix . 'variants' : 'variants');
    $lqipDir = STORAGE_PATH . '/' . ($pathPrefix ? $pathPrefix . 'lqip' : 'lqip');

    foreach ([$originalsDir, $variantsDir, $lqipDir] as $dir) {
        if (!is_dir($dir)) {
            mkdir($dir, 0755, true);
        }
    }

    // Clean, SEO-friendly filename
    $baseName = pathinfo($originalName, PATHINFO_FILENAME);
    $extension = strtolower(pathinfo($originalName, PATHINFO_EXTENSION));
    $slugName = preg_replace('/[^a-z0-9_-]/i', '-', strtolower($baseName));
    $slugName = trim(preg_replace('/-+/', '-', $slugName), '-');
    if (empty($slugName)) {
        $slugName = 'image';
    }
    $safeName = $slugName . ($extension ? '.' . $extension : '');
    $originalDest = $originalsDir . '/' . $safeName;

    // If a file with same name exists but has different hash, add short hash to avoid collision
    if (file_exists($originalDest) && hash_file('sha256', $originalDest) !== $sha256) {
        $shortHash = substr($sha256, 0, 8);
        $safeName = $slugName . '-' . $shortHash . ($extension ? '.' . $extension : '');
        $originalDest = $originalsDir . '/' . $safeName;
    }

    if (!file_exists($originalDest)) {
        move_uploaded_file($uploadedFile, $originalDest);
    }

    // Process Images if Raster
    $width = 0;
    $height = 0;
    $lqipBase64 = null;
    $variants = [];

    $isRasterImage = in_array($mimeType, ['image/jpeg', 'image/png', 'image/webp', 'image/avif'], true);

    if ($isRasterImage && extension_loaded('imagick')) {
        try {
            $imagick = new Imagick($originalDest);
            $width = $imagick->getImageWidth();
            $height = $imagick->getImageHeight();

            // Generate tiny LQIP (20px blur)
            $lqip = clone $imagick;
            $lqip->resizeImage(20, 0, Imagick::FILTER_LANCZOS, 1);
            $lqip->setImageFormat('webp');
            $lqip->setImageCompressionQuality(30);
            $lqipBase64 = 'data:image/webp;base64,' . base64_encode($lqip->getImageBlob());
            $lqip->clear();

            // Target widths for responsive images
            $targetWidths = [400, 800, 1200, 1600];
            $formats = ['webp', 'avif'];

            foreach ($targetWidths as $targetW) {
                if ($targetW >= $width) {
                    continue; // Do not upscale smaller images
                }

                foreach ($formats as $format) {
                    $variantFile = "{$slugName}-w{$targetW}.{$format}";
                    $variantPath = $variantsDir . '/' . $variantFile;

                    if (!file_exists($variantPath)) {
                        $vImg = clone $imagick;
                        $vImg->resizeImage($targetW, 0, Imagick::FILTER_LANCZOS, 1);
                        $vImg->setImageFormat($format);
                        $vImg->setImageCompressionQuality($format === 'avif' ? 65 : 75);
                        $vImg->writeImage($variantPath);
                        $vHeight = $vImg->getImageHeight();
                        $vSize = filesize($variantPath);
                        $vImg->clear();
                    } else {
                        $vSize = filesize($variantPath);
                        $vHeight = (int)round(($height / $width) * $targetW);
                    }

                    $variants[] = [
                        'width' => $targetW,
                        'height' => $vHeight,
                        'format' => $format,
                        'storagePath' => ($pathPrefix ? $pathPrefix . 'variants/' : 'variants/') . $variantFile,
                        'cdnUrl' => PUBLIC_URL . '/storage/' . ($pathPrefix ? $pathPrefix . 'variants/' : 'variants/') . $variantFile,
                        'fileSizeBytes' => $vSize,
                    ];
                }
            }
            $imagick->clear();
        } catch (Exception $e) {
            error_log('Image processing warning: ' . $e->getMessage());
        }
    } elseif ($isRasterImage) {
        $imageSize = @getimagesize($originalDest);
        if ($imageSize) {
            $width = $imageSize[0];
            $height = $imageSize[1];
        }
    }

    $relativeStoragePath = ($pathPrefix ? $pathPrefix . 'originals/' : 'originals/') . $safeName;
    $originalCdnUrl = PUBLIC_URL . '/storage/' . $relativeStoragePath;

    sendJson([
        'success' => true,
        'url' => $originalCdnUrl,
        'cdnUrl' => $originalCdnUrl,
        'width' => $width,
        'height' => $height,
        'media' => [
            'originalFilename' => $originalName,
            'storagePath' => $relativeStoragePath,
            'cdnUrl' => $originalCdnUrl,
            'url' => $originalCdnUrl,
            'mimeType' => $mimeType,
            'width' => $width,
            'height' => $height,
            'fileSizeBytes' => $fileSize,
            'sha256' => $sha256,
            'lqipBase64' => $lqipBase64,
        ],
        'variants' => $variants,
    ], 201);
}

// 5. Delete Handler (DELETE /upload?path=...)
if ($_SERVER['REQUEST_METHOD'] === 'DELETE') {
    parse_str($_SERVER['QUERY_STRING'] ?? '', $params);
    $path = $params['path'] ?? '';
    
    if (empty($path)) {
        sendJson(['error' => 'Missing path parameter'], 400);
    }

    $safePath = STORAGE_PATH . '/' . ltrim(str_replace('..', '', $path), '/');
    if (file_exists($safePath) && is_file($safePath)) {
        unlink($safePath);
        sendJson(['success' => true, 'message' => 'File deleted']);
    }

    sendJson(['error' => 'File not found'], 404);
}

sendJson(['error' => 'Method Not Allowed'], 405);
