<?php
if (!defined('ABSPATH')) {
    exit;
}

/**
 * Service for handling image resolution, fallbacks, gallery parsing, and media ownership.
 */
class NEXDIRECTORY_Media_Helper {

    /**
     * @var NEXDIRECTORY_User_Capabilities
     */
    private $user_caps;

    /**
     * Constructor.
     * * @param NEXDIRECTORY_User_Capabilities $user_caps Required for checking media ownership/moderation rights.
     */
    public function __construct($user_caps) {
        $this->user_caps = $user_caps;
    }

    /**
     * Shared brand-name fallback used by media placeholders.
     */
    private function get_platform_brand_name() {
        $brand_name = sanitize_text_field((string) get_option('nexdirectory_company_brand_name', ''));
        if ($brand_name === '') {
            $brand_name = sanitize_text_field((string) get_option('blogname', get_bloginfo('name')));
        }
        if ($brand_name === '') {
            $brand_name = __('Nex Directory Free', 'nexdirectory');
        }

        $brand_name = sanitize_text_field((string) apply_filters('nexdirectory_public_brand_name', $brand_name));
        return $brand_name !== '' ? $brand_name : __('Nex Directory Free', 'nexdirectory');
    }

    /**
     * Parses a string of URLs (separated by newlines, commas, pipes, or JSON) into a clean array.
     */
    public function parse_multiline_urls($raw) {
        $raw = (string) $raw;
        if ($raw === '') {
            return [];
        }

        // Normalize HTML/editor separators.
        $raw = preg_replace('/<br\s*\/?>/i', "\n", $raw);
        $raw = html_entity_decode($raw, ENT_QUOTES, 'UTF-8');

        // Accept JSON array payloads when imported/edited from external tools.
        $json_decoded = json_decode($raw, true);
        if (is_array($json_decoded)) {
            $json_values = [];
            foreach ($json_decoded as $item) {
                if (!is_scalar($item)) {
                    continue;
                }
                $candidate = esc_url_raw((string) $item);
                if ($candidate !== '') {
                    $json_values[] = $candidate;
                }
            }
            if (!empty($json_values)) {
                return array_values(array_unique($json_values));
            }
        }

        $lines = preg_split('/\r\n|\r|\n/', $raw) ?: [];
        
        // Backward compatibility with old comma-separated or pipe-separated values.
        if (count($lines) <= 1) {
            if (strpos($raw, ',') !== false) {
                $lines = array_merge($lines, preg_split('/\s*,\s*/', $raw) ?: []);
            } elseif (strpos($raw, '|') !== false) {
                $lines = array_merge($lines, preg_split('/\s*\|\s*/', $raw) ?: []);
            }
        }

        $urls = [];
        foreach ($lines as $line) {
            $line = trim($line);
            if (!$line) {
                continue;
            }

            // Extract multiple URLs from a single line if needed.
            if (preg_match_all('~https?://[^\s<>"\']+~i', $line, $matches) && !empty($matches[0])) {
                foreach ((array) $matches[0] as $match) {
                    $url = esc_url_raw((string) $match);
                    if ($url !== '') {
                        $urls[] = $url;
                    }
                }
                continue;
            }

            $url = esc_url_raw($line);
            if ($url !== '') {
                $urls[] = $url;
            }
        }
        
        return array_values(array_unique($urls));
    }

    /**
     * Ensures the cover image is included in the gallery array and deduplicates them.
     */
    public function normalize_cover_and_gallery_meta_urls($cover_url, $gallery_raw) {
        $cover_url = esc_url_raw((string) $cover_url);
        $gallery_urls = $this->parse_multiline_urls((string) $gallery_raw);

        if ($cover_url !== '' && !in_array($cover_url, $gallery_urls, true)) {
            array_unshift($gallery_urls, $cover_url);
        }

        return [
            'cover' => $cover_url,
            'gallery' => array_values(array_unique(array_filter($gallery_urls))),
        ];
    }

