<?php
/**
 * BookiFlex
 *
 * @package   BookiFlex
 * @author    BookiFlex
 * @copyright Copyright (c) 2025 BookiFlex
 * @license   GPL-2.0-or-later
 *
 * @link      https://bookiflex.com
 */

declare(strict_types=1);

namespace BookiFlex\Plugin\UI\Elementor;

use BookiFlex\Plugin\UI\SearchFormRenderer;
use Elementor\Controls_Manager;
use Elementor\Widget_Base;

defined('ABSPATH') || exit;

/**
 * Elementor widget wrapping the <bookiflex-search-form> web component.
 *
 * Mirrors the Gutenberg `bookiflex/search-form` block (see UI\Blocks\SearchFormBlock):
 * controls map 1:1 to the block.json attributes, and rendering is delegated to the
 * shared SearchFormRenderer so both editors emit identical markup.
 */
class SearchFormWidget extends Widget_Base
{
    public function get_name(): string
    {
        return 'bookiflex-search-form';
    }

    public function get_title(): string
    {
        return esc_html__('BookiFlex Search Form', 'bookiflex');
    }

    public function get_icon(): string
    {
        return 'eicon-search';
    }

    /**
     * @return string[]
     */
    public function get_categories(): array
    {
        return ['bookiflex'];
    }

    /**
     * @return string[]
     */
    public function get_keywords(): array
    {
        return ['bookiflex', 'booking', 'search', 'hotel', 'reservation'];
    }

    /**
     * The web component script is registered on `init` by AbstractAssetsManager;
     * declaring it here lets Elementor enqueue it on both the frontend and the
     * editor preview.
     *
     * @return string[]
     */
    public function get_script_depends(): array
    {
        return ['bookiflex-search-form'];
    }

    protected function register_controls(): void
    {
        $this->registerLayoutSection();
        $this->registerGuestSection();
        $this->registerSearchSection();
        $this->registerAppearanceSection();
        $this->registerRadiusSection();
    }

    private function registerLayoutSection(): void
    {
        $this->start_controls_section('section_layout', [
            'label' => esc_html__('Layout', 'bookiflex'),
        ]);

        $this->add_control('layout', [
            'label'   => esc_html__('Layout', 'bookiflex'),
            'type'    => Controls_Manager::SELECT,
            'default' => 'bar',
            'options' => [
                'bar'     => esc_html__('Bar', 'bookiflex'),
                'hero'    => esc_html__('Hero', 'bookiflex'),
                'sidebar' => esc_html__('Sidebar', 'bookiflex'),
            ],
        ]);

        $this->add_control('buttonText', [
            'label'       => esc_html__('Button Text', 'bookiflex'),
            'type'        => Controls_Manager::TEXT,
            'default'     => '',
            'description' => esc_html__('Leave empty to use the locale default.', 'bookiflex'),
        ]);

        $this->add_control('locale', [
            'label'   => esc_html__('Locale', 'bookiflex'),
            'type'    => Controls_Manager::SELECT,
            'default' => '',
            'options' => [
                ''   => esc_html__('Auto', 'bookiflex'),
                'en' => 'English',
                'ru' => 'Русский',
                'pl' => 'Polski',
                'de' => 'Deutsch',
                'es' => 'Español',
                'it' => 'Italiano',
                'fr' => 'Français',
            ],
        ]);

        $this->end_controls_section();
    }

