<?php

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

class SEO_Fury_LLMS_Txt {

    public function __construct() {
        $this->init_hooks();
    }

    private function init_hooks() {
        add_action('init', array($this, 'register_rewrite_rules'));
        add_action('init', array($this, 'maybe_intercept_llms_txt'), 0);
        add_action('wp_ajax_seo_fury_regenerate_llms_txt', array($this, 'ajax_regenerate_llms_txt'));
    }

    /**
     * Register rewrite rules for llms.txt and llms-full.txt.
     */
    public function register_rewrite_rules() {
        add_rewrite_rule('^llms\.txt$', 'index.php?seo_fury_llms_txt=1', 'top');
        add_rewrite_rule('^llms-full\.txt$', 'index.php?seo_fury_llms_full_txt=1', 'top');
        add_filter('query_vars', array($this, 'add_query_vars'));
    }

    /**
     * Register query vars for rewrite rules.
     *
     * @param array $vars Existing query vars.
     * @return array
     */
    public function add_query_vars($vars) {
        $vars[] = 'seo_fury_llms_txt';
        $vars[] = 'seo_fury_llms_full_txt';
        return $vars;
    }

    /**
     * Intercept /llms.txt and /llms-full.txt requests early via init + REQUEST_URI.
     *
     * This ensures our virtual llms.txt is always served even if rewrite rules
     * have not been flushed yet (same approach as the robots.txt module).
     */
    public function maybe_intercept_llms_txt() {
        if (is_admin()) {
            return;
        }

        $enabled = get_option('seo_fury_llms_txt_enabled', 0);
        if (!$enabled) {
            return;
        }

        $request_uri = isset($_SERVER['REQUEST_URI']) ? sanitize_text_field(wp_unslash($_SERVER['REQUEST_URI'])) : '';
        $request_path = strtok($request_uri, '?');

        if ('/llms.txt' === $request_path) {
            $this->serve_llms_txt(false);
        } elseif ('/llms-full.txt' === $request_path) {
            $this->serve_llms_txt(true);
        }
    }

    /**
     * Output llms.txt or llms-full.txt content and exit.
     *
     * @param bool $full Whether to serve the full version (llms-full.txt).
     */
    private function serve_llms_txt($full = false) {
        $content = $this->get_llms_txt_output($full);

        header('Content-Type: text/plain; charset=UTF-8');
        header('X-Robots-Source: seo-fury-llms-txt');
        status_header(200);
        echo $content; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- plain-text llms.txt content
        exit;
    }

    /**
     * Build the llms.txt output.
     *
     * If auto-generate is enabled or no manual content exists, generate from site structure.
     * Otherwise, use the manually edited content from the option.
     *
     * @param bool $full Whether to build the full version (up to 100 items).
     * @return string
     */
    private function get_llms_txt_output($full = false) {
        $auto_generate = get_option('seo_fury_llms_txt_auto_generate', 0);
        $content = get_option('seo_fury_llms_txt_content', '');

        if ($auto_generate || empty($content)) {
            return $this->generate_llms_txt_content($full);
        }

        // For manual content, return as-is for llms.txt.
        // For llms-full.txt, append additional posts if auto-generate is off.
        if ($full) {
            $extra = $this->generate_additional_posts_section(100);
            if (!empty($extra)) {
                $content .= "\n\n" . $extra;
            }
        }

        return trim($content) . "\n";
    }

    /**
     * Auto-generate llms.txt content from site structure.
     *
     * @param bool $full Whether to generate the full version.
     * @return string
     */
    /**
     * Escape text used as a Markdown link label / heading: collapse whitespace
     * to single spaces and backslash-escape the bracket characters so a title
     * like "Foo](http://evil)" can't hijack or break the generated link.
     */
    private function md_text($s) {
        $s = preg_replace('/\s+/u', ' ', (string) $s);
        $s = str_replace(array('[', ']'), array('\[', '\]'), $s);
        return trim($s);
    }

    /**
     * Make a URL safe inside Markdown ( ) parentheses.
     */
    private function md_url($url) {
        return str_replace(array(' ', '(', ')'), array('%20', '%28', '%29'), (string) $url);
    }

