<?php

namespace PhotoSphereViewer\Includes;

use Elementor\Controls_Manager;
use Elementor\Widget_Base;
use Elementor\Group_Control_Typography;
use Elementor\Modules\Promotions\Controls\Promotion_Control;

/**
 * AR 3D Viewer Elementor Widget
 *
 * Renders interactive 3D/AR models using the <model-viewer> web component.
 * Free: model source, poster, canvas size, auto-rotate, shadow intensity, alignment.
 * Pro:  environment image (HDR), skybox image, camera orbit, disable zoom, disable tap.
 */
class AR_3D_Viewer extends Widget_Base {

    private function is_pro_activated(): bool {
        return ProStatus::is_active();
    }

    public function get_name() {
        return 'psv-ar-3d-viewer';
    }

    public function get_title() {
        return __('AR 3D Model Viewer', 'photo-sphere-viewer');
    }

    public function get_icon() {
        return 'psv-widget-icon psv-widget-icon-ar-model';
    }

    public function get_categories() {
        return ['photo-sphere-viewer'];
    }

    public function get_keywords() {
        return [
            'ar',
            '3d',
            '3d model',
            'model',
            'model viewer',
            'viewer',
            'gltf',
            'glb',
            'augmented reality',
            'augmented',
            'reality',
            'psv',
            'photo sphere viewer',
            'product',
            'product viewer',
            'configurator',
            'woocommerce',
            'ecommerce',
            'usdz',
            'iOS ar',
            'webxr',
        ];
    }

    public function get_script_depends() {
        return ['psv-ar-model-viewer'];
    }

