<?php

namespace Calio\Widgets;

use Elementor\Controls_Manager;
use Elementor\Group_Control_Border;
use Elementor\Group_Control_Box_Shadow;
use Elementor\Group_Control_Typography;
use Elementor\Repeater;

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

/**
 * Renders a stylish list with icon/image media, counters, badges and per-item highlight options.
 */
class StylishListWidget extends BaseWidget
{
    public function get_name(): string
    {
        return 'calio-stylish-list';
    }

    public function get_title(): string
    {
        return esc_html__('Stylish List', 'calio-addon');
    }

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

    public function get_style_depends(): array
    {
        return $this->resolve_widget_style_depends('calio-widget-stylish-list');
    }

    public function get_script_depends(): array
    {
        return $this->resolve_widget_script_depends('calio-widget-stylish-list');
    }

    protected function register_controls(): void
    {
        $this->register_layout_controls();
        $this->register_items_controls();
        $this->register_common_style_controls();
        $this->register_media_style_controls();
        $this->register_counter_style_controls();
        $this->register_title_style_controls();
        $this->register_description_style_controls();
        $this->register_badge_style_controls();
    }

    private function register_layout_controls(): void
    {
        $this->start_controls_section('stylish_list_layout_section', [
            'label' => esc_html__('Layout', 'calio-addon'),
        ]);

        $this->add_control('list_type', [
            'label' => esc_html__('List Type', 'calio-addon'),
            'type' => Controls_Manager::SELECT,
            'default' => 'vertical',
            'options' => [
                'vertical' => esc_html__('Vertical', 'calio-addon'),
                'horizontal' => esc_html__('Horizontal', 'calio-addon'),
            ],
        ]);
        $this->add_responsive_control('horizontal_columns', [
            'label' => esc_html__('Horizontal Columns', 'calio-addon'),
            'type' => Controls_Manager::NUMBER,
            'min' => 1,
            'max' => 6,
            'default' => 3,
            'tablet_default' => 2,
            'mobile_default' => 1,
            'condition' => ['list_type' => 'horizontal'],
            'selectors' => [
                '{{WRAPPER}} .calio-stylish-list.layout-horizontal .calio-stylish-list-items' => 'grid-template-columns: repeat({{VALUE}}, minmax(0, 1fr));',
            ],
        ]);
        $this->add_control('item_vertical_alignment', [
            'label' => esc_html__('Item Vertical Alignment', 'calio-addon'),
            'type' => Controls_Manager::SELECT,
            'default' => 'flex-start',
            'options' => [
                'flex-start' => esc_html__('Top', 'calio-addon'),
                'center' => esc_html__('Center', 'calio-addon'),
                'flex-end' => esc_html__('Bottom', 'calio-addon'),
            ],
            'selectors' => [
                '{{WRAPPER}} .calio-stylish-list-item' => 'align-items: {{VALUE}};',
                '{{WRAPPER}} .calio-stylish-list-item .calio-stylish-list-badge' => 'align-self: {{VALUE}};',
            ],
        ]);

        $this->add_control('use_divider', [
            'label' => esc_html__('Use Divider', 'calio-addon'),
            'type' => Controls_Manager::SWITCHER,
            'return_value' => 'yes',
            'default' => 'yes',
        ]);

        $this->add_control('use_counter', [
            'label' => esc_html__('Use Counter', 'calio-addon'),
            'type' => Controls_Manager::SWITCHER,
            'return_value' => 'yes',
            'default' => '',
        ]);

        $this->add_control('counter_style', [
            'label' => esc_html__('Counter Style', 'calio-addon'),
            'type' => Controls_Manager::SELECT,
            'default' => 'normal',
            'options' => [
                'normal' => esc_html__('Normal', 'calio-addon'),
                'decimal-leading-zero' => esc_html__('Decimal Leading Zero', 'calio-addon'),
                'upper-alpha' => esc_html__('Upper Alpha', 'calio-addon'),
                'lower-alpha' => esc_html__('Lower Alpha', 'calio-addon'),
                'upper-roman' => esc_html__('Upper Roman', 'calio-addon'),
                'lower-roman' => esc_html__('Lower Roman', 'calio-addon'),
                'lower-greek' => esc_html__('Lower Greek', 'calio-addon'),
            ],
            'condition' => ['use_counter' => 'yes'],
        ]);

        $this->add_control('counter_suffix', [
            'label' => esc_html__('Counter Suffix', 'calio-addon'),
            'type' => Controls_Manager::SELECT,
            'default' => 'dot',
            'options' => [
                'none' => esc_html__('None', 'calio-addon'),
                'dot' => esc_html__('Dot', 'calio-addon'),
                'bracket' => esc_html__('Bracket', 'calio-addon'),
                'colon' => esc_html__('Colon', 'calio-addon'),
            ],
            'condition' => ['use_counter' => 'yes'],
        ]);

        $this->add_control('hover_style', [
            'label' => esc_html__('Choose Hover Style', 'calio-addon'),
            'type' => Controls_Manager::SELECT,
            'default' => 'slide',
            'options' => [
                'none' => esc_html__('None', 'calio-addon'),
                'blur' => esc_html__('Blur', 'calio-addon'),
                'slide' => esc_html__('Slide', 'calio-addon'),
            ],
        ]);

        $this->add_control('use_entrance_animation', [
            'label' => esc_html__('Use Entrance Animation', 'calio-addon'),
            'type' => Controls_Manager::SWITCHER,
            'return_value' => 'yes',
            'default' => '',
        ]);

        $this->add_control('entrance_animation', [
            'label' => esc_html__('Entrance Animation', 'calio-addon'),
            'type' => Controls_Manager::SELECT,
            'default' => 'fade-up',
            'options' => [
                'fade-up' => esc_html__('Fade Up', 'calio-addon'),
                'fade-left' => esc_html__('Fade Left', 'calio-addon'),
                'zoom-in' => esc_html__('Zoom In', 'calio-addon'),
            ],
            'condition' => ['use_entrance_animation' => 'yes'],
        ]);

        $this->add_control('animation_duration', [
            'label' => esc_html__('Animation Duration (ms)', 'calio-addon'),
            'type' => Controls_Manager::NUMBER,
            'default' => 650,
            'min' => 100,
            'max' => 4000,
            'step' => 50,
            'condition' => ['use_entrance_animation' => 'yes'],
        ]);

        $this->add_control('animation_stagger', [
            'label' => esc_html__('Animation Delay In Between (ms)', 'calio-addon'),
            'type' => Controls_Manager::NUMBER,
            'default' => 120,
            'min' => 0,
            'max' => 1200,
            'step' => 20,
            'condition' => ['use_entrance_animation' => 'yes'],
        ]);

        $this->end_controls_section();
    }