    public function generate_llms_txt_content($full = false) {
        $site_title = get_option('seo_fury_llms_txt_title', '');
        if (empty($site_title)) {
            $site_title = get_bloginfo('name');
        }

        $site_description = get_option('seo_fury_llms_txt_description', '');
        if (empty($site_description)) {
            $site_description = get_bloginfo('description');
        }

        $limit = $full ? 100 : 20;
        $include_post_types = get_option('seo_fury_llms_txt_include_post_types', array('post', 'page'));
        if (!is_array($include_post_types) || empty($include_post_types)) {
            $include_post_types = array('post', 'page');
        }

        $output = '# ' . $this->md_text($site_title) . "\n";
        if (!empty($site_description)) {
            $output .= '> ' . $this->md_text($site_description) . "\n";
        }
        $output .= "\n";

        // Main Pages (pages only)
        if (in_array('page', $include_post_types, true)) {
            $pages = $this->get_main_pages();
            if (!empty($pages)) {
                $output .= "## Main Pages\n";
                foreach ($pages as $page) {
                    $output .= '- [' . $this->md_text($page['title']) . '](' . $this->md_url($page['url']) . ')' . "\n";
                }
                $output .= "\n";
            }
        }

        // Content sections per post type (excluding 'page' which is handled above)
        $content_post_types = array_diff($include_post_types, array('page'));

        foreach ($content_post_types as $post_type) {
            $post_type_obj = get_post_type_object($post_type);
            if (!$post_type_obj) {
                continue;
            }

            $section_title = $post_type_obj->labels->name;
            $posts = $this->get_posts_for_type($post_type, $limit, $full);

            if (!empty($posts)) {
                $output .= '## ' . $section_title . "\n";
                foreach ($posts as $post_data) {
                    $line = '- [' . $this->md_text($post_data['title']) . '](' . $this->md_url($post_data['url']) . ')';
                    if (!empty($post_data['description'])) {
                        $line .= ': ' . $this->md_text($post_data['description']);
                    }
                    $output .= $line . "\n";
                }
                $output .= "\n";
            }
        }

        return trim($output) . "\n";
    }

    /**
     * Get main pages (front page, about, contact, etc.).
     *
     * @return array
     */
    private function get_main_pages() {
        $pages = array();

        // Always include home
        $pages[] = array(
            'title' => __('Home', 'seo-fury'),
            'url'   => home_url('/'),
        );

        // Get published pages, ordered by menu_order then title
        $wp_pages = get_pages(array(
            'sort_column'  => 'menu_order,post_title',
            'sort_order'   => 'ASC',
            'post_status'  => 'publish',
            'number'       => 20,
            'hierarchical' => false,
        ));

        if ($wp_pages) {
            // Get the front page ID to exclude it (already added as Home)
            $front_page_id = (int) get_option('page_on_front', 0);

            foreach ($wp_pages as $page) {
                if ($page->ID === $front_page_id) {
                    continue;
                }
                $pages[] = array(
                    'title' => get_the_title($page->ID),
                    'url'   => get_permalink($page->ID),
                );
            }
        }

        return $pages;
    }

    /**
     * Get posts for a given post type.
     *
     * @param string $post_type The post type slug.
     * @param int    $limit     Maximum number of posts.
     * @param bool   $full      Whether this is the full version (longer descriptions).
     * @return array
     */
    private function get_posts_for_type($post_type, $limit = 20, $full = false) {
        $posts = array();

        $query_args = array(
            'post_type'      => $post_type,
            'post_status'    => 'publish',
            'posts_per_page' => $limit,
            'orderby'        => 'date',
            'order'          => 'DESC',
            'no_found_rows'  => true,
        );

        $query = new WP_Query($query_args);

        if ($query->have_posts()) {
            while ($query->have_posts()) {
                $query->the_post();

                $description = '';
                if ($full) {
                    // Full version: longer excerpt (up to 200 chars)
                    $excerpt = get_the_excerpt();
                    if (empty($excerpt)) {
                        $excerpt = wp_trim_words(get_the_content(), 30, '...');
                    }
                    $description = wp_strip_all_tags($excerpt);
                    if (mb_strlen($description) > 200) {
                        $description = mb_substr($description, 0, 197) . '...';
                    }
                } else {
                    // Standard version: short excerpt (up to 100 chars)
                    $excerpt = get_the_excerpt();
                    if (empty($excerpt)) {
                        $excerpt = wp_trim_words(get_the_content(), 15, '...');
                    }
                    $description = wp_strip_all_tags($excerpt);
                    if (mb_strlen($description) > 100) {
                        $description = mb_substr($description, 0, 97) . '...';
                    }
                }

                $posts[] = array(
                    'title'       => get_the_title(),
                    'url'         => get_permalink(),
                    'description' => $description,
                );
            }
            wp_reset_postdata();
        }

        return $posts;
    }

