<?php

namespace lucidpen;

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

use \Exception;
use \WP_Query;
use \Parsedown;

/**
 * BaseFrontEndPage
 * This abstract class provides a base for front-end pages that handle creating, editing, and listing drafts.
 * Subclasses must define the necessary constants for their specific functionality.
 */
abstract class BaseFrontEndPage
{
    protected const CSS_JS_VERSION = '1.1.20300';
    protected const CSS_HANDLE = '';
    protected const JS_HANDLE = '';
    protected const CSS_FILE = '';
    protected const JS_FILE = '';
    protected const NONCE_NAME = '';
    protected const TEMPLATE_FILE = '';

    protected const POSTS_PER_PAGE = 20; // Default number of posts per page

    private $assistant;

    public function __construct($assistant)
    {
        $this->assistant = $assistant;
        add_action('init', [$this, 'init']);
        add_action('template_redirect', [$this, 'render_template']);
        add_action('wp_enqueue_scripts', [$this, 'enqueue_assets']);
        add_action('admin_bar_menu', [$this, 'add_custom_admin_bar_link'], 80); // Add the action hook here
    }

    public function init(): void
    {
        $this->register_slug();
    }

    abstract public function register_slug(): void;

    abstract protected function is_active_type(): bool;

    public function enqueue_assets()
    {
        if ($this->is_active_type()) {
            $this->enqueue_assets_internal();
            $mode = get_query_var($this->get_var_name()) ?: '';
            do_action("lucidpen_enqueue_assets", $this->get_slug(), $mode);
        }
    }

    abstract protected function enqueue_assets_internal();

    public function add_custom_admin_bar_link($wp_admin_bar)
    {
        if (!is_user_logged_in() || !current_user_can('edit_posts')) {
            return;
        }

        $slug = $this->get_slug();
        $var_name = $this->get_var_name();
        $url = home_url("/{$slug}/new/");

        $wp_admin_bar->add_node([
            'id' => "{$var_name}_new",
            'parent' => 'new-content',
            'title' => esc_html($this->get_assistant()->get_category()),
            'href' => $url,
            'meta' => [
                'class' => 'lucidpen-new-draft',
                'title' => esc_html($this->get_assistant()->get_editor_panel_title()),
            ],
        ]);
    }

    /**
     * Render the template for this page
     */

    public function render_template(): void
    {
        // Check if this is the active type
        if (!$this->is_active_type()) {
            return;
        }

        // If not logged in, redirect to login page
        if (!is_user_logged_in()) {
            wp_safe_redirect(wp_login_url(home_url('/' . $this->get_slug() . '/')));
            exit;
        }

        // Render the template
        $this->render_template_internal();
    }

    protected function render_template_internal(): void
    {
        status_header(200);
        nocache_headers();
        get_header();
        include LCPN_PLUGIN_DIR . static::TEMPLATE_FILE;
        get_footer();
        exit;
    }

    // --- helpers for Parsedown and PostManager ---
    private $parsedown = null;
    protected function get_parsedown(): \Parsedown
    {
        if ($this->parsedown === null) {
            require_once LCPN_PLUGIN_DIR . 'vendor/parsedown/Parsedown.php';
            $this->parsedown = new \Parsedown();
        }
        return $this->parsedown;
    }
    protected function get_post_manager($post_id = null): PostManager
    {
        require_once LCPN_PLUGIN_DIR . 'include/cls-post-manager.php';
        return new PostManager($this->get_category(), $post_id ?? PostManager::INVALID_POST_ID);
    }

    protected function get_category(): string
    {
        return $this->get_assistant()->get_category();
    }

    protected function get_slug(): string
    {
        return $this->get_assistant()->get_slug();
    }

    protected function get_var_name(): string
    {
        return $this->get_assistant()->get_var_name();
    }

    protected function get_assistant(): Assistant
    {
        return $this->assistant;
    }

    private ?string $nonce_name = null;
    protected function get_nonce_name(): string
    {
        if ($this->nonce_name === null) {
            $this->nonce_name = $this->get_var_name() . '_nonce';
        }
        return $this->nonce_name;
    }
}



/* *********************************************************************************
 * Class EditFrontEndPage
 *   This abstract class provides a base for editing drafts with AI assistance.
 * *********************************************************************************/
abstract class EditFrontEndPage extends BaseFrontEndPage
{
    public function __construct($assistant)
    {
        parent::__construct($assistant);
        if (defined('DOING_AJAX') && DOING_AJAX) {
            $this->register_ajax_handlers();
        }
    }