    private function register_items_controls(): void
    {
        $this->start_controls_section('stylish_list_items_section', [
            'label' => esc_html__('List Items', 'calio-addon'),
        ]);

        $repeater = new Repeater();
        $repeater->add_control('title', [
            'label' => esc_html__('Title', 'calio-addon'),
            'type' => Controls_Manager::TEXT,
            'default' => esc_html__('Header Footer Builder', 'calio-addon'),
            'label_block' => true,
        ]);
        $repeater->add_control('description', [
            'label' => esc_html__('Description', 'calio-addon'),
            'type' => Controls_Manager::TEXTAREA,
            'default' => esc_html__('There are many variations of passages of lorem ipsum available, but the majority have suffered.', 'calio-addon'),
        ]);
        $repeater->add_control('media_type', [
            'label' => esc_html__('Media Type', 'calio-addon'),
            'type' => Controls_Manager::SELECT,
            'default' => 'icon',
            'options' => [
                'none' => esc_html__('None', 'calio-addon'),
                'icon' => esc_html__('Icon', 'calio-addon'),
                'image' => esc_html__('Image', 'calio-addon'),
            ],
        ]);
        $repeater->add_control('icon', [
            'label' => esc_html__('Icon', 'calio-addon'),
            'type' => Controls_Manager::ICONS,
            'default' => [
                'value' => 'fas fa-check',
                'library' => 'fa-solid',
            ],
            'condition' => ['media_type' => 'icon'],
        ]);
        $repeater->add_control('image', [
            'label' => esc_html__('Image', 'calio-addon'),
            'type' => Controls_Manager::MEDIA,
            'condition' => ['media_type' => 'image'],
        ]);

        $repeater->add_control('show_badge', [
            'label' => esc_html__('Show Badge', 'calio-addon'),
            'type' => Controls_Manager::SWITCHER,
            'return_value' => 'yes',
            'default' => '',
        ]);
        $repeater->add_control('badge_text', [
            'label' => esc_html__('Badge Text', 'calio-addon'),
            'type' => Controls_Manager::TEXT,
            'default' => esc_html__('New', 'calio-addon'),
            'condition' => ['show_badge' => 'yes'],
        ]);
        $repeater->add_control('badge_text_color', [
            'label' => esc_html__('Badge Text Color', 'calio-addon'),
            'type' => Controls_Manager::COLOR,
            'condition' => ['show_badge' => 'yes'],
        ]);
        $repeater->add_control('badge_bg_color', [
            'label' => esc_html__('Badge Background Color', 'calio-addon'),
            'type' => Controls_Manager::COLOR,
            'condition' => ['show_badge' => 'yes'],
        ]);
        $repeater->add_control('link', [
            'label' => esc_html__('Link', 'calio-addon'),
            'type' => Controls_Manager::URL,
            'default' => ['url' => ''],
        ]);

        $repeater->add_control('add_particular_style', [
            'label' => esc_html__('Add Particular Style', 'calio-addon'),
            'type' => Controls_Manager::SWITCHER,
            'return_value' => 'yes',
            'default' => '',
        ]);
        $repeater->add_control('particular_bg_color', [
            'label' => esc_html__('Background Color', 'calio-addon'),
            'type' => Controls_Manager::COLOR,
            'condition' => ['add_particular_style' => 'yes'],
        ]);
        $repeater->add_control('particular_border_color', [
            'label' => esc_html__('Border Color', 'calio-addon'),
            'type' => Controls_Manager::COLOR,
            'condition' => ['add_particular_style' => 'yes'],
        ]);
        $repeater->add_control('particular_icon_color', [
            'label' => esc_html__('Icon Color', 'calio-addon'),
            'type' => Controls_Manager::COLOR,
            'condition' => ['add_particular_style' => 'yes'],
        ]);
        $repeater->add_control('particular_icon_bg_color', [
            'label' => esc_html__('Icon Background Color', 'calio-addon'),
            'type' => Controls_Manager::COLOR,
            'condition' => ['add_particular_style' => 'yes'],
        ]);

        $this->add_control('items', [
            'label' => esc_html__('Items', 'calio-addon'),
            'type' => Controls_Manager::REPEATER,
            'fields' => $repeater->get_controls(),
            'title_field' => '{{{ title }}}',
            'default' => [
                [
                    'title' => esc_html__('Header Footer Builder', 'calio-addon'),
                    'description' => esc_html__('There are many variations of passages of lorem ipsum available, but the majority have suffered.', 'calio-addon'),
                    'show_badge' => 'yes',
                    'badge_text' => 'Popular',
                    'add_particular_style' => 'yes',
                    'particular_bg_color' => '#F8FAFC',
                    'particular_border_color' => '#C7D2FE',
                    'particular_icon_color' => '#4338CA',
                    'particular_icon_bg_color' => '#EEF2FF',
                ],
                [
                    'title' => esc_html__('Widget Builder', 'calio-addon'),
                    'description' => esc_html__('Build custom widget rows with icon, media and context notes for each capability.', 'calio-addon'),
                ],
                [
                    'title' => esc_html__('Mega Menu Builder', 'calio-addon'),
                    'description' => esc_html__('Use flexible list content to explain key addon modules with clearer scanning.', 'calio-addon'),
                ],
            ],
        ]);

        $this->end_controls_section();
    }