    /**
     * Generate additional posts section for llms-full.txt when manual content is used.
     *
     * @param int $limit Maximum number of posts.
     * @return string
     */
    private function generate_additional_posts_section($limit) {
        $include_post_types = get_option('seo_fury_llms_txt_include_post_types', array('post', 'page'));
        if (!is_array($include_post_types) || empty($include_post_types)) {
            $include_post_types = array('post', 'page');
        }

        $content_post_types = array_diff($include_post_types, array('page'));
        $output = '';

        foreach ($content_post_types as $post_type) {
            $post_type_obj = get_post_type_object($post_type);
            if (!$post_type_obj) {
                continue;
            }

            $posts = $this->get_posts_for_type($post_type, $limit, true);
            if (!empty($posts)) {
                $output .= '## ' . $post_type_obj->labels->name . " (Extended)\n";
                foreach ($posts as $post_data) {
                    $line = '- [' . $this->md_text($post_data['title']) . '](' . $this->md_url($post_data['url']) . ')';
                    if (!empty($post_data['description'])) {
                        $line .= ': ' . $this->md_text($post_data['description']);
                    }
                    $output .= $line . "\n";
                }
                $output .= "\n";
            }
        }

        return trim($output);
    }

    /**
     * Register settings for the llms.txt admin tab.
     */
    public function register_settings() {
        $sanitize_checkbox = array('sanitize_callback' => 'absint');
        $sanitize_textarea = array('sanitize_callback' => 'sanitize_textarea_field');
        $sanitize_text     = array('sanitize_callback' => 'sanitize_text_field');

        register_setting('seo_fury_llms_txt_group', 'seo_fury_llms_txt_enabled', $sanitize_checkbox);
        register_setting('seo_fury_llms_txt_group', 'seo_fury_llms_txt_content', $sanitize_textarea);
        register_setting('seo_fury_llms_txt_group', 'seo_fury_llms_txt_auto_generate', $sanitize_checkbox);
        register_setting('seo_fury_llms_txt_group', 'seo_fury_llms_txt_title', $sanitize_text);
        register_setting('seo_fury_llms_txt_group', 'seo_fury_llms_txt_description', $sanitize_textarea);
        register_setting('seo_fury_llms_txt_group', 'seo_fury_llms_txt_include_post_types', array(
            'sanitize_callback' => array($this, 'sanitize_post_types'),
        ));

        add_settings_section(
            'seo_fury_llms_txt_section',
            __('llms.txt Settings', 'seo-fury'),
            array($this, 'llms_txt_section_callback'),
            'seo_fury_llms_txt_group'
        );

        add_settings_field('seo_fury_llms_txt_enabled', __('Enable virtual llms.txt', 'seo-fury'), array($this, 'llms_txt_enabled_callback'), 'seo_fury_llms_txt_group', 'seo_fury_llms_txt_section');
        add_settings_field('seo_fury_llms_txt_title', __('Site Title Override', 'seo-fury'), array($this, 'llms_txt_title_callback'), 'seo_fury_llms_txt_group', 'seo_fury_llms_txt_section');
        add_settings_field('seo_fury_llms_txt_description', __('Site Description', 'seo-fury'), array($this, 'llms_txt_description_callback'), 'seo_fury_llms_txt_group', 'seo_fury_llms_txt_section');
        add_settings_field('seo_fury_llms_txt_auto_generate', __('Auto-generate from site', 'seo-fury'), array($this, 'llms_txt_auto_generate_callback'), 'seo_fury_llms_txt_group', 'seo_fury_llms_txt_section');
        add_settings_field('seo_fury_llms_txt_include_post_types', __('Include Post Types', 'seo-fury'), array($this, 'llms_txt_include_post_types_callback'), 'seo_fury_llms_txt_group', 'seo_fury_llms_txt_section');
        add_settings_field('seo_fury_llms_txt_content', __('llms.txt Content', 'seo-fury'), array($this, 'llms_txt_content_callback'), 'seo_fury_llms_txt_group', 'seo_fury_llms_txt_section');
        add_settings_field('seo_fury_llms_txt_regenerate', __('Regenerate Content', 'seo-fury'), array($this, 'llms_txt_regenerate_callback'), 'seo_fury_llms_txt_group', 'seo_fury_llms_txt_section');
        add_settings_field('seo_fury_llms_txt_link', __('Current llms.txt', 'seo-fury'), array($this, 'llms_txt_link_callback'), 'seo_fury_llms_txt_group', 'seo_fury_llms_txt_section');
    }

