<?php
/**
 * Cloudflare Worker Script Templates
 *
 * Generates worker JavaScript code for different storage providers.
 *
 * @package suspended-cloud/staticq
 * @since 2.1.0
 */

if (!defined('ABSPATH')) {
    exit;
}

if (class_exists('SQMedia_Cloudflare_Worker')) {
    return;
}

class SQMedia_Cloudflare_Worker {

    /**
     * Path to template files directory
     *
     * @return string
     */
    private static function templates_dir(): string {
        return __DIR__ . '/templates/';
    }

    /**
     * Read a template file from the templates directory
     *
     * @param string $filename Template filename
     * @return string Template contents
     */
    private static function read_template(string $filename): string {
        $path = self::templates_dir() . $filename;
        // phpcs:ignore WordPress.WP.AlternativeFunctions.file_get_contents_file_get_contents -- reading local template file
        $contents = file_get_contents($path);
        if ($contents === false) {
            return '';
        }
        return $contents;
    }

    /**
     * Get bindings configuration for worker deployment
     *
     * @param string $provider Storage provider (currently only 'r2')
     * @param array $config Configuration options
     * @return array Bindings array for API
     */
    public static function get_bindings(string $provider, array $config): array {
        return [
            [
                'type' => 'r2_bucket',
                'name' => 'MEDIA_BUCKET',
                'bucket_name' => $config['bucket_name'],
            ],
        ];
    }

    /**
     * Generate worker script for R2 storage
     *
     * @param array $config Configuration options
     * @return string JavaScript worker code
     */
    public static function generate_r2_worker(array $config): string {
        $uploads_prefix = $config['uploads_prefix'] ?? '/wp-content/uploads/';
        $bucket_prefix = $config['bucket_prefix'] ?? 'wp-content/uploads/';
        // Ensure bucket_prefix ends with /
        $bucket_prefix = rtrim($bucket_prefix, '/') . '/';
        $cache_ttl = $config['cache_ttl'] ?? 2592000; // 30 days
        $enable_fallback = $config['enable_fallback'] ?? true;
        $enable_variant_fallback = $config['enable_variant_fallback'] ?? true;
        $variant_fallback_cdn_ttl = $config['variant_fallback_cdn_ttl'] ?? 86400; // 1 day

        $origin_fallback_code = $enable_fallback ? self::get_origin_fallback_code() : '';
        $variant_fallback_code = $enable_variant_fallback ? self::get_variant_fallback_code() : '';
        $not_found_code = self::get_not_found_code();
        $enable_fallback_js = self::bool_to_js($enable_fallback);
        $enable_variant_fallback_js = self::bool_to_js($enable_variant_fallback);

        $template = self::read_template('worker-r2.js');

        return str_replace(
            array(
                '{{UPLOADS_PREFIX}}',
                '{{BUCKET_PREFIX}}',
                '{{CACHE_TTL}}',
                '{{ENABLE_FALLBACK}}',
                '{{ENABLE_VARIANT_FALLBACK}}',
                '{{VARIANT_FALLBACK_CDN_TTL}}',
                '{{ORIGIN_FALLBACK_CODE}}',
                '{{VARIANT_FALLBACK_CODE}}',
                '{{NOT_FOUND_CODE}}',
            ),
            array(
                $uploads_prefix,
                $bucket_prefix,
                $cache_ttl,
                $enable_fallback_js,
                $enable_variant_fallback_js,
                $variant_fallback_cdn_ttl,
                $origin_fallback_code,
                $variant_fallback_code,
                $not_found_code,
            ),
            $template
        );
    }

    /**
     * Get variant fallback code block (resize master on-the-fly via Cloudflare Image Resizing)
     *
     * When a variant file (e.g. image-300x200.jpg) is missing from storage,
     * this code parses the dimensions from the filename, locates the master file,
     * and uses Cloudflare Image Resizing to serve a resized version on-the-fly.
     * A short CDN cache ensures the real file replaces it once Phase 2 creates it.
     */
    private static function get_variant_fallback_code(): string {
        return self::read_template('worker-variant-fallback.js');
    }

    /**
     * Get origin fallback code block (fetch from origin server)
     *
     * Returns on success, falls through on failure so subsequent
     * fallbacks (variant resize) can be attempted.
     */
    private static function get_origin_fallback_code(): string {
        return self::read_template('worker-origin-fallback.js');
    }

    /**
     * Get not-found code block (final 404)
     */
    private static function get_not_found_code(): string {
        return self::read_template('worker-not-found.js');
    }

    /**
     * Convert PHP boolean to JavaScript boolean string
     */
    private static function bool_to_js(bool $value): string {
        return $value ? 'true' : 'false';
    }

    /**
     * Generate worker based on provider
     *
     * @param string $provider Storage provider (currently only 'r2')
     * @param array $config Configuration options
     * @return string JavaScript worker code
     */
    public static function generate(string $provider, array $config): string {
        return self::generate_r2_worker($config);
    }

    /**
     * Generate a simple test script to verify worker deployment
     *
     * @return string JavaScript worker code
     */
    public static function generate_test_worker(): string {
        return self::read_template('worker-test.js');
    }
}