    private function register_common_style_controls(): void
    {
        $this->start_controls_section('stylish_list_style_common', [
            'label' => esc_html__('Common', 'calio-addon'),
            'tab' => Controls_Manager::TAB_STYLE,
        ]);

        $this->add_control('stylish_list_item_gap', [
            'label' => esc_html__('Item Spacing', 'calio-addon'),
            'type' => Controls_Manager::SLIDER,
            'size_units' => ['px'],
            'range' => [
                'px' => ['min' => 0, 'max' => 50],
            ],
            'default' => ['unit' => 'px', 'size' => 16],
            'selectors' => [
                '{{WRAPPER}} .calio-stylish-list-items' => 'gap: {{SIZE}}{{UNIT}};',
            ],
        ]);
        $this->add_responsive_control('stylish_list_content_alignment', [
            'label' => esc_html__('Content Alignment', 'calio-addon'),
            'type' => Controls_Manager::CHOOSE,
            'options' => [
                'left' => [
                    'title' => esc_html__('Left', 'calio-addon'),
                    'icon' => 'eicon-text-align-left',
                ],
                'center' => [
                    'title' => esc_html__('Center', 'calio-addon'),
                    'icon' => 'eicon-text-align-center',
                ],
                'right' => [
                    'title' => esc_html__('Right', 'calio-addon'),
                    'icon' => 'eicon-text-align-right',
                ],
            ],
            'default' => 'left',
            'selectors' => [
                '{{WRAPPER}} .calio-stylish-list-content' => 'text-align: {{VALUE}};',
                '{{WRAPPER}} .calio-stylish-list-badge' => 'text-align: {{VALUE}};',
            ],
        ]);
        $this->add_control('stylish_list_content_justify', [
            'label' => esc_html__('Justify Content', 'calio-addon'),
            'type' => Controls_Manager::SELECT,
            'default' => 'flex-start',
            'options' => [
                'flex-start' => esc_html__('Start', 'calio-addon'),
                'center' => esc_html__('Center', 'calio-addon'),
                'flex-end' => esc_html__('End', 'calio-addon'),
                'space-between' => esc_html__('Space Between', 'calio-addon'),
            ],
            'selectors' => [
                '{{WRAPPER}} .calio-stylish-list-content' => 'justify-content: {{VALUE}};',
            ],
        ]);
        $this->add_background_type_control('stylish_list_item_bg', '{{WRAPPER}} .calio-stylish-list-item');
        $this->add_background_type_control('stylish_list_item_bg_hover', '{{WRAPPER}} .calio-stylish-list-item:hover, {{WRAPPER}} .calio-stylish-list-item:focus-within');
        $this->add_group_control(Group_Control_Border::get_type(), [
            'name' => 'stylish_list_item_border',
            'selector' => '{{WRAPPER}} .calio-stylish-list-item',
        ]);
        $this->add_group_control(Group_Control_Box_Shadow::get_type(), [
            'name' => 'stylish_list_item_shadow',
            'selector' => '{{WRAPPER}} .calio-stylish-list-item',
        ]);
        $this->add_dimensions_control(
            'stylish_list_item_radius',
            esc_html__('Border Radius', 'calio-addon'),
            '{{WRAPPER}} .calio-stylish-list-item',
            'border-radius',
            ['size_units' => ['px', '%']]
        );
        $this->add_dimensions_control(
            'stylish_list_item_padding',
            esc_html__('Padding', 'calio-addon'),
            '{{WRAPPER}} .calio-stylish-list-item',
            'padding'
        );
        $this->add_control('stylish_list_divider_color', [
            'label' => esc_html__('Divider Color', 'calio-addon'),
            'type' => Controls_Manager::COLOR,
            'condition' => [
                'use_divider' => 'yes',
            ],
            'selectors' => [
                '{{WRAPPER}} .calio-stylish-list.has-divider.layout-vertical .calio-stylish-list-item' => 'border-bottom-color: {{VALUE}};',
                '{{WRAPPER}} .calio-stylish-list.has-divider.layout-horizontal .calio-stylish-list-item' => 'border-right-color: {{VALUE}};',
            ],
        ]);
        $this->add_control('stylish_list_divider_width', [
            'label' => esc_html__('Divider Width', 'calio-addon'),
            'type' => Controls_Manager::SLIDER,
            'size_units' => ['px'],
            'range' => [
                'px' => ['min' => 0, 'max' => 8],
            ],
            'default' => ['unit' => 'px', 'size' => 1],
            'condition' => [
                'use_divider' => 'yes',
            ],
            'selectors' => [
                '{{WRAPPER}} .calio-stylish-list' => '--calio-stylish-list-divider-width: {{SIZE}}{{UNIT}};',
            ],
        ]);

        $this->end_controls_section();
    }