    /**
     * Sanitize post types array.
     *
     * @param mixed $input Raw input.
     * @return array
     */
    public function sanitize_post_types($input) {
        if (!is_array($input)) {
            return array('post', 'page');
        }
        return array_map('sanitize_text_field', $input);
    }

    /**
     * Section description callback.
     */
    public function llms_txt_section_callback() {
        ?>
        <?php
    }

    /**
     * Enable/disable checkbox callback.
     */
    public function llms_txt_enabled_callback() {
        $enabled = get_option('seo_fury_llms_txt_enabled', 0);
        ?>
        <label>
            <input type="checkbox" name="seo_fury_llms_txt_enabled" value="1" <?php checked($enabled, 1); ?> />
            <?php esc_html_e('Enable virtual llms.txt and llms-full.txt', 'seo-fury'); ?>
        </label>
        <p class="description">
            <?php esc_html_e('When enabled, the plugin will serve virtual llms.txt and llms-full.txt files at your site root.', 'seo-fury'); ?>
        </p>
        <?php
    }

    /**
     * Site title override callback.
     */
    public function llms_txt_title_callback() {
        $title = get_option('seo_fury_llms_txt_title', '');
        ?>
        <input type="text" name="seo_fury_llms_txt_title" value="<?php echo esc_attr($title); ?>" class="regular-text" placeholder="<?php echo esc_attr(get_bloginfo('name')); ?>" />
        <p class="description">
            <?php esc_html_e('Override the site title used in llms.txt. Leave empty to use the default WordPress site title.', 'seo-fury'); ?>
        </p>
        <?php
    }

    /**
     * Site description callback.
     */
    public function llms_txt_description_callback() {
        $description = get_option('seo_fury_llms_txt_description', '');
        ?>
        <textarea name="seo_fury_llms_txt_description" rows="3" cols="80" class="large-text" placeholder="<?php echo esc_attr(get_bloginfo('description')); ?>"><?php echo esc_textarea($description); ?></textarea>
        <p class="description">
            <?php esc_html_e('A brief description of your site for AI crawlers. Leave empty to use the default WordPress tagline.', 'seo-fury'); ?>
        </p>
        <?php
    }

    /**
     * Auto-generate checkbox callback.
     */
    public function llms_txt_auto_generate_callback() {
        $auto_generate = get_option('seo_fury_llms_txt_auto_generate', 0);
        ?>
        <label>
            <input type="checkbox" name="seo_fury_llms_txt_auto_generate" value="1" <?php checked($auto_generate, 1); ?> />
            <?php esc_html_e('Automatically generate llms.txt content from site structure', 'seo-fury'); ?>
        </label>
        <p class="description">
            <?php esc_html_e('When enabled, the llms.txt content will be dynamically generated from your published pages and posts. Manual edits to the content below will be ignored.', 'seo-fury'); ?>
        </p>
        <?php
    }

    /**
     * Include post types checkboxes callback.
     */
    public function llms_txt_include_post_types_callback() {
        $selected = get_option('seo_fury_llms_txt_include_post_types', array('post', 'page'));
        if (!is_array($selected)) {
            $selected = array('post', 'page');
        }

        $post_types = get_post_types(array('public' => true), 'objects');

        foreach ($post_types as $pt) {
            if ($pt->name === 'attachment') {
                continue;
            }
            ?>
            <label style="display: block; margin-bottom: 5px;">
                <input type="checkbox" name="seo_fury_llms_txt_include_post_types[]" value="<?php echo esc_attr($pt->name); ?>" <?php checked(in_array($pt->name, $selected, true)); ?> />
                <?php echo esc_html($pt->labels->name); ?> <code>(<?php echo esc_html($pt->name); ?>)</code>
            </label>
            <?php
        }
        ?>
        <p class="description">
            <?php esc_html_e('Select which post types to include when generating llms.txt content.', 'seo-fury'); ?>
        </p>
        <?php
    }

    /**
     * Content textarea callback.
     */
    public function llms_txt_content_callback() {
        $content = get_option('seo_fury_llms_txt_content', '');
        if (empty($content)) {
            $content = $this->generate_llms_txt_content(false);
        }
        ?>
        <textarea name="seo_fury_llms_txt_content" id="seo-llms-txt-content" rows="20" cols="80" class="large-text code" style="font-family: monospace; width: 100%;"><?php echo esc_textarea($content); ?></textarea>
        <p class="description">
            <?php esc_html_e('Edit the llms.txt content directly. If "Auto-generate from site" is enabled, this content will be overridden with dynamically generated content.', 'seo-fury'); ?>
        </p>
        <?php
    }

