<?php

namespace Calio\Widgets;

use Elementor\Controls_Manager;
use Elementor\Group_Control_Typography;

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

/**
 * Renders a lightweight breadcrumb trail for pages, posts and archive views.
 */
class BreadcrumbsWidget extends BaseWidget
{
    public function get_name(): string
    {
        return 'calio-breadcrumbs';
    }

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

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

    public function get_style_depends(): array
    {
        if ($this->is_calio_edit_or_preview_mode()) {
            return ['calio-styles', 'calio-widget-breadcrumbs'];
        }

        return ['calio-widget-breadcrumbs'];
    }

    public function get_script_depends(): array
    {
        return [];
    }

    public function get_keywords(): array
    {
        return array_merge(parent::get_keywords(), ['breadcrumbs', 'breadcrumb', 'navigation', 'hierarchy']);
    }

    protected function register_controls(): void
    {
        $this->start_controls_section(
            'section_content',
            [
                'label' => esc_html__('Breadcrumbs', 'calio-addon'),
            ]
        );

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

        $this->add_control(
            'home_label',
            [
                'label' => esc_html__('Home Label', 'calio-addon'),
                'type' => Controls_Manager::TEXT,
                'default' => esc_html__('Home', 'calio-addon'),
                'condition' => [
                    'show_home' => 'yes',
                ],
            ]
        );

        $this->add_control(
            'separator',
            [
                'label' => esc_html__('Separator', 'calio-addon'),
                'type' => Controls_Manager::TEXT,
                'default' => '/',
                'placeholder' => '/',
            ]
        );

        $this->add_responsive_control(
            'alignment',
            [
                'label' => esc_html__('Alignment', 'calio-addon'),
                'type' => Controls_Manager::CHOOSE,
                'options' => [
                    'flex-start' => [
                        'title' => esc_html__('Left', 'calio-addon'),
                        'icon' => 'eicon-text-align-left',
                    ],
                    'center' => [
                        'title' => esc_html__('Center', 'calio-addon'),
                        'icon' => 'eicon-text-align-center',
                    ],
                    'flex-end' => [
                        'title' => esc_html__('Right', 'calio-addon'),
                        'icon' => 'eicon-text-align-right',
                    ],
                ],
                'default' => 'flex-start',
                'selectors' => [
                    '{{WRAPPER}} .calio-breadcrumbs__list' => 'justify-content: {{VALUE}};',
                ],
            ]
        );

        $this->end_controls_section();

        $this->start_controls_section(
            'section_style',
            [
                'label' => esc_html__('Style', 'calio-addon'),
                'tab' => Controls_Manager::TAB_STYLE,
            ]
        );

        $this->add_control(
            'link_color',
            [
                'label' => esc_html__('Link Color', 'calio-addon'),
                'type' => Controls_Manager::COLOR,
                'selectors' => [
                    '{{WRAPPER}} .calio-breadcrumbs__link' => 'color: {{VALUE}};',
                ],
            ]
        );

        $this->add_control(
            'link_hover_color',
            [
                'label' => esc_html__('Link Hover Color', 'calio-addon'),
                'type' => Controls_Manager::COLOR,
                'selectors' => [
                    '{{WRAPPER}} .calio-breadcrumbs__link:hover, {{WRAPPER}} .calio-breadcrumbs__link:focus' => 'color: {{VALUE}};',
                ],
            ]
        );

        $this->add_control(
            'current_color',
            [
                'label' => esc_html__('Current Color', 'calio-addon'),
                'type' => Controls_Manager::COLOR,
                'selectors' => [
                    '{{WRAPPER}} .calio-breadcrumbs__current' => 'color: {{VALUE}};',
                ],
            ]
        );

        $this->add_control(
            'separator_color',
            [
                'label' => esc_html__('Separator Color', 'calio-addon'),
                'type' => Controls_Manager::COLOR,
                'selectors' => [
                    '{{WRAPPER}} .calio-breadcrumbs__separator' => 'color: {{VALUE}};',
                ],
            ]
        );

        $this->add_group_control(
            Group_Control_Typography::get_type(),
            [
                'name' => 'typography',
                'selector' => '{{WRAPPER}} .calio-breadcrumbs__link, {{WRAPPER}} .calio-breadcrumbs__current, {{WRAPPER}} .calio-breadcrumbs__separator',
            ]
        );

        $this->add_responsive_control(
            'item_spacing',
            [
                'label' => esc_html__('Spacing', 'calio-addon'),
                'type' => Controls_Manager::SLIDER,
                'size_units' => ['px', 'em', 'rem'],
                'range' => [
                    'px' => [
                        'min' => 0,
                        'max' => 48,
                    ],
                    'em' => [
                        'min' => 0,
                        'max' => 4,
                        'step' => 0.1,
                    ],
                    'rem' => [
                        'min' => 0,
                        'max' => 4,
                        'step' => 0.1,
                    ],
                ],
                'default' => [
                    'size' => 8,
                    'unit' => 'px',
                ],
                'selectors' => [
                    '{{WRAPPER}} .calio-breadcrumbs__list' => 'gap: {{SIZE}}{{UNIT}};',
                ],
            ]
        );

        $this->end_controls_section();
    }

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

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