    private function register_media_style_controls(): void
    {
        $this->start_controls_section('stylish_list_style_media', [
            'label' => esc_html__('Icon / Image', 'calio-addon'),
            'tab' => Controls_Manager::TAB_STYLE,
        ]);

        $this->add_control('stylish_list_media_size', [
            'label' => esc_html__('Media Box Size', 'calio-addon'),
            'type' => Controls_Manager::SLIDER,
            'size_units' => ['px'],
            'range' => [
                'px' => ['min' => 22, 'max' => 120],
            ],
            'default' => ['unit' => 'px', 'size' => 40],
            'selectors' => [
                '{{WRAPPER}} .calio-stylish-list-media' => 'width: {{SIZE}}{{UNIT}}; height: {{SIZE}}{{UNIT}};',
            ],
        ]);
        $this->add_control('stylish_list_icon_size', [
            'label' => esc_html__('Icon Size', 'calio-addon'),
            'type' => Controls_Manager::SLIDER,
            'size_units' => ['px'],
            'range' => [
                'px' => ['min' => 10, 'max' => 60],
            ],
            'default' => ['unit' => 'px', 'size' => 18],
            'selectors' => [
                '{{WRAPPER}} .calio-stylish-list-media i' => 'font-size: {{SIZE}}{{UNIT}};',
                '{{WRAPPER}} .calio-stylish-list-media svg' => 'width: {{SIZE}}{{UNIT}}; height: {{SIZE}}{{UNIT}};',
            ],
        ]);
        $this->add_text_paint_controls('stylish_list_media_icon_text', esc_html__('Icon Color', 'calio-addon'), '{{WRAPPER}} .calio-stylish-list-media');
        $this->add_background_type_control('stylish_list_media_bg', '{{WRAPPER}} .calio-stylish-list-media');
        $this->add_group_control(Group_Control_Border::get_type(), [
            'name' => 'stylish_list_media_border',
            'selector' => '{{WRAPPER}} .calio-stylish-list-media',
        ]);
        $this->add_dimensions_control(
            'stylish_list_media_radius',
            esc_html__('Border Radius', 'calio-addon'),
            '{{WRAPPER}} .calio-stylish-list-media, {{WRAPPER}} .calio-stylish-list-media img',
            'border-radius',
            ['size_units' => ['px', '%']]
        );

        $this->end_controls_section();
    }