    private function registerGuestSection(): void
    {
        $this->start_controls_section('section_guests', [
            'label' => esc_html__('Guest Options', 'bookiflex'),
        ]);

        $this->add_control('hideGuests', [
            'label'        => esc_html__('Hide Guests', 'bookiflex'),
            'type'         => Controls_Manager::SWITCHER,
            'return_value' => 'yes',
            'default'      => '',
        ]);

        $this->add_control('hideChildren', [
            'label'        => esc_html__('Hide Children', 'bookiflex'),
            'type'         => Controls_Manager::SWITCHER,
            'return_value' => 'yes',
            'default'      => '',
        ]);

        $this->add_control('hidePromo', [
            'label'        => esc_html__('Hide Promo Code', 'bookiflex'),
            'type'         => Controls_Manager::SWITCHER,
            'return_value' => 'yes',
            'default'      => '',
        ]);

        $this->add_control('maxAdults', [
            'label' => esc_html__('Max Adults', 'bookiflex'),
            'type'  => Controls_Manager::NUMBER,
            'min'   => 1,
            'max'   => 30,
        ]);

        $this->add_control('maxChildren', [
            'label' => esc_html__('Max Children', 'bookiflex'),
            'type'  => Controls_Manager::NUMBER,
            'min'   => 0,
            'max'   => 20,
        ]);

        $this->add_control('maxChildAge', [
            'label' => esc_html__('Max Child Age', 'bookiflex'),
            'type'  => Controls_Manager::NUMBER,
            'min'   => 1,
            'max'   => 25,
        ]);

        $this->end_controls_section();
    }

    private function registerSearchSection(): void
    {
        $this->start_controls_section('section_search', [
            'label' => esc_html__('Search Settings', 'bookiflex'),
        ]);

        $this->add_control('submitMode', [
            'label'   => esc_html__('Search Results', 'bookiflex'),
            'type'    => Controls_Manager::SELECT,
            'default' => 'event',
            'options' => [
                'event'    => esc_html__('Modal Window', 'bookiflex'),
                'redirect' => esc_html__('On Page', 'bookiflex'),
            ],
        ]);

        $this->add_control('actionUrl', [
            'label'       => esc_html__('Redirect URL', 'bookiflex'),
            'type'        => Controls_Manager::URL,
            'options'     => false,
            'default'     => ['url' => ''],
            'condition'   => ['submitMode' => 'redirect'],
            'description' => esc_html__('Visitor is redirected to this page where results are displayed.', 'bookiflex'),
        ]);

        $this->end_controls_section();
    }

    private function registerAppearanceSection(): void
    {
        $this->start_controls_section('section_appearance', [
            'label' => esc_html__('Appearance', 'bookiflex'),
            'tab'   => Controls_Manager::TAB_STYLE,
        ]);

        $colors = [
            'colorPrimary'      => esc_html__('Button Color', 'bookiflex'),
            'colorPrimaryHover' => esc_html__('Button Hover Color', 'bookiflex'),
            'colorOnPrimary'    => esc_html__('Button Text', 'bookiflex'),
            'colorSurface'      => esc_html__('Background', 'bookiflex'),
            'colorOnSurface'    => esc_html__('Text Color', 'bookiflex'),
            'colorBorder'       => esc_html__('Borders & Dividers', 'bookiflex'),
            'colorMuted'        => esc_html__('Labels & Hints', 'bookiflex'),
        ];
        foreach ($colors as $id => $label) {
            $this->add_control($id, [
                'label' => $label,
                'type'  => Controls_Manager::COLOR,
            ]);
        }

        $texts = [
            'borderWidth'         => ['Border Width', '--bflex-border-width · e.g. 1px'],
            'gap'                 => ['Gap', '--bflex-gap · e.g. 0px'],
            'fieldPadding'        => ['Field Padding', '--bflex-field-padding · e.g. 12px 16px'],
            'fontFamily'          => ['Font Family', '--bflex-font-family'],
            'fontSize'            => ['Font Size', '--bflex-font-size · e.g. 14px'],
            'buttonTextTransform' => ['Button Text Transform', '--bflex-button-text-transform · e.g. uppercase'],
            'shadow'              => ['Box Shadow', '--bflex-shadow'],
        ];
        foreach ($texts as $id => $meta) {
            $this->add_control($id, [
                'label'       => esc_html__($meta[0], 'bookiflex'),
                'type'        => Controls_Manager::TEXT,
                'description' => $meta[1],
            ]);
        }

        $this->end_controls_section();
    }