    protected function register_controls() {

        // =====================================================================
        // Section: 3D Model Source
        // =====================================================================
        $this->start_controls_section(
            '_ar_content_section',
            [
                'label' => __('3D Model', 'photo-sphere-viewer'),
                'tab'   => Controls_Manager::TAB_CONTENT,
            ]
        );

        $this->add_control(
            'ar_src_source_type',
            [
                'label'       => __('Model Source', 'photo-sphere-viewer'),
                'type'        => Controls_Manager::CHOOSE,
                'toggle'      => false,
                'default'     => 'remote',
                'render_type' => 'template',
                'options'     => [
                    'remote' => [
                        'title' => __('Remote URL', 'photo-sphere-viewer'),
                        'icon'  => 'eicon-link',
                    ],
                    'self'   => [
                        'title' => __('Media Library', 'photo-sphere-viewer'),
                        'icon'  => 'eicon-image-rollover',
                    ],
                ],
            ]
        );

        $this->add_control(
            'ar_model_url',
            [
                'label'         => __('Model URL', 'photo-sphere-viewer'),
                'type'          => Controls_Manager::URL,
                'description'   => __('Direct URL to a .glb or .gltf 3D model file.', 'photo-sphere-viewer'),
                'render_type'   => 'template',
                'placeholder'   => __('https://example.com/model.glb', 'photo-sphere-viewer'),
                'default'       => [
                    'url' => 'https://modelviewer.dev/shared-assets/models/Astronaut.glb',
                ],
                'label_block'   => true,
                'condition'     => ['ar_src_source_type' => 'remote'],
            ]
        );

        $this->add_control(
            'ar_model_file',
            [
                'label'       => __('Model File', 'photo-sphere-viewer'),
                'type'        => Controls_Manager::MEDIA,
                'description' => __('Select a .glb or .gltf model from the media library.', 'photo-sphere-viewer'),
                'render_type' => 'template',
                'options'     => false,
                'condition'   => ['ar_src_source_type' => 'self'],
            ]
        );

        $this->add_control(
            'ar_alt_text',
            [
                'label'       => __('Alt Text', 'photo-sphere-viewer'),
                'type'        => Controls_Manager::TEXT,
                'default'     => __('3D Model', 'photo-sphere-viewer'),
                'label_block' => true,
                'separator'   => 'before',
            ]
        );

        $this->add_control(
            'ar_poster_source_type',
            [
                'label'       => __('Poster Source', 'photo-sphere-viewer'),
                'type'        => Controls_Manager::CHOOSE,
                'toggle'      => false,
                'default'     => 'self',
                'render_type' => 'template',
                'options'     => [
                    'remote' => [
                        'title' => __('Remote URL', 'photo-sphere-viewer'),
                        'icon'  => 'eicon-link',
                    ],
                    'self'   => [
                        'title' => __('Media Library', 'photo-sphere-viewer'),
                        'icon'  => 'eicon-image-rollover',
                    ],
                ],
                'separator' => 'before',
            ]
        );

        $this->add_control(
            'ar_poster_url',
            [
                'label'       => __('Poster URL', 'photo-sphere-viewer'),
                'type'        => Controls_Manager::URL,
                'description' => __('Thumbnail displayed while the 3D model loads.', 'photo-sphere-viewer'),
                'render_type' => 'template',
                'options'     => false,
                'condition'   => ['ar_poster_source_type' => 'remote'],
            ]
        );

        $this->add_control(
            'ar_poster_image',
            [
                'label'       => __('Poster Image', 'photo-sphere-viewer'),
                'type'        => Controls_Manager::MEDIA,
                'description' => __('Thumbnail displayed while the 3D model loads.', 'photo-sphere-viewer'),
                'render_type' => 'template',
                'condition'   => ['ar_poster_source_type' => 'self'],
            ]
        );

        $this->end_controls_section();

        // =====================================================================
        // Section: Canvas (Dimensions)
        // =====================================================================
        $this->start_controls_section(
            '_ar_canvas_section',
            [
                'label' => __('Canvas', 'photo-sphere-viewer'),
                'tab'   => Controls_Manager::TAB_CONTENT,
            ]
        );

        $this->add_responsive_control(
            'ar_canvas_width',
            [
                'label'       => __('Width', 'photo-sphere-viewer'),
                'type'        => Controls_Manager::SLIDER,
                'size_units'  => ['px', '%', 'vw'],
                'range'       => [
                    'px' => ['min' => 100, 'max' => 2000, 'step' => 5],
                    '%'  => ['min' => 10,  'max' => 100],
                ],
                'default'     => ['unit' => '%', 'size' => 100],
                'render_type' => 'template',
                'selectors'   => [
                    '{{WRAPPER}} .psv-ar-viewer-wrapper'               => 'width: {{SIZE}}{{UNIT}};',
                    '{{WRAPPER}} .psv-ar-viewer-wrapper model-viewer'  => 'width: 100%;',
                ],
            ]
        );

        $this->add_responsive_control(
            'ar_canvas_height',
            [
                'label'       => __('Height', 'photo-sphere-viewer'),
                'type'        => Controls_Manager::SLIDER,
                'size_units'  => ['px', 'vh'],
                'range'       => [
                    'px' => ['min' => 100, 'max' => 2000, 'step' => 5],
                    'vh' => ['min' => 10,  'max' => 100],
                ],
                'default'     => ['unit' => 'px', 'size' => 500],
                'render_type' => 'template',
                'selectors'   => [
                    '{{WRAPPER}} .psv-ar-viewer-wrapper model-viewer' => 'height: {{SIZE}}{{UNIT}};',
                ],
            ]
        );

        $this->end_controls_section();

        // =====================================================================
        // Section: Camera & Display
        // =====================================================================
        $this->start_controls_section(
            '_ar_camera_section',
            [
                'label' => __('Camera & Display', 'photo-sphere-viewer'),
                'tab'   => Controls_Manager::TAB_CONTENT,
            ]
        );

        $this->add_control(
            'ar_auto_rotate',
            [
                'label'        => __('Auto Rotate', 'photo-sphere-viewer'),
                'type'         => Controls_Manager::SWITCHER,
                'label_on'     => __('Yes', 'photo-sphere-viewer'),
                'label_off'    => __('No', 'photo-sphere-viewer'),
                'return_value' => 'yes',
                'default'      => 'yes',
                'render_type'  => 'template',
            ]
        );

        $this->add_control(
            'ar_shadow_intensity',
            [
                'label'   => __('Shadow Intensity', 'photo-sphere-viewer'),
                'type'    => Controls_Manager::SLIDER,
                'range'   => [
                    'px' => ['min' => 0, 'max' => 10, 'step' => 0.1],
                ],
                'default' => ['unit' => 'px', 'size' => 1],
            ]
        );

        // ── Pro Features ──────────────────────────────────────────────────────
        $this->add_control(
            'ar_pro_camera_heading',
            [
                'label'     => __('Pro Features', 'photo-sphere-viewer'),
                'type'      => Controls_Manager::HEADING,
                'separator' => 'before',
            ]
        );

        $this->add_control(
            'ar_camera_orbit',
            [
                'label'       => __('Camera Orbit', 'photo-sphere-viewer'),
                'type'        => $this->is_pro_activated() ? Controls_Manager::TEXT : Promotion_Control::TYPE,
                'default'     => $this->is_pro_activated() ? '45deg 55deg 4m' : '',
                'description' => !$this->is_pro_activated()
                    ? __('Available in Pro version', 'photo-sphere-viewer')
                    : __('Initial camera angle. e.g. 45deg 55deg 4m', 'photo-sphere-viewer'),
                'render_type' => 'template',
            ]
        );

        $this->add_control(
            'ar_disable_zoom',
            [
                'label'        => __('Disable Zoom', 'photo-sphere-viewer'),
                'type'         => $this->is_pro_activated() ? Controls_Manager::SWITCHER : Promotion_Control::TYPE,
                'label_on'     => __('Yes', 'photo-sphere-viewer'),
                'label_off'    => __('No', 'photo-sphere-viewer'),
                'return_value' => 'yes',
                'default'      => '',
                'description'  => !$this->is_pro_activated()
                    ? __('Available in Pro version', 'photo-sphere-viewer')
                    : __('Prevent users from zooming in or out.', 'photo-sphere-viewer'),
                'render_type'  => 'template',
            ]
        );

        $this->add_control(
            'ar_disable_tap',
            [
                'label'        => __('Disable Tap to Rotate', 'photo-sphere-viewer'),
                'type'         => $this->is_pro_activated() ? Controls_Manager::SWITCHER : Promotion_Control::TYPE,
                'label_on'     => __('Yes', 'photo-sphere-viewer'),
                'label_off'    => __('No', 'photo-sphere-viewer'),
                'return_value' => 'yes',
                'default'      => '',
                'description'  => !$this->is_pro_activated()
                    ? __('Available in Pro version', 'photo-sphere-viewer')
                    : __('Prevent tap-to-rotate gesture on touch devices.', 'photo-sphere-viewer'),
                'render_type'  => 'template',
            ]
        );

        $this->end_controls_section();

        // =====================================================================
        // Section: Light & Environment (Pro)
        // =====================================================================
        $this->start_controls_section(
            '_ar_environment_section',
            [
                'label' => __('Light & Environment', 'photo-sphere-viewer'),
                'tab'   => Controls_Manager::TAB_CONTENT,
            ]
        );

        $this->add_control(
            'ar_env_source_type',
            [
                'label'       => __('Environment Image Source', 'photo-sphere-viewer'),
                'type'        => $this->is_pro_activated() ? Controls_Manager::CHOOSE : Promotion_Control::TYPE,
                'toggle'      => false,
                'default'     => 'remote',
                'render_type' => 'template',
                'options'     => $this->is_pro_activated() ? [
                    'remote' => [
                        'title' => __('Remote URL', 'photo-sphere-viewer'),
                        'icon'  => 'eicon-link',
                    ],
                    'self'   => [
                        'title' => __('Media Library', 'photo-sphere-viewer'),
                        'icon'  => 'eicon-image-rollover',
                    ],
                ] : [],
                'description' => !$this->is_pro_activated()
                    ? __('Available in Pro version', 'photo-sphere-viewer')
                    : __('HDR image for lighting and reflections.', 'photo-sphere-viewer'),
            ]
        );

        if ($this->is_pro_activated()) {
            $this->add_control(
                'ar_environment_url',
                [
                    'label'       => __('Environment Image URL', 'photo-sphere-viewer'),
                    'type'        => Controls_Manager::URL,
                    'description' => __('HDR image used for reflections and lighting.', 'photo-sphere-viewer'),
                    'render_type' => 'template',
                    'options'     => false,
                    'condition'   => ['ar_env_source_type' => 'remote'],
                ]
            );

            $this->add_control(
                'ar_environment_file',
                [
                    'label'       => __('Environment Image', 'photo-sphere-viewer'),
                    'type'        => Controls_Manager::MEDIA,
                    'description' => __('Select an HDR image from the media library.', 'photo-sphere-viewer'),
                    'render_type' => 'template',
                    'options'     => false,
                    'condition'   => ['ar_env_source_type' => 'self'],
                ]
            );
        }

        $this->add_control(
            'ar_skybox_source_type',
            [
                'label'       => __('Skybox Image Source', 'photo-sphere-viewer'),
                'type'        => $this->is_pro_activated() ? Controls_Manager::CHOOSE : Promotion_Control::TYPE,
                'toggle'      => false,
                'default'     => 'remote',
                'render_type' => 'template',
                'options'     => $this->is_pro_activated() ? [
                    'remote' => [
                        'title' => __('Remote URL', 'photo-sphere-viewer'),
                        'icon'  => 'eicon-link',
                    ],
                    'self'   => [
                        'title' => __('Media Library', 'photo-sphere-viewer'),
                        'icon'  => 'eicon-image-rollover',
                    ],
                ] : [],
                'separator'   => 'before',
                'description' => !$this->is_pro_activated()
                    ? __('Available in Pro version', 'photo-sphere-viewer')
                    : __('Background skybox image for the scene.', 'photo-sphere-viewer'),
            ]
        );

        if ($this->is_pro_activated()) {
            $this->add_control(
                'ar_skybox_url',
                [
                    'label'       => __('Skybox Image URL', 'photo-sphere-viewer'),
                    'type'        => Controls_Manager::URL,
                    'render_type' => 'template',
                    'options'     => false,
                    'condition'   => ['ar_skybox_source_type' => 'remote'],
                ]
            );

            $this->add_control(
                'ar_skybox_file',
                [
                    'label'       => __('Skybox Image', 'photo-sphere-viewer'),
                    'type'        => Controls_Manager::MEDIA,
                    'render_type' => 'template',
                    'options'     => false,
                    'condition'   => ['ar_skybox_source_type' => 'self'],
                ]
            );
        }

        $this->end_controls_section();

        // =====================================================================
        // Section: Style — Alignment
        // =====================================================================
        $this->start_controls_section(
            '_ar_style_section',
            [
                'label' => __('Alignment', 'photo-sphere-viewer'),
                'tab'   => Controls_Manager::TAB_STYLE,
            ]
        );

        $this->add_control(
            'ar_alignment',
            [
                'label'                => __('Alignment', 'photo-sphere-viewer'),
                'type'                 => Controls_Manager::CHOOSE,
                'default'              => 'center',
                'options'              => [
                    'left'   => [
                        'title' => __('Left', 'photo-sphere-viewer'),
                        'icon'  => 'eicon-h-align-left',
                    ],
                    'center' => [
                        'title' => __('Center', 'photo-sphere-viewer'),
                        'icon'  => 'eicon-h-align-center',
                    ],
                    'right'  => [
                        'title' => __('Right', 'photo-sphere-viewer'),
                        'icon'  => 'eicon-h-align-right',
                    ],
                ],
                'selectors_dictionary' => [
                    'left'   => 'justify-content: flex-start;',
                    'center' => 'justify-content: center;',
                    'right'  => 'justify-content: flex-end;',
                ],
                'selectors'            => [
                    '{{WRAPPER}} .elementor-widget-container' => 'display: flex; {{VALUE}};',
                ],
            ]
        );

        $this->end_controls_section();
    }

