<?php

namespace MODELORA\Core;

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

class Shortcode
{
    private function is_debug_enabled(): bool
    {
        $enabled = defined('WP_DEBUG') && WP_DEBUG;
        return (bool) apply_filters('modelora_debug_logs_enabled', $enabled);
    }

    private function build_trace_id(): string
    {
        if (function_exists('wp_generate_uuid4')) {
            return 'modelora-' . wp_generate_uuid4();
        }

        return 'modelora-' . uniqid('', true);
    }

    private function sanitize_trace_id($trace_id): string
    {
        $raw = is_scalar($trace_id) ? (string) $trace_id : '';
        $clean = preg_replace('/[^a-zA-Z0-9\-_.:]/', '', $raw);

        return ! empty($clean) ? $clean : $this->build_trace_id();
    }

    private function debug_log(string $stage, array $context = []): void
    {
        if (! $this->is_debug_enabled()) {
            return;
        }

        /**
         * Allow debug logging integrations without hard-coding error_log usage.
         */
        do_action('modelora_debug_log', $stage, $context);
    }

    public function register(): void
    {
        add_shortcode('modelora_viewer', [$this, 'render']);
        add_shortcode('modelora_compare', [$this, 'render_compare']);
        add_action('init', [$this, 'register_block']);
    }

    private function resolve_model_id(array $atts, string $id_key, string $product_key): int
    {
        $model_id = (int) ($atts[$id_key] ?? 0);
        if (! $model_id && ! empty($atts[$product_key])) {
            $model_id = (int) get_post_meta((int) $atts[$product_key], '_modelora_model_id', true);
        }

        return $model_id;
    }

    private function resolve_model_source(int $model_id, string $trace_id): array
    {
        if (! $model_id) {
            return [
                'success' => false,
                'error' => esc_html__('No 3D model selected.', 'modelora-3d-product-viewer'),
            ];
        }

        $file_url = (string) get_post_meta($model_id, '_modelora_model_glb_url', true);
        if ($file_url === '') {
            $this->debug_log('shortcode_model_url_missing', ['traceId' => $trace_id, 'modelId' => $model_id]);
            return [
                'success' => false,
                'error' => esc_html__('3D model is not ready yet.', 'modelora-3d-product-viewer'),
            ];
        }

        $ext = strtolower((string) pathinfo($file_url, PATHINFO_EXTENSION));
        if (! in_array($ext, ['glb', 'gltf', 'usdz'], true)) {
            $this->debug_log('shortcode_model_bad_extension', ['traceId' => $trace_id, 'modelId' => $model_id, 'extension' => $ext]);
            return [
                'success' => false,
                'error' => esc_html__('This model format is uploaded but not web-renderable yet. Please use GLB/GLTF/USDZ or enable conversion.', 'modelora-3d-product-viewer'),
            ];
        }

        return [
            'success' => true,
            'model_id' => $model_id,
            'file_url' => $file_url,
            'extension' => $ext,
        ];
    }

    public function register_block(): void
    {
        register_block_type(MODELORA_PLUGIN_DIR . 'src/block/block.json', [
            'render_callback' => [$this, 'render_block'],
        ]);
    }

    public function render_block(array $attributes): string
    {
        $trace_id = isset($attributes['traceId']) ? $this->sanitize_trace_id($attributes['traceId']) : $this->build_trace_id();

        $atts = [
            'id' => isset($attributes['modelId']) ? (int) $attributes['modelId'] : 0,
            'preset' => isset($attributes['preset']) ? sanitize_key((string) $attributes['preset']) : 'studio',
            'ar' => ! empty($attributes['ar']) ? 1 : 0,
            'background' => array_key_exists('background', $attributes) && empty($attributes['background']) ? 0 : 1,
            'autoplay' => ! empty($attributes['autoplay']) ? 1 : 0,
            '_trace_id' => $trace_id,
        ];

        $this->debug_log('block_render_request', [
            'traceId' => $trace_id,
            'modelId' => $atts['id'],
            'preset' => $atts['preset'],
            'ar' => $atts['ar'],
            'background' => $atts['background'],
        ]);

        return $this->render($atts);
    }

