<?php

namespace Calio\Core;

use Calio\Widgets\PostTimelineHelper;
use Calio\Widgets\PostTimelineWidget;

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

/**
 * Handles Ajax pagination for the Post Timeline widget.
 */
class PostTimelineAjaxManager
{
    private const AJAX_ACTION_LOAD_MORE = 'calio_post_timeline_load_more';
    private const AJAX_NONCE_FIELD = '_ajax_nonce';

    public function __construct()
    {
        add_action('wp_ajax_' . self::AJAX_ACTION_LOAD_MORE, [$this, 'ajax_load_more']);
        add_action('wp_ajax_nopriv_' . self::AJAX_ACTION_LOAD_MORE, [$this, 'ajax_load_more']);
    }

    public function ajax_load_more(): void
    {
        if (check_ajax_referer(self::AJAX_ACTION_LOAD_MORE, self::AJAX_NONCE_FIELD, false) === false) {
            wp_send_json_error(['message' => esc_html__('Security token did not match.', 'calio-addon')], 403);
        }

        $pageId = isset($_POST['page_id']) ? absint(wp_unslash($_POST['page_id'])) : 0;
        $widgetId = isset($_POST['widget_id']) ? sanitize_key((string) wp_unslash($_POST['widget_id'])) : '';
        $page = isset($_POST['page']) ? max(1, absint(wp_unslash($_POST['page']))) : 1;

        if ($pageId < 1 || $widgetId === '') {
            wp_send_json_error(['message' => esc_html__('Page ID or widget ID is missing.', 'calio-addon')], 400);
        }

        $widget = $this->resolve_widget_instance($pageId, $widgetId);
        if (!$widget instanceof PostTimelineWidget) {
            wp_send_json_error(['message' => esc_html__('Timeline widget settings could not be resolved.', 'calio-addon')], 404);
        }

        $settings = PostTimelineHelper::fix_old_query($widget->get_settings_for_display());
        $settings['expanison_indicator'] = $settings['excerpt_expanison_indicator'] ?? '...';

        if (($settings['post_type'] ?? '') === 'source_dynamic') {
            wp_send_json_error(['message' => esc_html__('Dynamic source uses reveal mode instead of Ajax pagination.', 'calio-addon')], 400);
        }

        $args = PostTimelineHelper::get_query_args($settings);
        $args = PostTimelineHelper::get_dynamic_args($settings, $args);

        $postsPerPage = max(1, (int) ($settings['posts_per_page'] ?? 4));
        $baseOffset = max(0, (int) ($args['offset'] ?? 0));

        $args['posts_per_page'] = $postsPerPage;
        $args['offset'] = $baseOffset + (($page - 1) * $postsPerPage);

        $template = PostTimelineWidget::get_template_file((string) ($settings['eael_dynamic_template_Layout'] ?? 'default'));
        if ($template === null) {
            wp_send_json_error(['message' => esc_html__('Timeline template could not be loaded.', 'calio-addon')], 500);
        }

        $query = new \WP_Query($args);
        $html = $query->have_posts()
            ? PostTimelineWidget::render_items_html($query, $settings, $template)
            : '';

        $maxPage = max(1, (int) $query->max_num_pages);

        wp_reset_postdata();

        wp_send_json_success([
            'html' => $html,
            'page' => $page,
            'max_page' => $maxPage,
            'has_more' => $page < $maxPage,
        ]);
    }

    private function resolve_widget_instance(int $pageId, string $widgetId): ?PostTimelineWidget
    {
        if (!class_exists('\Elementor\Plugin')) {
            return null;
        }

        $elementData = $this->find_widget_element($this->get_document_elements($pageId), $widgetId);
        if ($elementData === null) {
            return null;
        }

        $element = \Elementor\Plugin::$instance->elements_manager->create_element_instance($elementData);

        return $element instanceof PostTimelineWidget ? $element : null;
    }

    /**
     * @return array<int, array<string, mixed>>
     */
    private function get_document_elements(int $pageId): array
    {
        $data = get_post_meta($pageId, '_elementor_data', true);

        if (is_string($data) && $data !== '') {
            $decoded = json_decode($data, true);
            if (is_array($decoded)) {
                return $decoded;
            }
        }

        if (is_array($data)) {
            return $data;
        }

        $document = \Elementor\Plugin::$instance->documents->get($pageId);
        if ($document && method_exists($document, 'get_elements_data')) {
            $elements = $document->get_elements_data();
            if (is_array($elements)) {
                return $elements;
            }
        }

        return [];
    }

    /**
     * @param array<int, array<string, mixed>> $elements
     * @return array<string, mixed>|null
     */
    private function find_widget_element(array $elements, string $widgetId): ?array
    {
        foreach ($elements as $element) {
            if (!is_array($element)) {
                continue;
            }

            if (
                ($element['id'] ?? '') === $widgetId
                && ($element['elType'] ?? '') === 'widget'
                && ($element['widgetType'] ?? '') === 'calio-post-timeline'
            ) {
                return $element;
            }

            $children = $element['elements'] ?? [];
            if (is_array($children)) {
                $match = $this->find_widget_element($children, $widgetId);
                if ($match !== null) {
                    return $match;
                }
            }
        }

        return null;
    }
}
