<?php
/**
 * Server-side photo download handler
 * Bypasses CORS restrictions by proxying through the server
 */

// Prevent any output before headers
ob_start();

session_start();

// Load configuration
$configFile = __DIR__ . '/config.php';
if (!file_exists($configFile)) {
    http_response_code(500);
    die('Configuration not found');
}
$config = require $configFile;

// Autoload classes
spl_autoload_register(function ($class) {
    $file = __DIR__ . '/classes/' . $class . '.php';
    if (file_exists($file)) {
        require_once $file;
    }
});

// Check authentication
$auth = new Auth();
if (!$auth->isAuthenticated()) {
    http_response_code(401);
    die('Not authenticated');
}

$action = $_GET['action'] ?? '';

/**
 * Fetch remote file content with proper error handling
 */
function fetchRemoteFile($url) {
    // Use cURL for more reliable fetching
    $ch = curl_init();
    curl_setopt_array($ch, [
        CURLOPT_URL => $url,
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_FOLLOWLOCATION => true,
        CURLOPT_MAXREDIRS => 5,
        CURLOPT_TIMEOUT => 60,
        CURLOPT_CONNECTTIMEOUT => 15,
        CURLOPT_USERAGENT => 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36',
        CURLOPT_SSL_VERIFYPEER => true,
        CURLOPT_HTTPHEADER => [
            'Accept: image/*, */*',
            'Referer: https://www.flickr.com/',
        ],
    ]);

    $content = curl_exec($ch);
    $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
    $contentType = curl_getinfo($ch, CURLINFO_CONTENT_TYPE);
    $error = curl_error($ch);
    curl_close($ch);

    // Check for errors
    if ($content === false || $httpCode !== 200) {
        error_log("Flickr fetch failed: HTTP $httpCode, Error: $error, URL: $url");
        return null;
    }

    // Validate it's actually an image
    if (strlen($content) < 1000) {
        error_log("Flickr fetch: Content too small (" . strlen($content) . " bytes), likely error page");
        return null;
    }

    // Check magic bytes for image formats
    $magicBytes = substr($content, 0, 8);
    $isJpeg = (substr($magicBytes, 0, 2) === "\xFF\xD8");
    $isPng = (substr($magicBytes, 0, 4) === "\x89PNG");
    $isGif = (substr($magicBytes, 0, 3) === "GIF");
    $isWebp = (substr($magicBytes, 0, 4) === "RIFF" && substr($content, 8, 4) === "WEBP");

    if (!$isJpeg && !$isPng && !$isGif && !$isWebp) {
        error_log("Flickr fetch: Not a valid image format. First bytes: " . bin2hex(substr($content, 0, 16)));
        return null;
    }

    // Determine content type from magic bytes if needed
    if (empty($contentType) || strpos($contentType, 'image/') !== 0) {
        if ($isJpeg) $contentType = 'image/jpeg';
        elseif ($isPng) $contentType = 'image/png';
        elseif ($isGif) $contentType = 'image/gif';
        elseif ($isWebp) $contentType = 'image/webp';
    }

    return [
        'content' => $content,
        'content_type' => $contentType,
        'size' => strlen($content),
    ];
}

/**
 * Clean filename for download
 */
function cleanFilename($name, $ext = 'jpg') {
    $name = preg_replace('/[<>:"\/\\\\|?*]/', '_', $name);
    $name = substr($name, 0, 100);
    return $name . '.' . $ext;
}

/**
 * Get file extension from URL or format
 */
function getExtension($url, $format = 'jpg') {
    // Check URL extension first
    $path = parse_url($url, PHP_URL_PATH);
    $ext = strtolower(pathinfo($path, PATHINFO_EXTENSION));

    if (in_array($ext, ['jpg', 'jpeg', 'png', 'gif', 'webp'])) {
        return $ext === 'jpeg' ? 'jpg' : $ext;
    }

    return $format ?: 'jpg';
}

/**
 * Check if URL is a valid Flickr image URL
 */
function isFlickrUrl($url) {
    // Flickr uses several domain/URL formats:
    // - farm{N}.staticflickr.com (static images)
    // - live.staticflickr.com (static images, modern)
    // - www.flickr.com/photo_download.gne (download endpoint for originals)
    $patterns = [
        '/^https?:\/\/farm\d+\.staticflickr\.com\//',
        '/^https?:\/\/live\.staticflickr\.com\//',
        '/^https?:\/\/farm\d+\.static\.flickr\.com\//',
        '/^https?:\/\/staticflickr\.com\//',
        '/^https?:\/\/c\d+\.staticflickr\.com\//',
        '/^https?:\/\/(www\.)?flickr\.com\/photo_download\.gne\?/',
    ];

    foreach ($patterns as $pattern) {
        if (preg_match($pattern, $url)) {
            return true;
        }
    }

    return false;
}