    public function register_slug(): void
    {
        $slug = $this->get_assistant()->get_slug(true);
        $var = $this->get_assistant()->get_var_name(true);

        add_rewrite_tag("%{$var}%", '([^&]+)');
        add_rewrite_tag('%post_id%', '([0-9]+)');
        add_rewrite_rule("^{$slug}/new/?$", "index.php?{$var}=new", 'top');
        add_rewrite_rule("^{$slug}/([0-9]+)/edit/?$", "index.php?{$var}=edit&post_id=\$matches[1]", 'top');
    }

    protected function is_active_type(): bool
    {
        $type = get_query_var($this->get_var_name()) ?: '';
        return in_array($type, ['new', 'edit'], true);
    }

    protected function register_ajax_handlers()
    {
        $actions = [
            'load_existing' => 'handle_load_existing',
            'chat' => 'handle_chat',
            'clear_chat' => 'handle_clear_chat',
            'compose_and_title' => 'handle_compose_and_title',
            'save' => 'handle_save',
            'discard' => 'handle_discard',
            'post_result' => 'handle_post_result',
        ];
        foreach ($actions as $action => $handler) {
            $var_name = $this->get_var_name();
            add_action("wp_ajax_{$var_name}_{$action}", [$this, $handler]);
            add_action("wp_ajax_nopriv_{$var_name}_{$action}", [$this, $handler]);
        }
    }

    protected function enqueue_assets_internal()
    {
        wp_register_script('tinymce_7_9_1', LCPN_PLUGIN_URL . 'vendor/tinymce/tinymce.min.js', [], '7.9.1', true);
        wp_enqueue_script('tinymce_7_9_1');
        wp_enqueue_style(static::CSS_HANDLE, LCPN_PLUGIN_URL . static::CSS_FILE, [], self::CSS_JS_VERSION);
        wp_enqueue_script(static::JS_HANDLE, LCPN_PLUGIN_URL . static::JS_FILE, [], self::CSS_JS_VERSION, true);

        $post_id = intval(get_query_var('post_id') ?: 0);
        wp_localize_script(static::JS_HANDLE, 'LCPN_PAGE_VARS', [
            'ajax_url' => admin_url('admin-ajax.php'),
            'nonce' => wp_create_nonce($this->get_nonce_name()),
            'prefix' => $this->get_slug(), // e.g. 'blog'
            'post_id' => $post_id,
            'tinymce_plugins' => LCPN_PLUGIN_URL . 'vendor/tinymce/plugins',

            'assistant_panel_title' => esc_html($this->get_assistant()->get_assistant_panel_title()),
            'assistant_starter_question' => esc_html($this->get_assistant()->starter_question()),
            'assistant_greeting' => esc_html($this->get_assistant()->greeting()),
            'editor_panel_title' => esc_html($this->get_assistant()->get_editor_panel_title()),
        ]);
    }

    // ------------- AJAX HANDLERS for edit page -------------
    public function handle_load_existing()
    {
        try {
            check_ajax_referer($this->get_nonce_name(), 'nonce');
            $post_id = intval($_POST['post_id'] ?? 0);

            if (!$post_id) {
                throw new Exception('Invalid or missing post ID.');
            }

            $post_manager = $this->get_post_manager($post_id);
            $chat_history = $post_manager->load_chat_history();
            $post = $post_manager->get_post();

            $title = $post->post_title ?? '';
            $content = $post->post_content ?? '';

            $Parsedown = $this->get_parsedown();
            $chat_history_html = array_map(function ($msg) use ($Parsedown) {
                $content_html = $msg['role'] === 'assistant'
                    ? wp_unslash($Parsedown->text($msg['content']))   // stripslashes ?
                    : '<p>' . esc_html($msg['content']) . '</p>';
                return [
                    'role' => $msg['role'],
                    'content_html' => $content_html,
                    'content' => $msg['content'],
                ];
            }, $chat_history);

            wp_send_json_success([
                'history' => $chat_history,
                'history_html' => $chat_history_html,
                'guide_question' => '',
                'post' => [
                    'title' => $title,
                    'content' => $content,
                ],
                'post_id' => $post_id,
            ]);
        } catch (Exception $e) {
            wp_send_json_error(['message' => $e->getMessage()]);
        }
    }