    private function register_counter_style_controls(): void
    {
        $this->start_controls_section('stylish_list_style_counter', [
            'label' => esc_html__('Counter', 'calio-addon'),
            'tab' => Controls_Manager::TAB_STYLE,
            'condition' => ['use_counter' => 'yes'],
        ]);

        $this->add_group_control(Group_Control_Typography::get_type(), [
            'name' => 'stylish_list_counter_typography',
            'selector' => '{{WRAPPER}} .calio-stylish-list-counter',
        ]);
        $this->add_text_paint_controls('stylish_list_counter_text', esc_html__('Counter Color', 'calio-addon'), '{{WRAPPER}} .calio-stylish-list-counter');
        $this->add_background_type_control('stylish_list_counter_bg', '{{WRAPPER}} .calio-stylish-list-counter');
        $this->add_group_control(Group_Control_Border::get_type(), [
            'name' => 'stylish_list_counter_border',
            'selector' => '{{WRAPPER}} .calio-stylish-list-counter',
        ]);
        $this->add_dimensions_control(
            'stylish_list_counter_radius',
            esc_html__('Border Radius', 'calio-addon'),
            '{{WRAPPER}} .calio-stylish-list-counter',
            'border-radius',
            ['size_units' => ['px', '%']]
        );
        $this->add_dimensions_control(
            'stylish_list_counter_padding',
            esc_html__('Padding', 'calio-addon'),
            '{{WRAPPER}} .calio-stylish-list-counter',
            'padding'
        );

        $this->end_controls_section();
    }

    private function register_title_style_controls(): void
    {
        $this->start_controls_section('stylish_list_style_title', [
            'label' => esc_html__('Title', 'calio-addon'),
            'tab' => Controls_Manager::TAB_STYLE,
        ]);

        $this->add_group_control(Group_Control_Typography::get_type(), [
            'name' => 'stylish_list_title_typography',
            'selector' => '{{WRAPPER}} .calio-stylish-list-title',
        ]);
        $this->add_text_paint_controls('stylish_list_title_text', esc_html__('Title Color', 'calio-addon'), '{{WRAPPER}} .calio-stylish-list-title, {{WRAPPER}} .calio-stylish-list-title a');
        $this->add_control('stylish_list_title_spacing', [
            'label' => esc_html__('Spacing', 'calio-addon'),
            'type' => Controls_Manager::SLIDER,
            'size_units' => ['px'],
            'range' => [
                'px' => ['min' => 0, 'max' => 40],
            ],
            'default' => ['unit' => 'px', 'size' => 4],
            'selectors' => [
                '{{WRAPPER}} .calio-stylish-list-title' => 'margin-bottom: {{SIZE}}{{UNIT}};',
            ],
        ]);

        $this->end_controls_section();
    }

    private function register_description_style_controls(): void
    {
        $this->start_controls_section('stylish_list_style_description', [
            'label' => esc_html__('Description', 'calio-addon'),
            'tab' => Controls_Manager::TAB_STYLE,
        ]);

        $this->add_group_control(Group_Control_Typography::get_type(), [
            'name' => 'stylish_list_description_typography',
            'selector' => '{{WRAPPER}} .calio-stylish-list-description',
        ]);
        $this->add_text_paint_controls('stylish_list_description_text', esc_html__('Description Color', 'calio-addon'), '{{WRAPPER}} .calio-stylish-list-description');

        $this->end_controls_section();
    }

    private function register_badge_style_controls(): void
    {
        $this->start_controls_section('stylish_list_style_badge', [
            'label' => esc_html__('Badge', 'calio-addon'),
            'tab' => Controls_Manager::TAB_STYLE,
        ]);

        $this->add_group_control(Group_Control_Typography::get_type(), [
            'name' => 'stylish_list_badge_typography',
            'selector' => '{{WRAPPER}} .calio-stylish-list-badge',
        ]);
        $this->add_text_paint_controls('stylish_list_badge_text', esc_html__('Badge Text Color', 'calio-addon'), '{{WRAPPER}} .calio-stylish-list-badge');
        $this->add_background_type_control('stylish_list_badge_bg', '{{WRAPPER}} .calio-stylish-list-badge');
        $this->add_group_control(Group_Control_Border::get_type(), [
            'name' => 'stylish_list_badge_border',
            'selector' => '{{WRAPPER}} .calio-stylish-list-badge',
        ]);
        $this->add_dimensions_control(
            'stylish_list_badge_radius',
            esc_html__('Border Radius', 'calio-addon'),
            '{{WRAPPER}} .calio-stylish-list-badge',
            'border-radius',
            ['size_units' => ['px', '%']]
        );
        $this->add_dimensions_control(
            'stylish_list_badge_padding',
            esc_html__('Padding', 'calio-addon'),
            '{{WRAPPER}} .calio-stylish-list-badge',
            'padding'
        );

        $this->end_controls_section();
    }