    /**
     * Regenerate button callback.
     */
    public function llms_txt_regenerate_callback() {
        ?>
        <button type="button" id="seo-regenerate-llms-txt" class="button button-secondary">
            <?php esc_html_e('Regenerate from site', 'seo-fury'); ?>
        </button>
        <span id="seo-regenerate-llms-txt-status" style="margin-left: 10px;"></span>
        <p class="description">
            <?php esc_html_e('Regenerate the llms.txt content based on your current site structure. This will replace the content in the editor above.', 'seo-fury'); ?>
        </p>
        <script>
        jQuery(document).ready(function($) {
            $('#seo-regenerate-llms-txt').on('click', function() {
                if (!confirm('<?php echo esc_js(__('Regenerate llms.txt content from site structure? The current content will be replaced.', 'seo-fury')); ?>')) {
                    return;
                }
                var $btn = $(this);
                var $status = $('#seo-regenerate-llms-txt-status');
                $btn.prop('disabled', true);
                $status.html('<span style="color: orange;"><?php echo esc_js(__('Generating...', 'seo-fury')); ?></span>');
                $.ajax({
                    url: ajaxurl,
                    type: 'POST',
                    data: {
                        action: 'seo_fury_regenerate_llms_txt',
                        _ajax_nonce: '<?php echo esc_js( wp_create_nonce('seo_fury_regenerate_llms_txt_nonce') ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>'
                    },
                    success: function(response) {
                        if (response.success) {
                            $status.html('<span style="color: green;"><?php echo esc_js(__('Content regenerated!', 'seo-fury')); ?></span>');
                            if (response.data && response.data.content) {
                                $('#seo-llms-txt-content').val(response.data.content);
                            }
                        } else {
                            $status.html('<span style="color: red;"><?php echo esc_js(__('Error:', 'seo-fury')); ?> ' + (response.data || '<?php echo esc_js(__('unknown', 'seo-fury')); ?>') + '</span>');
                        }
                        $btn.prop('disabled', false);
                    },
                    error: function() {
                        $status.html('<span style="color: red;"><?php echo esc_js(__('AJAX error', 'seo-fury')); ?></span>');
                        $btn.prop('disabled', false);
                    }
                });
            });
        });
        </script>
        <?php
    }

    /**
     * Link to view current llms.txt callback.
     */
    public function llms_txt_link_callback() {
        $llms_url = home_url('/llms.txt');
        $llms_full_url = home_url('/llms-full.txt');
        ?>
        <p>
            <strong><?php esc_html_e('llms.txt:', 'seo-fury'); ?></strong>
            <a href="<?php echo esc_url($llms_url); ?>" target="_blank" style="font-size: 14px; font-weight: 600;">
                <?php echo esc_html($llms_url); ?>
            </a>
        </p>
        <p>
            <strong><?php esc_html_e('llms-full.txt:', 'seo-fury'); ?></strong>
            <a href="<?php echo esc_url($llms_full_url); ?>" target="_blank" style="font-size: 14px; font-weight: 600;">
                <?php echo esc_html($llms_full_url); ?>
            </a>
        </p>
        <?php
    }

    /**
     * AJAX handler: regenerate llms.txt content from site structure.
     */
    public function ajax_regenerate_llms_txt() {
        check_ajax_referer('seo_fury_regenerate_llms_txt_nonce', '_ajax_nonce');

        if (!current_user_can('manage_options')) {
            wp_send_json_error(__('Insufficient permissions.', 'seo-fury'));
        }

        $content = $this->generate_llms_txt_content(false);
        update_option('seo_fury_llms_txt_content', $content);

        wp_send_json_success(array(
            'content' => $content,
            'message' => __('Content regenerated successfully.', 'seo-fury'),
        ));
    }

    /**
     * Render the admin tab content.
     *
     * Called from class-admin.php in the settings page switch/case.
     */
    public function render_admin_tab() {
        ?>
        <form method="post" action="options.php">
            <?php
            settings_fields('seo_fury_llms_txt_group');
            do_settings_sections('seo_fury_llms_txt_group');
            submit_button();
            ?>
        </form>
        <?php
    }
}