    public function handle_chat()
    {
        try {
            check_ajax_referer($this->get_nonce_name(), 'nonce');
            $post_id = intval($_POST['post_id'] ?? 0);
            $message = sanitize_text_field(wp_unslash($_POST['message'] ?? ''));

            $assistant = $this->get_assistant();

            // Determine this is a request not a chat message
            $requests = $assistant->determine($message);

            $post_manager = $this->get_post_manager($post_id);
            $history = $post_manager->load_chat_history();

            $history[] = ['role' => 'user', 'content' => $message];

            $reply = $assistant->chat($message, $history);

            $history[] = ['role' => 'assistant', 'content' => $reply];
            $post_manager->store_chat_history($history);

            $Parsedown = $this->get_parsedown();
            $history_html = array_map(function ($msg) use ($Parsedown) {
                $content_html = $msg['role'] === 'assistant' ? $Parsedown->text($msg['content']) : '<p>' . esc_html($msg['content']) . '</p>';
                return [
                    'role' => $msg['role'],
                    'content_html' => $content_html,
                    'content' => $msg['content'],
                ];
            }, $history);

            wp_send_json_success([
                'reply' => $reply,
                'history' => $history,
                'history_html' => $history_html,
                'post_id' => $post_manager->get_post_id(),
                'requests' => $requests
            ]);
        } catch (Exception $e) {
            wp_send_json_error(['message' => 'Error: ' . $e->getMessage()]);
        }
    }

    public function handle_clear_chat()
    {
        try {
            check_ajax_referer($this->get_nonce_name(), 'nonce');
            $post_id = intval($_POST['post_id'] ?? 0);
            $post_manager = $this->get_post_manager($post_id);
            $post_manager->store_chat_history([]);
            wp_send_json_success(['message' => 'Chat cleared!', 'post_id' => $post_manager->get_post_id()]);
        } catch (Exception $e) {
            wp_send_json_error(['message' => $e->getMessage()]);
        }
    }

    public function handle_compose_and_title()
    {
        try {
            check_ajax_referer($this->get_nonce_name(), 'nonce');
            $post_id = intval($_POST['post_id'] ?? 0);
            $post_manager = $this->get_post_manager($post_id);

            $history = $post_manager->load_chat_history();
            if (empty($history)) {
                throw new Exception('No chat history available to draft a post.');
            }

            $assistant = $this->get_assistant();
            $content = sanitize_text_field(wp_unslash($_POST['content'] ?? ''));
            $draft_content = $assistant->draft($history, $content);
            $title = $assistant->title($draft_content);

            $title = preg_replace('/^\"|\"$/', '', trim($title));
            $Parsedown = $this->get_parsedown();
            $draft_html = $Parsedown->text(preg_replace('/```.*?\n(.*?)```/s', '$1', $draft_content));

            wp_send_json_success([
                'draft_content' => $draft_content,
                'draft_html' => $draft_html,
                'title' => $title,
                'post_id' => $post_manager->get_post_id(),
            ]);
        } catch (Exception $e) {
            wp_send_json_error(['message' => 'Error: ' . $e->getMessage()]);
        }
    }

    public function handle_save()
    {
        try {
            check_ajax_referer($this->get_nonce_name(), 'nonce');
            $post_id = intval($_POST['post_id'] ?? 0);
            $title = sanitize_text_field(wp_unslash($_POST['title'] ?? ''));
            $content = wp_kses_post(wp_unslash($_POST['content'] ?? ''));

            if ($post_id <= 0 || !current_user_can('edit_post', $post_id)) {
                wp_send_json_error(['message' => 'Invalid post.']);
            }

            $assistant = $this->get_assistant();
            $category = $assistant->get_category();

            $post_manager = $this->get_post_manager($post_id);
            $ok = $post_manager->save_post($content, 'draft', $title, $category);

            if (!$ok) {
                throw new Exception('Failed to save draft.');
            }

            $post_manager->store_draft_history([
                'title' => $title,
                'content' => $content,
            ]);

            wp_send_json_success(['post_id' => $post_id]);
        } catch (Exception $e) {
            wp_send_json_error(['message' => 'Error: ' . $e->getMessage()]);
        }
    }

    public function handle_discard()
    {
        try {
            check_ajax_referer($this->get_nonce_name(), 'nonce');
            $post_id = intval($_POST['post_id'] ?? 0);

            if (!$post_id || get_post_status($post_id) !== 'draft') {
                throw new Exception('Invalid draft post ID.');
            }

            $res = $this->get_post_manager($post_id)->delete_post();
            if (is_wp_error($res)) {
                throw new Exception("Error deleting draft: PostID = $post_id.");
            }

            wp_send_json_success(['message' => 'Draft deleted.']);
        } catch (Exception $e) {
            wp_send_json_error(['message' => $e->getMessage()]);
        }
    }