    protected function render() {
        $settings = $this->get_settings_for_display();
        $is_pro   = $this->is_pro_activated();

        // ── Resolve model URL ─────────────────────────────────────────────────
        $model_url = '';
        if ('self' === $settings['ar_src_source_type'] && !empty($settings['ar_model_file']['url'])) {
            $model_url = $settings['ar_model_file']['url'];
        } elseif (!empty($settings['ar_model_url']['url'])) {
            $model_url = $settings['ar_model_url']['url'];
        }

        if (empty($model_url)) {
            printf(
                '<div style="padding:30px;text-align:center;color:#999;border:2px dashed #ddd;border-radius:4px;">%s</div>',
                esc_html__('Please provide a 3D model source (.glb / .gltf).', 'photo-sphere-viewer')
            );
            return;
        }

        // ── Resolve poster ────────────────────────────────────────────────────
        $poster = '';
        if ('self' === $settings['ar_poster_source_type'] && !empty($settings['ar_poster_image']['url'])) {
            $poster = $settings['ar_poster_image']['url'];
        } elseif (!empty($settings['ar_poster_url']['url'])) {
            $poster = $settings['ar_poster_url']['url'];
        }

        $alt           = !empty($settings['ar_alt_text']) ? $settings['ar_alt_text'] : '';
        $shadow        = isset($settings['ar_shadow_intensity']['size']) ? floatval($settings['ar_shadow_intensity']['size']) : 1;
        $auto_rotate   = 'yes' === ($settings['ar_auto_rotate'] ?? '');

        // ── Pro: environment, skybox, camera orbit, disable zoom/tap ──────────
        $environment_url = '';
        $skybox_url      = '';
        $camera_orbit    = '';
        $disable_zoom    = false;
        $disable_tap     = false;

        if ($is_pro) {
            if (!empty($settings['ar_env_source_type'])) {
                if ('self' === $settings['ar_env_source_type'] && !empty($settings['ar_environment_file']['url'])) {
                    $environment_url = $settings['ar_environment_file']['url'];
                } elseif (!empty($settings['ar_environment_url']['url'])) {
                    $environment_url = $settings['ar_environment_url']['url'];
                }
            }

            if (!empty($settings['ar_skybox_source_type'])) {
                if ('self' === $settings['ar_skybox_source_type'] && !empty($settings['ar_skybox_file']['url'])) {
                    $skybox_url = $settings['ar_skybox_file']['url'];
                } elseif (!empty($settings['ar_skybox_url']['url'])) {
                    $skybox_url = $settings['ar_skybox_url']['url'];
                }
            }

            $camera_orbit = !empty($settings['ar_camera_orbit']) ? $settings['ar_camera_orbit'] : '';
            $disable_zoom = 'yes' === ($settings['ar_disable_zoom'] ?? '');
            $disable_tap  = 'yes' === ($settings['ar_disable_tap'] ?? '');
        }

        // ── Build <model-viewer> attributes ───────────────────────────────────
        $this->add_render_attribute('ar-viewer-model', [
            'src'              => esc_url($model_url),
            'alt'              => esc_attr($alt),
            'shadow-intensity' => esc_attr($shadow),
            'camera-controls'  => '',
            'touch-action'     => 'pan-y',
            'tone-mapping'     => 'neutral',
            'ar'               => '',
            'style'            => 'width:100%;display:block;',
        ]);

        if (!empty($poster)) {
            $this->add_render_attribute('ar-viewer-model', 'poster', esc_url($poster));
        }
        if ($auto_rotate) {
            $this->add_render_attribute('ar-viewer-model', 'auto-rotate', '');
        }
        if (!empty($environment_url)) {
            $this->add_render_attribute('ar-viewer-model', 'environment-image', esc_url($environment_url));
        }
        if (!empty($skybox_url)) {
            $this->add_render_attribute('ar-viewer-model', 'skybox-image', esc_url($skybox_url));
        }
        if (!empty($camera_orbit)) {
            $this->add_render_attribute('ar-viewer-model', 'camera-orbit', esc_attr($camera_orbit));
        }
        if ($disable_zoom) {
            $this->add_render_attribute('ar-viewer-model', 'disable-zoom', '');
        }
        if ($disable_tap) {
            $this->add_render_attribute('ar-viewer-model', 'disable-tap', '');
        }

        // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- attributes are escaped individually above
        printf(
            '<div class="psv-ar-viewer-wrapper"><model-viewer %s></model-viewer></div>',
            $this->get_render_attribute_string('ar-viewer-model')
        );
    }
}