    /**
     * Updates post meta for videos, gallery, and cover images cleanly.
     */
    public function update_media_meta($post_id, $video_raw, $gallery_raw) {
        $post_id = absint($post_id);
        if ($post_id <= 0) return;

        $videos = $this->parse_multiline_urls($video_raw);
        $normalized = $this->normalize_cover_and_gallery_meta_urls(
            (string) get_post_meta($post_id, 'nexdirectory_cover_image_url', true),
            (string) $gallery_raw
        );
        
        $gallery = (array) ($normalized['gallery'] ?? []);
        $cover = (string) ($normalized['cover'] ?? '');
        
        update_post_meta($post_id, 'nexdirectory_video_urls', implode("\n", $videos));
        update_post_meta($post_id, 'nexdirectory_gallery_urls', implode("\n", $gallery));
        
        if ($cover !== '') {
            update_post_meta($post_id, 'nexdirectory_cover_image_url', $cover);
        }
    }

    /**
     * Returns maximum file upload limits defined in settings.
     */
    public function get_upload_limits() {
        $cover_max_kb = max(64, min(10240, absint((int) get_option('nexdirectory_upload_cover_max_kb', 500))));
        $gallery_max_kb = max(64, min(20480, absint((int) get_option('nexdirectory_upload_gallery_max_kb', 2000))));
        $gallery_max_files = max(1, min(100, absint((int) get_option('nexdirectory_upload_gallery_max_files', 10))));
        $file_max_kb = max(64, min(20480, absint((int) get_option('nexdirectory_upload_file_max_kb', 2048))));

        return [
            'cover_max_kb' => $cover_max_kb,
            'gallery_max_kb' => $gallery_max_kb,
            'gallery_max_files' => $gallery_max_files,
            'file_max_kb' => $file_max_kb,
            'cover_max_bytes' => $cover_max_kb * 1024,
            'gallery_max_bytes' => $gallery_max_kb * 1024,
            'file_max_bytes' => $file_max_kb * 1024,
        ];
    }

    /**
     * Compatibility provider for platform design settings used by legacy frontend flow.
     *
     * @return array<string, mixed>
     */
    public function get_platform_design_settings() {
        $accent = sanitize_hex_color((string) get_option('nexdirectory_style_accent_color', '#FF5E14')) ?: '#FF5E14';
        $hover = sanitize_hex_color((string) get_option('nexdirectory_style_accent_hover_color', '#E04F0D')) ?: '#E04F0D';

        $font_body = sanitize_text_field((string) get_option('nexdirectory_style_font_family', 'Inter, system-ui, -apple-system, sans-serif'));
        if ($font_body === '') {
            $font_body = 'Inter, system-ui, -apple-system, sans-serif';
        }
        $font_display = sanitize_text_field((string) get_option('nexdirectory_style_display_font_family', 'Oswald, Inter, sans-serif'));
        if ($font_display === '') {
            $font_display = 'Oswald, Inter, sans-serif';
        }
        $box_style = sanitize_key((string) get_option('nexdirectory_style_box_style', 'default'));
        if (!in_array($box_style, ['default', 'gradient', 'bold', 'neumorphic'], true)) {
            $box_style = 'default';
        }
        $button_style = sanitize_key((string) get_option('nexdirectory_style_button_style', 'solid'));
        if (!in_array($button_style, ['solid', 'outline', 'soft', 'dark'], true)) {
            $button_style = 'solid';
        }
        $button_radius_mode = sanitize_key((string) get_option('nexdirectory_style_button_radius_mode', 'inherit'));
        if (!in_array($button_radius_mode, ['inherit', 'pill', 'sharp'], true)) {
            $button_radius_mode = 'inherit';
        }
        $density_mode = sanitize_key((string) get_option('nexdirectory_style_density_mode', 'comfortable'));
        if (!in_array($density_mode, ['compact', 'comfortable', 'loose'], true)) {
            $density_mode = 'comfortable';
        }
        $border_mode = sanitize_key((string) get_option('nexdirectory_style_border_mode', 'subtle'));
        if (!in_array($border_mode, ['minimal', 'subtle', 'strong'], true)) {
            $border_mode = 'subtle';
        }
        $shadow_mode = sanitize_key((string) get_option('nexdirectory_style_shadow_mode', 'soft'));
        if (!in_array($shadow_mode, ['none', 'soft', 'medium', 'dramatic'], true)) {
            $shadow_mode = 'soft';
        }
        $content_width = sanitize_key((string) get_option('nexdirectory_style_content_width', 'standard'));
        if (!in_array($content_width, ['narrow', 'standard', 'wide', 'full'], true)) {
            $content_width = 'standard';
        }
        $input_style = sanitize_key((string) get_option('nexdirectory_style_input_style', 'outline'));
        if (!in_array($input_style, ['outline', 'filled', 'underlined'], true)) {
            $input_style = 'outline';
        }

        return [
            'use_defaults' => (string) get_option('nexdirectory_style_use_theme_defaults', '0') === '1',
            'accent' => $accent,
            'hover' => $hover,
            'on_primary' => sanitize_hex_color((string) get_option('nexdirectory_style_on_primary_color', '#FFFFFF')) ?: '#FFFFFF',
            'font_body' => $font_body,
            'font_display' => $font_display,
            'font_size_base' => sanitize_text_field((string) get_option('nexdirectory_style_font_size_base', '18px')) ?: '18px',
            'h2_size' => sanitize_text_field((string) get_option('nexdirectory_style_h2_size', '1.75rem')) ?: '1.75rem',
            'h3_size' => sanitize_text_field((string) get_option('nexdirectory_style_h3_size', '1.35rem')) ?: '1.35rem',
            'weight_body' => sanitize_text_field((string) get_option('nexdirectory_style_font_weight_body', '400')) ?: '400',
            'weight_heading' => sanitize_text_field((string) get_option('nexdirectory_style_font_weight_heading', '700')) ?: '700',
            'space_unit' => sanitize_text_field((string) get_option('nexdirectory_style_spacing_unit', '16px')) ?: '16px',
            'space_scale' => sanitize_text_field((string) get_option('nexdirectory_style_spacing_scale', '1')) ?: '1',
            'radius_md' => sanitize_text_field((string) get_option('nexdirectory_style_radius_md', '12px')) ?: '12px',
            'radius_lg' => sanitize_text_field((string) get_option('nexdirectory_style_radius_lg', '24px')) ?: '24px',
            'box_style' => $box_style,
            'button_style' => $button_style,
            'button_radius_mode' => $button_radius_mode,
            'density_mode' => $density_mode,
            'border_mode' => $border_mode,
            'shadow_mode' => $shadow_mode,
            'content_width' => $content_width,
            'input_style' => $input_style,
        ];
    }