    public function handle_post_result()
    {
        try {
            check_ajax_referer($this->get_nonce_name(), 'nonce');
            $post_id = intval($_POST['post_id'] ?? 0);
            $title = sanitize_text_field(wp_unslash($_POST['title'] ?? 'AI Chat Result'));
            $content = wp_kses_post(wp_unslash($_POST['content'] ?? ''));

            // NEW: Get 'status' from AJAX, default to 'publish'
            $status = sanitize_text_field(wp_unslash($_POST['status'] ?? ''));
            $status = !empty($status) && in_array($status, ['publish', 'private']) ? $status : 'publish';

            $assistant = $this->get_assistant();
            $category = $assistant->get_category();

            // Pass status to save_post!
            $post_manager = $this->get_post_manager($post_id);
            $ok = $post_manager->save_post($content, $status, $title, $category);

            $post_manager->store_draft_history([
                'title' => $title,
                'content' => $content
            ]);

            if (!$ok) {
                throw new Exception('Error publishing post.');
            }

            wp_send_json_success([
                'message' => 'Content posted!',
                'post_id' => $post_id,
                'permalink' => get_permalink($post_id),
            ]);
        } catch (Exception $e) {
            wp_send_json_error(['message' => $e->getMessage()]);
        }
    }
}


/* *********************************************************************************
 * Class ListFrontEndPage
 *   This abstract class provides a base for listing drafts in a specific category.
 * *********************************************************************************/
abstract class ListFrontEndPage extends BaseFrontEndPage
{
    // protected const CATEGORY = '';

    public function __construct($assistant)
    {
        parent::__construct($assistant);
        if (defined('DOING_AJAX') && DOING_AJAX) {
            $this->register_ajax_handlers();
        }
    }

    public function register_slug(): void
    {
        $var = $this->get_var_name();
        $slug = $this->get_slug();
        add_rewrite_tag("%{$var}%", '([^&]+)');
        add_rewrite_rule("^{$slug}/?$", "index.php?{$var}=list", 'top');
    }

    protected function is_active_type(): bool
    {
        $type = get_query_var($this->get_var_name()) ?: '';
        return in_array($type, ['list'], true);
    }

    protected function register_ajax_handlers()
    {
        $actions = [
            'list' => 'handle_list',
            'load' => 'handle_load',
            'delete' => 'handle_delete',
            'bulk_delete' => 'handle_bulk_delete',

        ];
        foreach ($actions as $action => $handler) {
            $var_name = $this->get_var_name();
            add_action("wp_ajax_{$var_name}_{$action}", [$this, $handler]);
            add_action("wp_ajax_nopriv_{$var_name}_{$action}", [$this, $handler]);
        }
    }

    protected function enqueue_assets_internal()
    {
        wp_enqueue_style(static::CSS_HANDLE, LCPN_PLUGIN_URL . static::CSS_FILE, [], self::CSS_JS_VERSION);
        wp_enqueue_script(static::JS_HANDLE, LCPN_PLUGIN_URL . static::JS_FILE, ['jquery'], self::CSS_JS_VERSION, true);

        $edit_url_prefix = '/' . $this->get_slug() . '/'; // e.g. "/blogs/" or "/prayers/"

        wp_localize_script(static::JS_HANDLE, 'LCPN_PAGE_VARS', [
            'ajax_url' => admin_url('admin-ajax.php'),
            'nonce' => wp_create_nonce($this->get_nonce_name()),
            'prefix' => $this->get_slug(),                  // e.g. 'blog'
            'edit_url_prefix' => $edit_url_prefix,          // e.g. '/blogs/'
        ]);
    }