    public function render(array $atts): string
    {
        wp_enqueue_style('modelora-viewer');
        wp_enqueue_script('modelora-model-viewer');
        wp_enqueue_script('modelora-viewer');

        $atts = shortcode_atts([
            'id' => 0,
            'preset' => 'studio',
            'background' => 1,
            'bg_color' => '',
            'bg_image' => '',
            'autoplay' => 0,
            'ar' => 0,
            'product_id' => 0,
            '_trace_id' => '',
        ], $atts, 'modelora_viewer');

        $trace_id = $this->sanitize_trace_id($atts['_trace_id']);
        $this->debug_log('shortcode_render_start', [
            'traceId' => $trace_id,
            'id' => (int) $atts['id'],
            'productId' => (int) $atts['product_id'],
            'preset' => (string) $atts['preset'],
            'ar' => ! empty($atts['ar']) ? 1 : 0,
        ]);

        $model_id = (int) $atts['id'];
        if (! $model_id && ! empty($atts['product_id'])) {
            $model_id = (int) get_post_meta((int) $atts['product_id'], '_modelora_model_id', true);
        }

        if (! $model_id) {
            $this->debug_log('shortcode_model_missing', ['traceId' => $trace_id]);
            return '<div class="modelora-inline-error">' . esc_html__('No 3D model selected.', 'modelora-3d-product-viewer') . '</div>';
        }

        $file_url = get_post_meta($model_id, '_modelora_model_glb_url', true);
        if (! $file_url) {
            $this->debug_log('shortcode_model_url_missing', ['traceId' => $trace_id, 'modelId' => $model_id]);
            return '<div class="modelora-inline-error">' . esc_html__('3D model is not ready yet.', 'modelora-3d-product-viewer') . '</div>';
        }

        $ext = strtolower((string) pathinfo((string) $file_url, PATHINFO_EXTENSION));
        if (! in_array($ext, ['glb', 'gltf', 'usdz'], true)) {
            $this->debug_log('shortcode_model_bad_extension', ['traceId' => $trace_id, 'modelId' => $model_id, 'extension' => $ext]);
            return '<div class="modelora-inline-error">' . esc_html__('This model format is uploaded but not web-renderable yet. Please use GLB/GLTF/USDZ or enable conversion.', 'modelora-3d-product-viewer') . '</div>';
        }

        $this->debug_log('shortcode_render_success', [
            'traceId' => $trace_id,
            'modelId' => $model_id,
            'fileUrl' => (string) $file_url,
        ]);

        ob_start();
        include MODELORA_PLUGIN_DIR . 'templates/viewer.php';

        return (string) ob_get_clean();
    }

    public function render_compare(array $atts): string
    {
        wp_enqueue_style('modelora-viewer');
        wp_enqueue_script('modelora-model-viewer');
        wp_enqueue_script('modelora-viewer');

        $atts = shortcode_atts([
            'left_id' => 0,
            'right_id' => 0,
            'left_product_id' => 0,
            'right_product_id' => 0,
            'left_label' => __('Model A', 'modelora-3d-product-viewer'),
            'right_label' => __('Model B', 'modelora-3d-product-viewer'),
            'preset' => 'studio',
            'background' => '#f8fafc',
            'sync' => 1,
            'wireframe' => 0,
            '_trace_id' => '',
        ], $atts, 'modelora_compare');

        $trace_id = $this->sanitize_trace_id($atts['_trace_id']);
        $left_id = $this->resolve_model_id($atts, 'left_id', 'left_product_id');
        $right_id = $this->resolve_model_id($atts, 'right_id', 'right_product_id');

        $left_model = $this->resolve_model_source($left_id, $trace_id);
        $right_model = $this->resolve_model_source($right_id, $trace_id);

        if (empty($left_model['success']) && empty($right_model['success'])) {
            return '<div class="modelora-inline-error">' . esc_html__('Both comparison models are missing or invalid.', 'modelora-3d-product-viewer') . '</div>';
        }

        $settings = get_option('modelora_settings', []);
        $loading_mode = ! empty($settings['lazy_load']) ? 'lazy' : 'eager';

        $left_label = sanitize_text_field((string) $atts['left_label']);
        $right_label = sanitize_text_field((string) $atts['right_label']);
        $preset = sanitize_key((string) $atts['preset']);
        $background = sanitize_hex_color((string) $atts['background']);
        if (empty($background)) {
            $background = '#f8fafc';
        }

        $sync_enabled = ! empty($atts['sync']) ? '1' : '0';
        $wireframe_enabled = ! empty($atts['wireframe']) ? '1' : '0';

        $this->debug_log('compare_shortcode_render', [
            'traceId' => $trace_id,
            'leftModelId' => (int) ($left_model['model_id'] ?? 0),
            'rightModelId' => (int) ($right_model['model_id'] ?? 0),
            'sync' => $sync_enabled,
            'wireframe' => $wireframe_enabled,
            'preset' => $preset,
        ]);

        ob_start();
        include MODELORA_PLUGIN_DIR . 'templates/compare.php';

        return (string) ob_get_clean();
    }
}