    /**
     * Checks if a specific user is allowed to use an existing media library URL.
     */
    public function can_current_user_use_media_url($url, $user_id = 0) {
        $url = esc_url_raw((string) $url);
        if ($url === '') {
            return false;
        }
        
        $user_id = absint((int) $user_id);
        if ($user_id <= 0) {
            $user_id = get_current_user_id();
        }
        if ($user_id <= 0) {
            return false;
        }
        
        if ($this->user_caps->user_can_moderate_events($user_id)) {
            return true;
        }
        
        $attachment_id = attachment_url_to_postid($url);
        if ($attachment_id <= 0) {
            // External URLs remain allowed; ownership checks apply only to media-library assets.
            return true;
        }
        
        return (int) get_post_field('post_author', $attachment_id) === $user_id;
    }

    /**
     * Filters an array of URLs to ensure the user has permission to use them.
     */
    public function filter_media_urls_for_user(array $urls, $user_id = 0) {
        $filtered = [];
        foreach ($urls as $url) {
            $clean_url = esc_url_raw((string) $url);
            if ($clean_url !== '' && $this->can_current_user_use_media_url($clean_url, $user_id)) {
                $filtered[] = $clean_url;
            }
        }
        return array_values(array_unique($filtered));
    }

    /**
     * Takes raw gallery text input, parses it, filters by permission, and returns clean newline separated string.
     */
    public function filter_gallery_urls_text_for_user($raw, $user_id = 0) {
        $urls = $this->parse_multiline_urls((string) $raw);
        $urls = $this->filter_media_urls_for_user($urls, $user_id);
        return implode("\n", $urls);
    }