    protected function render(): void
    {
        $settings = $this->get_settings_for_display();
        $items = $settings['items'] ?? [];

        if (!is_array($items) || $items === []) {
            return;
        }

        $use_counter = ($settings['use_counter'] ?? '') === 'yes';
        $use_entrance = ($settings['use_entrance_animation'] ?? '') === 'yes';
        $counter_style = (string) ($settings['counter_style'] ?? 'normal');
        $counter_suffix = (string) ($settings['counter_suffix'] ?? 'dot');
        $animation_duration = $this->normalize_int($settings['animation_duration'] ?? 650, 650, 100, 4000);
        $animation_stagger = $this->normalize_int($settings['animation_stagger'] ?? 120, 120, 0, 1200);

        $wrapper_classes = [
            'calio-stylish-list',
            'layout-' . sanitize_html_class((string) ($settings['list_type'] ?? 'vertical')),
            'hover-' . sanitize_html_class((string) ($settings['hover_style'] ?? 'slide')),
            'entrance-' . sanitize_html_class((string) ($settings['entrance_animation'] ?? 'fade-up')),
        ];

        if (($settings['use_divider'] ?? 'yes') === 'yes') {
            $wrapper_classes[] = 'has-divider';
        }
        if ($use_counter) {
            $wrapper_classes[] = 'has-counter';
        }
        if ($use_entrance) {
            $wrapper_classes[] = 'use-entrance-animation';
        }

        $wrapper_style = $use_entrance
            ? '--calio-stylish-list-entrance-duration:' . (string) $animation_duration . 'ms;'
            : '';

        echo '<div class="' . esc_attr(implode(' ', $wrapper_classes)) . '"'
            . ' data-use-entrance-animation="' . esc_attr($use_entrance ? 'yes' : '') . '"'
            . ' data-animation-stagger="' . esc_attr((string) $animation_stagger) . '"'
            . ($wrapper_style !== '' ? ' style="' . esc_attr($wrapper_style) . '"' : '')
            . '>';
        echo '<div class="calio-stylish-list-items">';

        foreach ($items as $index => $item) {
            if (!is_array($item)) {
                continue;
            }

            $media_html = $this->render_item_media((string) ($item['media_type'] ?? 'none'), $item);
            $has_badge = ($item['show_badge'] ?? '') === 'yes' && trim((string) ($item['badge_text'] ?? '')) !== '';
            $has_start = $use_counter || $media_html !== '';
            $item_link = $this->prepare_item_link($item['link'] ?? []);
            $item_classes = ['calio-stylish-list-item'];

            if ($has_start) {
                $item_classes[] = 'has-start';
            } else {
                $item_classes[] = 'no-start';
            }

            if ($media_html !== '') {
                $item_classes[] = 'has-media';
            }

            if ($has_badge) {
                $item_classes[] = 'has-badge';
            }

            $item_style = $this->build_item_style_vars($item);
            if (($item['add_particular_style'] ?? '') === 'yes') {
                $item_classes[] = 'has-particular-style';
            }

            if ($use_entrance) {
                $item_style[] = '--calio-stylish-item-delay:' . max(0, ((int) $index) * $animation_stagger) . 'ms';
            }

            echo '<div class="' . esc_attr(implode(' ', $item_classes)) . '"';
            if ($item_style !== []) {
                echo ' style="' . esc_attr(implode(';', $item_style)) . ';"';
            }
            echo '>';
            if ($item_link !== null) {
                $link_label = trim((string) ($item['title'] ?? ''));
                if ($link_label === '') {
                    $link_label = esc_html__('Open list item', 'calio-addon');
                }
                $link_rel = [];
                if ($item_link['nofollow']) {
                    $link_rel[] = 'nofollow';
                }
                if ($item_link['target_blank']) {
                    $link_rel[] = 'noopener';
                    $link_rel[] = 'noreferrer';
                }
                echo '<a class="calio-stylish-list-item-link" href="' . esc_url((string) $item_link['href']) . '"';
                if ($item_link['target_blank']) {
                    echo ' target="' . esc_attr('_blank') . '"';
                }
                if ($link_rel !== []) {
                    echo ' rel="' . esc_attr(implode(' ', array_unique($link_rel))) . '"';
                }
                echo ' aria-label="' . esc_attr($link_label) . '"></a>';
            }

            if ($has_start) {
                echo '<div class="calio-stylish-list-start">';
                if ($use_counter) {
                    echo '<span class="calio-stylish-list-counter">' . esc_html($this->format_counter($index + 1, $counter_style, $counter_suffix)) . '</span>';
                }
                if ($media_html !== '') {
                    echo '<span class="calio-stylish-list-media">' . wp_kses($media_html, $this->allowed_media_markup()) . '</span>';
                }
                echo '</div>';
            }

            echo '<div class="calio-stylish-list-content">';
            $title = trim((string) ($item['title'] ?? ''));
            if ($title !== '') {
                echo '<h3 class="calio-stylish-list-title">';
                if ($item_link !== null) {
                    echo esc_html($title);
                } else {
                    echo wp_kses_post($this->render_linked_title($title, $item['link'] ?? []));
                }
                echo '</h3>';
            }
            $description = trim((string) ($item['description'] ?? ''));
            if ($description !== '') {
                echo '<div class="calio-stylish-list-description">' . esc_html($description) . '</div>';
            }
            echo '</div>';

            if ($has_badge) {
                echo '<span class="calio-stylish-list-badge">' . esc_html((string) $item['badge_text']) . '</span>';
            }

            echo '</div>';
        }

        echo '</div>';
        echo '</div>';
    }