switch ($action) {

    // Download single photo
    case 'photo':
        $url = $_GET['url'] ?? '';
        $filename = $_GET['filename'] ?? 'photo';
        $format = $_GET['format'] ?? 'jpg';

        if (!$url) {
            http_response_code(400);
            die('URL required');
        }

        // Validate URL is from Flickr (multiple domain formats)
        if (!isFlickrUrl($url)) {
            http_response_code(400);
            die('Invalid URL - only Flickr URLs allowed: ' . htmlspecialchars($url));
        }

        $file = fetchRemoteFile($url);

        if (!$file) {
            http_response_code(502);
            die('Failed to fetch image from Flickr');
        }

        $ext = getExtension($url, $format);
        $safeFilename = cleanFilename($filename, $ext);

        // Clear ALL output buffers (there might be multiple levels)
        while (ob_get_level()) {
            ob_end_clean();
        }

        header('Content-Type: ' . $file['content_type']);
        header('Content-Length: ' . $file['size']);
        header('Content-Disposition: attachment; filename="' . $safeFilename . '"');
        header('Cache-Control: no-cache, must-revalidate');
        header('Pragma: public');

        echo $file['content'];
        exit;

    // Download multiple photos as ZIP
    case 'zip':
        // Get photo data from POST
        $photosJson = $_POST['photos'] ?? '';
        $albumName = $_POST['album_name'] ?? '';

        if (!$photosJson) {
            http_response_code(400);
            die('Photos data required');
        }

        $photos = json_decode($photosJson, true);

        if (!$photos || !is_array($photos) || count($photos) === 0) {
            http_response_code(400);
            die('Invalid photos data');
        }

        // Limit to prevent server overload
        if (count($photos) > 500) {
            http_response_code(400);
            die('Maximum 500 photos per archive');
        }

        // Create temp file for ZIP
        $tempFile = tempnam(sys_get_temp_dir(), 'vh_photos_');

        $zip = new ZipArchive();
        if ($zip->open($tempFile, ZipArchive::CREATE | ZipArchive::OVERWRITE) !== true) {
            http_response_code(500);
            die('Failed to create ZIP archive');
        }

        // Create folder name
        $folderName = $albumName ? preg_replace('/[<>:"\/\\\\|?*]/', '_', $albumName) : 'flickr_photos_' . date('Y-m-d');
        $folderName = substr($folderName, 0, 100);

        $usedNames = [];
        $successCount = 0;
        $failCount = 0;

        foreach ($photos as $photo) {
            $url = $photo['url'] ?? '';
            $title = $photo['title'] ?? $photo['id'] ?? 'photo';
            $format = $photo['format'] ?? 'jpg';
            $photoId = $photo['id'] ?? uniqid();

            if (!$url) {
                $failCount++;
                continue;
            }

            // Validate URL - use same function as single photo
            if (!isFlickrUrl($url)) {
                $failCount++;
                continue;
            }

            $file = fetchRemoteFile($url);

            if (!$file) {
                $failCount++;
                continue;
            }

            $ext = getExtension($url, $format);
            $filename = cleanFilename($title, $ext);

            // Ensure unique filename
            if (in_array($filename, $usedNames)) {
                $baseName = pathinfo($filename, PATHINFO_FILENAME);
                $filename = $baseName . '_' . $photoId . '.' . $ext;
            }
            $usedNames[] = $filename;

            $zip->addFromString($folderName . '/' . $filename, $file['content']);
            $successCount++;
        }

        $zip->close();

        if ($successCount === 0) {
            // Clean up temp file if it exists
            if (file_exists($tempFile)) {
                @unlink($tempFile);
            }
            http_response_code(502);
            die('Failed to download any photos. Check that photo URLs are valid.');
        }

        // Send ZIP file
        $zipFilename = $folderName . '.zip';
        $zipSize = filesize($tempFile);

        // Clear ALL output buffers
        while (ob_get_level()) {
            ob_end_clean();
        }

        header('Content-Type: application/zip');
        header('Content-Length: ' . $zipSize);
        header('Content-Disposition: attachment; filename="' . $zipFilename . '"');
        header('Cache-Control: no-cache, must-revalidate');
        header('Pragma: public');
        header('X-Photos-Downloaded: ' . $successCount);
        header('X-Photos-Failed: ' . $failCount);

        readfile($tempFile);
        unlink($tempFile);
        exit;

    default:
        ob_end_clean();
        http_response_code(400);
        die('Unknown action');
}