    /**
     * Generates an SVG data URI as a fallback when no image exists.
     */
    public function get_placeholder_image_data_uri($context = 'thumbnail', array $ui_labels = [], $brand_name = '') {
        $is_hero = $context === 'hero';
        
        // Use injected UI labels to prevent cross-service dependencies inside this helper
        $default_singular = sanitize_text_field((string) ($ui_labels['singular'] ?? __('Event', 'nexdirectory')));
        $kicker = sanitize_text_field((string) ($ui_labels['hero_kicker_default'] ?? ($brand_name . ' ' . __('Event', 'nexdirectory'))));
        
        $title = $is_hero ? $kicker : $default_singular;
        $subtitle = $brand_name !== '' ? $brand_name : $this->get_platform_brand_name();
        
        $width = $is_hero ? 1920 : 800;
        $height = $is_hero ? 1080 : 600;
        $accent_hex = sanitize_hex_color((string) get_option('nexdirectory_style_accent_color', '#FF5E14')) ?: '#FF5E14';
        $accent_rgb = [255, 94, 20];
        if (preg_match('/^#?([a-f0-9]{6})$/i', $accent_hex, $accent_match) === 1) {
            $accent_value = ltrim((string) $accent_match[1], '#');
            $accent_rgb = [
                (int) hexdec(substr($accent_value, 0, 2)),
                (int) hexdec(substr($accent_value, 2, 2)),
                (int) hexdec(substr($accent_value, 4, 2)),
            ];
        }
        $accent_overlay = 'rgba(' . implode(',', $accent_rgb) . ',0.25)';
        
        $svg = '<svg xmlns="http://www.w3.org/2000/svg" width="' . $width . '" height="' . $height . '" viewBox="0 0 ' . $width . ' ' . $height . '">'
            . '<defs><linearGradient id="g" x1="0" x2="1" y1="0" y2="1"><stop stop-color="#0B1221"/><stop offset="1" stop-color="#1F2A3D"/></linearGradient></defs>'
            . '<rect width="100%" height="100%" fill="url(#g)"/>'
            . '<circle cx="' . (int) round($width * 0.84) . '" cy="' . (int) round($height * 0.2) . '" r="' . (int) round($width * 0.12) . '" fill="' . esc_attr($accent_overlay) . '"/>'
            . '<text x="50%" y="48%" text-anchor="middle" font-family="Inter,Arial,sans-serif" font-size="' . ($is_hero ? '74' : '52') . '" fill="#FFFFFF" opacity="0.95" font-weight="700">' . esc_html($title) . '</text>'
            . '<text x="50%" y="57%" text-anchor="middle" font-family="Inter,Arial,sans-serif" font-size="' . ($is_hero ? '30' : '24') . '" fill="#FFFFFF" opacity="0.72">' . esc_html($subtitle) . '</text>'
            . '</svg>';
            
        return 'data:image/svg+xml;charset=UTF-8,' . rawurlencode($svg);
    }

    /**
     * Resolves the default image URL (either configured in settings or falls back to SVG placeholder).
     */
    public function get_default_image_url($context = 'thumbnail', $seed = 0, array $ui_labels = [], $brand_name = '') {
        $context = $context === 'hero' ? 'hero' : 'thumbnail';
        $option_key = $context === 'hero' ? 'nexdirectory_style_fallback_hero_url' : 'nexdirectory_style_fallback_thumb_url';
        $seed = absint((int) $seed);

        if ($context === 'hero') {
            $featured_source_id = $seed > 0 ? $seed : absint((int) get_queried_object_id());
            if ($featured_source_id > 0 && has_post_thumbnail($featured_source_id)) {
                $featured = get_the_post_thumbnail_url($featured_source_id, 'full');
                if (is_string($featured) && $featured !== '') {
                    return esc_url_raw($featured);
                }
            }
        }
        
        $configured = (string) get_option($option_key, '');
        if ($configured !== '') {
            $candidates = $this->parse_multiline_urls($configured);
            if (!empty($candidates)) {
                if ($context === 'hero') {
                    return esc_url_raw((string) $candidates[0]);
                }
                
                $count = count($candidates);
                if ($count === 1) {
                    return esc_url_raw((string) $candidates[0]);
                }
                
                if ($seed <= 0) {
                    $seed = absint((int) get_queried_object_id());
                }
                if ($seed <= 0) {
                    $request_uri = isset($_SERVER['REQUEST_URI']) ? sanitize_text_field(wp_unslash($_SERVER['REQUEST_URI'])) : '';
                    $seed = abs(crc32((string) wp_json_encode([
                        'uri' => $request_uri,
                        'context' => $context,
                    ])));
                }
                $index = $seed % $count;
                return esc_url_raw((string) $candidates[$index]);
            }
        }
        
        return $this->get_placeholder_image_data_uri($context, $ui_labels, $brand_name);
    }