    private function registerRadiusSection(): void
    {
        $this->start_controls_section('section_radius', [
            'label' => esc_html__('Border Radius', 'bookiflex'),
            'tab'   => Controls_Manager::TAB_STYLE,
        ]);

        $this->add_control('radius', [
            'label'       => esc_html__('All Corners', 'bookiflex'),
            'type'        => Controls_Manager::TEXT,
            'description' => 'CSS value: e.g. 8px, 0.5rem → --bflex-radius',
        ]);

        $corners = [
            'radiusTl' => esc_html__('Top Left (px)', 'bookiflex'),
            'radiusTr' => esc_html__('Top Right (px)', 'bookiflex'),
            'radiusBr' => esc_html__('Bottom Right (px)', 'bookiflex'),
            'radiusBl' => esc_html__('Bottom Left (px)', 'bookiflex'),
        ];
        foreach ($corners as $id => $label) {
            $this->add_control($id, [
                'label'      => $label,
                'type'       => Controls_Manager::SLIDER,
                'size_units' => ['px'],
                'range'      => ['px' => ['min' => 0, 'max' => 48]],
            ]);
        }

        $this->end_controls_section();
    }

    protected function render(): void
    {
        $settings = $this->get_settings_for_display();
        $attrs    = $this->mapSettingsToAttributes($settings);

        printf(
            '<div class="bookiflex-search-form-block">%s</div>',
            // SearchFormRenderer escapes every attribute/value internally.
            (new SearchFormRenderer())->renderTag($attrs) // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
        );
    }

    /**
     * Normalize Elementor settings into the camelCase attribute array expected
     * by SearchFormRenderer (same keys as the block.json schema).
     *
     * @param array<string, mixed> $settings
     *
     * @return array<string, mixed>
     */
    private function mapSettingsToAttributes(array $settings): array
    {
        $attrs = [
            'layout'              => $settings['layout'] ?? 'bar',
            'buttonText'          => $settings['buttonText'] ?? '',
            'locale'              => $settings['locale'] ?? '',
            'submitMode'          => $settings['submitMode'] ?? 'event',
            'actionUrl'           => $settings['actionUrl']['url'] ?? '',
            'hideGuests'          => ($settings['hideGuests'] ?? '') === 'yes',
            'hideChildren'        => ($settings['hideChildren'] ?? '') === 'yes',
            'hidePromo'           => ($settings['hidePromo'] ?? '') === 'yes',
            'maxAdults'           => ($settings['maxAdults'] ?? '') !== '' ? $settings['maxAdults'] : null,
            'maxChildren'         => ($settings['maxChildren'] ?? '') !== '' ? $settings['maxChildren'] : null,
            'maxChildAge'         => ($settings['maxChildAge'] ?? '') !== '' ? $settings['maxChildAge'] : null,
            'colorPrimary'        => $settings['colorPrimary'] ?? '',
            'colorPrimaryHover'   => $settings['colorPrimaryHover'] ?? '',
            'colorOnPrimary'      => $settings['colorOnPrimary'] ?? '',
            'colorSurface'        => $settings['colorSurface'] ?? '',
            'colorOnSurface'      => $settings['colorOnSurface'] ?? '',
            'colorBorder'         => $settings['colorBorder'] ?? '',
            'colorMuted'          => $settings['colorMuted'] ?? '',
            'radius'              => $settings['radius'] ?? '',
            'borderWidth'         => $settings['borderWidth'] ?? '',
            'gap'                 => $settings['gap'] ?? '',
            'fieldPadding'        => $settings['fieldPadding'] ?? '',
            'fontFamily'          => $settings['fontFamily'] ?? '',
            'fontSize'            => $settings['fontSize'] ?? '',
            'buttonTextTransform' => $settings['buttonTextTransform'] ?? '',
            'shadow'              => $settings['shadow'] ?? '',
        ];

        // Slider controls return ['size' => int, 'unit' => 'px']; the renderer
        // wants a bare number and only emits the var when the key is set.
        foreach (['radiusTl', 'radiusTr', 'radiusBr', 'radiusBl'] as $corner) {
            if (isset($settings[$corner]['size']) && $settings[$corner]['size'] !== '') {
                $attrs[$corner] = $settings[$corner]['size'];
            }
        }

        return $attrs;
    }
}