    /**
     * List all drafts in this CATEGORY for the current user
     */
    public function handle_list()
    {
        try {
            check_ajax_referer($this->get_nonce_name(), 'nonce');
            $user_id = get_current_user_id();

            // Prepare the query arguments
            $args = [
                'post_type' => 'post',
                'author' => $user_id,
                'orderby' => 'modified',
                'order' => 'DESC',
                'category_name' => $this->get_category(),
                'fields' => 'ids',
            ];

            // Determine whether to filter only drafts or not
            $show_drafts_only = isset($_POST['drafts_only']) && $_POST['drafts_only'] == '1';
            if ($show_drafts_only) {
                $args['post_status'] = 'draft';
            } else {
                $args['post_status'] = ['publish', 'draft', 'private', 'pending', 'future'];  // Optionally include only visible statuses; or omit to include all
            }

            // Keyword search
            $keyword = isset($_POST['keyword']) ? sanitize_text_field(wp_unslash($_POST['keyword'])) : '';
            if (!empty($keyword)) {
                $args['s'] = $keyword;
            }

            // Pagination
            $page = isset($_POST['page']) ? max(1, intval($_POST['page'])) : 1;
            $args['paged'] = $page;
            $args['posts_per_page'] = self::POSTS_PER_PAGE; // or however many items per page


            $query = new \WP_Query($args);

            $posts = [];
            foreach ($query->posts as $post_id) {
                $post = get_post($post_id);
                if (!$post)
                    continue;
                $posts[] = [
                    'ID' => $post->ID,
                    'post_title' => $post->post_title ?: '(Untitled)',
                    'post_modified' => mysql2date('M j, Y H:i', $post->post_modified),
                    'post_content' => wp_trim_words($post->post_content, 40, '...'),
                    'post_status' => $post->post_status,
                    'permalink' => get_permalink($post->ID),
                ];
            }

            wp_send_json_success([
                'drafts' => $posts,
                'total_pages' => $query->max_num_pages
            ]);

        } catch (Exception $e) {
            wp_send_json_error(['message' => $e->getMessage()]);
        }
    }


    /**
     * Load a single draft by ID (only if in the right category)
     */
    public function handle_load()
    {
        try {
            check_ajax_referer($this->get_nonce_name(), 'nonce');
            $post_id = intval($_POST['post_id'] ?? 0);

            $post = get_post($post_id);
            if (!$post) {
                throw new Exception('Invalid or missing post ID.');
            }
            // Category check: if not in category, bail.
            if (!has_category($this->get_category(), $post)) {
                throw new Exception('This draft does not belong to the expected category.');
            }

            $manager = $this->get_post_manager($post_id);
            $draft = $manager->load_draft_history();
            $chat_history = $manager->load_chat_history();

            $parsedown = $this->get_parsedown();
            $chat_history_html = array_map(function ($msg) use ($parsedown) {
                $content_html = $msg['role'] === 'assistant'
                    ? $parsedown->text($msg['content'])
                    : '<p>' . esc_html($msg['content']) . '</p>';
                return [
                    'role' => $msg['role'],
                    'content_html' => $content_html,
                    'content' => $msg['content'],
                ];
            }, $chat_history);

            $draft_title = $draft['title'] ?? $post->post_title ?? '(Untitled)';
            $draft_content = $draft['content'] ?? $post->post_content ?? '';

            wp_send_json_success([
                'draft' => [
                    'title' => $draft_title,
                    'content' => $draft_content,
                ],
                'history_html' => $chat_history_html,
                'post_id' => $post_id,
            ]);
        } catch (Exception $e) {
            wp_send_json_error(['message' => $e->getMessage()]);
        }
    }

    public function handle_bulk_delete() {
        try {
            check_ajax_referer( $this->get_nonce_name(), 'nonce' );

            // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedVariableFound
            $post_ids = isset($_POST['post_ids'])
                ? array_map('intval', (array) wp_unslash($_POST['post_ids']))
                : [];

            if ( empty( $post_ids ) ) {
                throw new \Exception( 'No posts selected for deletion.' );
            }

            foreach ( $post_ids as $post_id ) {
                if ( current_user_can( 'delete_post', $post_id ) ) {
                    wp_delete_post( $post_id, true );
                }
            }

            wp_send_json_success( [ 'message' => 'Posts deleted successfully.' ] );

        } catch ( \Exception $e ) {
            wp_send_json_error( [ 'message' => $e->getMessage() ] );
        }
    }


    public function handle_delete()
    {
        try {
            check_ajax_referer($this->get_nonce_name(), 'nonce');
            $post_id = intval($_POST['post_id'] ?? 0);

            if (!$post_id) {
                throw new Exception('Invalid post ID.');
            }

            // Check permissions
            if (!current_user_can('delete_post', $post_id)) {
                throw new Exception('Permission denied.');
            }

            $post_manager = $this->get_post_manager($post_id);
            $result = $post_manager->delete_post();

            if (is_wp_error($result)) {
                throw new Exception($result->get_error_message());
            }

            wp_send_json_success(['message' => 'Post deleted successfully.', 'post_id' => $post_id]);
        } catch (Exception $e) {
            wp_send_json_error(['message' => $e->getMessage()]);
        }
    }

}