    /**
     * Formats an image URL for display, intercepting demo placeholder URLs and replacing them cleanly.
     */
    public function normalize_event_image_url_for_display($url, $post_id = 0, $context = 'thumbnail', $seed_offset = 0, array $ui_labels = [], $brand_name = '') {
        $context = $context === 'hero' ? 'hero' : 'thumbnail';
        $post_id = absint((int) $post_id);
        $seed_offset = max(0, absint((int) $seed_offset));
        
        $url = esc_url_raw((string) $url);
        if ($url === '') {
            return esc_url_raw($this->get_default_image_url($context, $post_id + $seed_offset, $ui_labels, $brand_name));
        }

        $parts = wp_parse_url($url);
        if (!is_array($parts)) {
            return esc_url_raw($this->get_default_image_url($context, $post_id + $seed_offset, $ui_labels, $brand_name));
        }
        
        $host = strtolower((string) ($parts['host'] ?? ''));
        $path = strtolower((string) ($parts['path'] ?? ''));
        $query = (string) ($parts['query'] ?? '');
        
        if ($host === '') {
            return esc_url_raw($this->get_default_image_url($context, $post_id + $seed_offset, $ui_labels, $brand_name));
        }

        $is_demo_imported = $post_id > 0 && (string) get_post_meta($post_id, 'nexdirectory_demo_imported', true) === '1';
        $looks_unstable_demo_url = false;
        
        $legacy_stock_image_host = implode('.', ['source', 'un' . 'splash', 'com']);

        if (strpos($host, $legacy_stock_image_host) !== false) {
            $looks_unstable_demo_url = true;
        } elseif (strpos($host, 'example.com') !== false && (strpos($path, '/images/') !== false || strpos($path, '.jpg') !== false)) {
            $looks_unstable_demo_url = true;
        }

        // Map unstable demo URLs to the bundled placeholder so front-end rendering does not depend on remote stock images.
        if ($looks_unstable_demo_url || ($is_demo_imported && strpos($host, $legacy_stock_image_host) !== false)) {
            return esc_url_raw(plugins_url('assets/images/placeholder-hero.svg', NEXDIRECTORY_PLUGIN_FILE));
        }

        return $url;
    }

    /**
     * Resolves the canonical cover image for a specific post.
     */
    public function get_event_cover_image_url($post_id, $size = 'medium_large', $context = 'thumbnail', array $ui_labels = [], $brand_name = '') {
        $post_id = absint($post_id);
        if ($post_id <= 0) {
            return esc_url($this->get_default_image_url($context, 0, $ui_labels, $brand_name));
        }

        $cover = esc_url_raw((string) get_post_meta($post_id, 'nexdirectory_cover_image_url', true));
        if ($cover !== '') {
            $normalized_cover = $this->normalize_event_image_url_for_display($cover, $post_id, $context, 0, $ui_labels, $brand_name);
            return esc_url((string) $normalized_cover);
        }

        if (has_post_thumbnail($post_id)) {
            // Keep a single canonical source image across hero/card/map contexts.
            $thumb = get_the_post_thumbnail_url($post_id, 'full');
            if (is_string($thumb) && $thumb !== '') {
                return esc_url($thumb);
            }
        }

        return esc_url($this->get_default_image_url($context, $post_id, $ui_labels, $brand_name));
    }

    /**
     * Resolves all gallery images attached to an event.
     */
    public function get_event_gallery_image_urls($post_id, $context = 'thumbnail', array $ui_labels = [], $brand_name = '') {
        $post_id = absint((int) $post_id);
        $raw_urls = $this->parse_multiline_urls((string) get_post_meta($post_id, 'nexdirectory_gallery_urls', true));
        $normalized = [];
        
        foreach (array_values((array) $raw_urls) as $index => $raw_url) {
            $candidate = $this->normalize_event_image_url_for_display(
                (string) $raw_url,
                $post_id,
                $context,
                (int) $index + 1,
                $ui_labels,
                $brand_name
            );
            $candidate = esc_url_raw((string) $candidate);
            if ($candidate !== '') {
                $normalized[] = $candidate;
            }
        }
        
        return array_values(array_unique(array_filter($normalized)));
    }
}