    /**
     * Returns item-level css variables for particular style mode.
     *
     * @param array<string, mixed> $item Repeater item.
     * @return array<int, string>
     */
    private function build_item_style_vars(array $item): array
    {
        $styles = [];
        if (($item['add_particular_style'] ?? '') === 'yes') {
            $map = [
                'particular_bg_color' => '--calio-stylish-item-bg',
                'particular_border_color' => '--calio-stylish-item-border',
                'particular_icon_color' => '--calio-stylish-item-icon',
                'particular_icon_bg_color' => '--calio-stylish-item-icon-bg',
            ];

            foreach ($map as $item_key => $css_var) {
                $value = $this->sanitize_css_color_value($item[$item_key] ?? '');
                if ($value !== '') {
                    $styles[] = $css_var . ':' . $value;
                }
            }
        }

        $badge_text_color = $this->sanitize_css_color_value($item['badge_text_color'] ?? '');
        if ($badge_text_color !== '') {
            $styles[] = '--calio-stylish-item-badge-text:' . $badge_text_color;
        }

        $badge_bg_color = $this->sanitize_css_color_value($item['badge_bg_color'] ?? '');
        if ($badge_bg_color !== '') {
            $styles[] = '--calio-stylish-item-badge-bg:' . $badge_bg_color;
        }

        return $styles;
    }

    /**
     * Renders icon or image media.
     *
     * @param array<string, mixed> $item Repeater item.
     */
    private function render_item_media(string $media_type, array $item): string
    {
        if ($media_type === 'image' && !empty($item['image']['url'])) {
            $url = (string) $item['image']['url'];
            $alt = get_post_meta((int) ($item['image']['id'] ?? 0), '_wp_attachment_image_alt', true);
            return '<img src="' . esc_url($url) . '" alt="' . esc_attr($alt ?: wp_basename($url)) . '">';
        }

        if ($media_type === 'icon') {
            return $this->get_icon_markup($item['icon'] ?? []);
        }

        return '';
    }

    /**
     * Normalizes URL control data into render-ready link payload.
     *
     * @param mixed $link Link control payload.
     * @return array{href: string, target_blank: bool, nofollow: bool}|null
     */
    private function prepare_item_link($link): ?array
    {
        if (!is_array($link)) {
            return null;
        }

        $href = trim((string) ($link['url'] ?? ''));
        if ($href === '') {
            return null;
        }

        return [
            'href' => $href,
            'target_blank' => !empty($link['is_external']),
            'nofollow' => !empty($link['nofollow']),
        ];
    }

    /**
     * Wraps title text with anchor when item has URL.
     *
     * @param array<string, mixed> $link Link control payload.
     */
    private function render_linked_title(string $title, array $link): string
    {
        $href = trim((string) ($link['url'] ?? ''));
        if ($href === '') {
            return esc_html($title);
        }

        $rel = [];
        if (!empty($link['nofollow'])) {
            $rel[] = 'nofollow';
        }
        if (!empty($link['is_external'])) {
            $rel[] = 'noopener';
            $rel[] = 'noreferrer';
        }

        $output = '<a class="calio-stylish-list-title-link" href="' . esc_url($href) . '"';
        if (!empty($link['is_external'])) {
            $output .= ' target="' . esc_attr('_blank') . '"';
        }
        if ($rel !== []) {
            $output .= ' rel="' . esc_attr(implode(' ', array_unique($rel))) . '"';
        }
        $output .= '>' . esc_html($title) . '</a>';

        return $output;
    }