        $separator = isset($settings['separator']) ? sanitize_text_field((string) $settings['separator']) : '/';

        echo '<nav class="calio-breadcrumbs" aria-label="' . esc_attr__('Breadcrumbs', 'calio-addon') . '">';
        echo '<ol class="calio-breadcrumbs__list">';

        $last_index = count($items) - 1;
        foreach ($items as $index => $item) {
            $label = isset($item['label']) ? (string) $item['label'] : '';
            $url = isset($item['url']) ? (string) $item['url'] : '';
            $is_current = $index === $last_index || $url === '';

            if ($label === '') {
                continue;
            }

            echo '<li class="calio-breadcrumbs__item">';
            if ($is_current) {
                echo '<span class="calio-breadcrumbs__current" aria-current="page">' . esc_html($label) . '</span>';
            } else {
                echo '<a class="calio-breadcrumbs__link" href="' . esc_url($url) . '">' . esc_html($label) . '</a>';
            }
            echo '</li>';

            if ($index < $last_index && $separator !== '') {
                echo '<li class="calio-breadcrumbs__separator" aria-hidden="true">' . esc_html($separator) . '</li>';
            }
        }

        echo '</ol>';
        echo '</nav>';
    }

    /**
     * @param array<string, mixed> $settings
     * @return array<int, array{label: string, url: string}>
     */
    private function build_breadcrumb_items(array $settings): array
    {
        $items = [];

        if (($settings['show_home'] ?? 'yes') === 'yes') {
            $items[] = [
                'label' => $this->home_label($settings),
                'url' => is_front_page() ? '' : home_url('/'),
            ];
        }

        if (is_front_page()) {
            return $items;
        }

        if (is_page()) {
            $this->add_page_ancestors($items, (int) get_queried_object_id());
            $items[] = [
                'label' => single_post_title('', false),
                'url' => '',
            ];
            return $this->dedupe_items($items);
        }

        if (is_singular()) {
            $this->add_singular_context($items);
            $items[] = [
                'label' => single_post_title('', false),
                'url' => '',
            ];
            return $this->dedupe_items($items);
        }

        if (is_category() || is_tag() || is_tax()) {
            $this->add_term_archive_context($items);
            return $this->dedupe_items($items);
        }

        if (is_post_type_archive()) {
            $items[] = [
                'label' => post_type_archive_title('', false),
                'url' => '',
            ];
            return $this->dedupe_items($items);
        }

        if (is_author()) {
            $author = get_queried_object();
            $items[] = [
                'label' => $author instanceof \WP_User ? $author->display_name : get_the_archive_title(),
                'url' => '',
            ];
            return $this->dedupe_items($items);
        }

        if (is_date()) {
            $items[] = [
                'label' => get_the_archive_title(),
                'url' => '',
            ];
            return $this->dedupe_items($items);
        }

        if (is_search()) {
            $items[] = [
                /* translators: %s: search query. */
                'label' => sprintf(__('Search results for "%s"', 'calio-addon'), get_search_query()),
                'url' => '',
            ];
            return $this->dedupe_items($items);
        }

        if (is_404()) {
            $items[] = [
                'label' => __('Page not found', 'calio-addon'),
                'url' => '',
            ];
            return $this->dedupe_items($items);
        }

        $archive_title = get_the_archive_title();
        if ($archive_title !== '') {
            $items[] = [
                'label' => $archive_title,
                'url' => '',
            ];
        }

        return $this->dedupe_items($items);
    }

    /**
     * @param array<string, mixed> $settings
     */
    private function home_label(array $settings): string
    {
        $label = isset($settings['home_label']) ? sanitize_text_field((string) $settings['home_label']) : '';

        return $label !== '' ? $label : __('Home', 'calio-addon');
    }

    /**
     * @param array<int, array{label: string, url: string}> $items
     */
    private function add_singular_context(array &$items): void
    {
        $post_id = (int) get_queried_object_id();
        $post_type = get_post_type($post_id);
        if (!is_string($post_type) || $post_type === '') {
            return;
        }

        if ($post_type === 'post') {
            $this->add_posts_page($items);
            $this->add_primary_category($items, $post_id);
            return;
        }

        $post_type_object = get_post_type_object($post_type);
        if ($post_type_object && $post_type_object->has_archive) {
            $archive_url = get_post_type_archive_link($post_type);
            if (is_string($archive_url) && $archive_url !== '') {
                $items[] = [
                    'label' => $post_type_object->labels->name,
                    'url' => $archive_url,
                ];
            }
        }

        $this->add_page_ancestors($items, $post_id);
    }

    /**
     * @param array<int, array{label: string, url: string}> $items
     */
    private function add_posts_page(array &$items): void
    {
        $posts_page_id = (int) get_option('page_for_posts');
        if ($posts_page_id <= 0 || !get_post($posts_page_id)) {
            return;
        }

        $items[] = [
            'label' => get_the_title($posts_page_id),
            'url' => get_permalink($posts_page_id),
        ];
    }

    /**
     * @param array<int, array{label: string, url: string}> $items
     */
    private function add_primary_category(array &$items, int $post_id): void
    {
        $categories = get_the_category($post_id);
        if (!is_array($categories) || $categories === []) {
            return;
        }

        $category = $categories[0];
        if (!$category instanceof \WP_Term) {
            return;
        }

        $this->add_term_ancestors($items, $category);
        $term_link = get_term_link($category);
        if (!is_wp_error($term_link)) {
            $items[] = [
                'label' => $category->name,
                'url' => (string) $term_link,
            ];
        }
    }

    /**
     * @param array<int, array{label: string, url: string}> $items
     */
    private function add_page_ancestors(array &$items, int $post_id): void
    {
        $ancestors = array_reverse(get_post_ancestors($post_id));
        foreach ($ancestors as $ancestor_id) {
            $ancestor_id = (int) $ancestor_id;
            if ($ancestor_id <= 0) {
                continue;
            }

            $items[] = [
                'label' => get_the_title($ancestor_id),
                'url' => get_permalink($ancestor_id),
            ];
        }
    }

    /**
     * @param array<int, array{label: string, url: string}> $items
     */
    private function add_term_archive_context(array &$items): void
    {
        $term = get_queried_object();
        if (!$term instanceof \WP_Term) {
            $items[] = [
                'label' => get_the_archive_title(),
                'url' => '',
            ];
            return;
        }

        $this->add_term_ancestors($items, $term);
        $items[] = [
            'label' => $term->name,
            'url' => '',
        ];
    }

    /**
     * @param array<int, array{label: string, url: string}> $items
     */
    private function add_term_ancestors(array &$items, \WP_Term $term): void
    {
        if ($term->parent <= 0) {
            return;
        }

        $ancestors = array_reverse(get_ancestors($term->term_id, $term->taxonomy, 'taxonomy'));
        foreach ($ancestors as $ancestor_id) {
            $ancestor = get_term((int) $ancestor_id, $term->taxonomy);
            if (!$ancestor instanceof \WP_Term) {
                continue;
            }

            $term_link = get_term_link($ancestor);
            if (is_wp_error($term_link)) {
                continue;
            }

            $items[] = [
                'label' => $ancestor->name,
                'url' => (string) $term_link,
            ];
        }
    }

    /**
     * @param array<int, array{label: string, url: string}> $items
     * @return array<int, array{label: string, url: string}>
     */
    private function dedupe_items(array $items): array
    {
        $deduped = [];
        $seen = [];

        foreach ($items as $item) {
            $label = trim((string) ($item['label'] ?? ''));
            $url = (string) ($item['url'] ?? '');
            if ($label === '') {
                continue;
            }

            $key = $label . '|' . $url;
            if (isset($seen[$key])) {
                continue;
            }

            $seen[$key] = true;
            $deduped[] = [
                'label' => $label,
                'url' => $url,
            ];
        }

        return $deduped;
    }
}