    /**
     * @return array<string, array<string, bool>>
     */
    private function allowed_media_markup(): array
    {
        $global_attributes = [
            'aria-hidden' => true,
            'class' => true,
            'focusable' => true,
            'height' => true,
            'role' => true,
            'viewbox' => true,
            'width' => true,
            'xmlns' => true,
        ];

        return [
            'img' => [
                'alt' => true,
                'class' => true,
                'height' => true,
                'loading' => true,
                'sizes' => true,
                'src' => true,
                'srcset' => true,
                'width' => true,
            ],
            'i' => $global_attributes,
            'span' => $global_attributes,
            'svg' => $global_attributes,
            'path' => [
                'clip-rule' => true,
                'd' => true,
                'fill' => true,
                'fill-rule' => true,
            ],
            'g' => $global_attributes,
            'use' => [
                'href' => true,
                'xlink:href' => true,
            ],
        ];
    }

    /**
     * Formats list counter with style + suffix selection.
     */
    private function format_counter(int $number, string $style, string $suffix): string
    {
        $formatted = (string) $number;

        switch ($style) {
            case 'decimal-leading-zero':
                $formatted = str_pad((string) $number, 2, '0', STR_PAD_LEFT);
                break;
            case 'upper-alpha':
                $formatted = strtoupper($this->number_to_alpha($number));
                break;
            case 'lower-alpha':
                $formatted = strtolower($this->number_to_alpha($number));
                break;
            case 'upper-roman':
                $formatted = strtoupper($this->number_to_roman($number));
                break;
            case 'lower-roman':
                $formatted = strtolower($this->number_to_roman($number));
                break;
            case 'lower-greek':
                $formatted = $this->number_to_lower_greek($number);
                break;
            default:
                $formatted = (string) $number;
                break;
        }

        if ($suffix === 'dot') {
            return $formatted . '.';
        }

        if ($suffix === 'bracket') {
            return $formatted . ')';
        }

        if ($suffix === 'colon') {
            return $formatted . ':';
        }

        return $formatted;
    }

    /**
     * Converts a positive integer to alphabetic sequence.
     */
    private function number_to_alpha(int $number): string
    {
        $number = max(1, $number);
        $result = '';

        while ($number > 0) {
            $number--;
            $result = chr(65 + ($number % 26)) . $result;
            $number = (int) floor($number / 26);
        }

        return $result;
    }

    /**
     * Converts a positive integer to roman numeral.
     */
    private function number_to_roman(int $number): string
    {
        $number = max(1, $number);
        $map = [
            'M' => 1000,
            'CM' => 900,
            'D' => 500,
            'CD' => 400,
            'C' => 100,
            'XC' => 90,
            'L' => 50,
            'XL' => 40,
            'X' => 10,
            'IX' => 9,
            'V' => 5,
            'IV' => 4,
            'I' => 1,
        ];

        $result = '';
        foreach ($map as $roman => $value) {
            while ($number >= $value) {
                $result .= $roman;
                $number -= $value;
            }
        }

        return $result;
    }

    /**
     * Converts integer to lower greek sequence.
     */
    private function number_to_lower_greek(int $number): string
    {
        $letters = ['a', 'b', 'g', 'd', 'e', 'z', 'h', 'th', 'i', 'k', 'l', 'm', 'n', 'x', 'o', 'p', 'r', 's', 't', 'y', 'ph', 'ch', 'ps', 'w'];
        $base = count($letters);
        $number = max(1, $number);
        $result = '';

        while ($number > 0) {
            $number--;
            $result = $letters[$number % $base] . $result;
            $number = (int) floor($number / $base);
        }

        return $result;
    }

    /**
     * Normalizes integer control values.
     *
     * @param mixed $value Raw value.
     */
    private function normalize_int($value, int $fallback, int $min, int $max): int
    {
        $number = is_numeric($value) ? (int) $value : $fallback;
        return max($min, min($max, $number));
    }

    /**
     * Normalizes color controls before they are written into CSS custom properties.
     *
     * @param mixed $value Raw color value.
     */
    private function sanitize_css_color_value($value): string
    {
        $value = trim((string) $value);
        if ($value === '') {
            return '';
        }

        $hex = sanitize_hex_color($value);
        if ($hex) {
            return $hex;
        }

        $lower = strtolower($value);
        if (in_array($lower, ['transparent', 'currentcolor', 'inherit', 'initial'], true)) {
            return $lower;
        }

        if (preg_match('/^rgba?\(\s*(\d{1,3}%?\s*,\s*){2}\d{1,3}%?(\s*,\s*(0|1|0?\.\d+))?\s*\)$/i', $value)) {
            return $value;
        }

        if (preg_match('/^hsla?\(\s*\d{1,3}(deg|rad|turn)?\s*,\s*\d{1,3}%\s*,\s*\d{1,3}%(\s*,\s*(0|1|0?\.\d+))?\s*\)$/i', $value)) {
            return $value;
        }

        return '';
    }
}
