<?php

namespace lucidpen;

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

/**
 * class Assistant
 * This class serves as a base for creating AI assistants that can interact with users.
 * It provides methods to ask questions and handle responses using the Azure OpenAI service.
 */
abstract class Assistant
{
    protected const ASSISTANT_PANEL_TITLE = '';
    protected const EDITOR_PANEL_TITLE = '';
    protected const CATEGORY = '';
    protected const SLUG = '';
    protected const SLUG_OPTION_NAME = LCPN_ABBR . '_option_assistant';

    public static function register(bool $active = true): void
    {
        AssistantFactory::get_instance()->registerAssistantClass(static::class, $active);
    }

    public function __construct()
    {
    }

    public static function get_slug_option_name(): string
    {
        return static::SLUG_OPTION_NAME;
    }

    public static function get_default_slug(): string
    {
        return static::SLUG;
    }

    private ?string $slug = null;
    public function get_slug(bool $refresh = false): string
    {
        if ($refresh || $this->slug === null) {
            $this->slug = get_option(static::SLUG_OPTION_NAME, '');
            if (empty($this->slug)) {
                update_option(static::SLUG_OPTION_NAME, static::SLUG);
                $this->slug = static::SLUG;
            }
        }
        return $this->slug;
    }

    private ?string $query_var = null;

    public function get_var_name(bool $refresh = false): string
    {
        if ($refresh || $this->query_var === null) {
            # lowercase the slug and replace spaces and dash with underscores
            $this->query_var = strtolower(str_replace([' ', '-'], '_', $this->get_slug()));
        }
        return $this->query_var;
    }

    private ?AIServiceAbstract $aiservice = null;
    private function get_openai(): AIServiceAbstract
    {
        if ($this->aiservice === null) {
            $this->aiservice = AIServiceManager::get_instance()->get_service();
        }
        return $this->aiservice;
    }

    protected function ask($question, $context = [], $instruction = '', $options = null)
    {
        $result = $this->get_openai()->chat(array_merge(
            [['role' => 'system', 'content' => $instruction]],
            $context,
            [['role' => 'user', 'content' => $question]]
        ), $options);

        if (!$result->success) {
            throw new \Exception("Error: " . esc_html($result->message));
        }
        return $result->value;
    }

    public function get_assistant_panel_title(): string
    {
        return static::ASSISTANT_PANEL_TITLE;
    }
    public function get_editor_panel_title(): string
    {
        return static::EDITOR_PANEL_TITLE;
    }
    public function get_category(): string
    {
        return static::CATEGORY;
    }

    abstract public function chat($input, $history = []);
    abstract public function draft($history);
    abstract public function title($draft);
}


/**
 * Class AssistantTemplate
 * A template for context-aware assistant classes.
 * Override the constants in subclasses to customize the assistant’s UI and behavior.
 */
abstract class AssistantTemplate extends Assistant
{
    // UI and configuration constants
    protected const ASSISTANT_PANEL_TITLE = '';
    protected const EDITOR_PANEL_TITLE = '';
    protected const CATEGORY = '';
    protected const SLUG = '';

    // System messages for AI guidance (can be overridden per use case)
    protected const SYSTEM_MESSAGE_CHAT = '';
    protected const SYSTEM_MESSAGE_DRAFT = '';
    protected const SYSTEM_MESSAGE_BENEDICTION = '';
    protected const SYSTEM_MESSAGE_TITLE = '';

    // Greetings
    protected const STARTER_QUESTIONS = [];
    protected const GREETINGS = [];

    // Prompts for each assistant action (can be overridden per use case)
    protected const PROMPT_DRAFT = 'Write a complete draft for the provided context and requests.';
    protected const PROMPT_DRAFT_UPDATE = "Please update the following draft with the most recent details from our chat history. Add any new requests or thoughts that were shared. Here is the current draft:\n\n%s\n\n";
    protected const PROMPT_BENEDICTION = 'Write a short benediction to close our service.';
    protected const PROMPT_BENEDICTION_THEME = 'Theme: %s';
    protected const PROMPT_TITLE = 'Suggest a short, reverent title for the following content: %s';
    protected const PROMPT_GREETING = 'Generate a warm, gentle greeting to begin a conversation as an assistant. Respond only with the greeting sentence, nothing else.';
    protected const PROMPT_START_QUESTION = 'Generate a warm, gentle question to begin a conversation as an assistant. Respond only with the question sentence, nothing else.';
    protected const PROMPT_REQUEST_DRAFT = 'Determine if the last user input contains an explicit request for you to draft a post. Respond only with "yes" or "no".';
    protected const PROMPT_REQUEST_PUBLISH = 'Determine if the last user input contains an explicit request to publish the post. If yes, specify whether the user requests it to be published in public, in private, or if it is not mentioned. Respond only with "no", "yes - public", "yes - private", or "yes - not mentioned".';
    protected const PROMPT_CONTINUE_EDITING = 'Determine if the last user input contains an explicit request to continue editing the post in the default editor or WordPress editor. Respond only with "yes" or "no".';

    public function greeting(): string
    {
        $greetings = static::GREETINGS;

        // If a single string is provided, return it directly
        if (!empty($greetings) && is_string($greetings)) {
            return $greetings;
        }

        // Randomly select a greeting from the array
        if (is_array($greetings) && count($greetings) > 0) {
            return $greetings[array_rand($greetings)];
        }

        // AI generated greeting fallback
        return $this->ask(static::PROMPT_GREETING, [], static::SYSTEM_MESSAGE_CHAT);
    }

    public function starter_question():string
    {
        $questions = static::STARTER_QUESTIONS;

        // If a single string is provided, return it directly
        if (!empty($questions) && is_string($questions)) {
            return $questions;
        }

        // Randomly select a question from the array
        if (is_array($questions) && count($questions) > 0) {
            return $questions[array_rand($questions)];
        }

        // AI generated question fallback
        return $this->ask(static::PROMPT_START_QUESTION, [], static::SYSTEM_MESSAGE_CHAT);
    }

    /** Main chat interaction (guided conversation) */
    public function chat($input, $history = [])
    {
        return $this->ask($input, $history, static::SYSTEM_MESSAGE_CHAT);
    }
    // public function chat($input, $history = [])
    // {
    //     $first_response = $this->ask($input, $history, static::SYSTEM_MESSAGE_CHAT);
    //     $follow_up_question = $this->follow_up_question($input, $history);
    //     $combined_response = $first_response . "\n" . $follow_up_question;
    //     return $combined_response;
    // }

    // protected function follow_up_question($input, $history = [])
    // {
    //     // This method can be used to ask follow-up questions based on the previous chat
    //     return $this->ask($input, $history, static::SYSTEM_MESSAGE_CHAT);
    // }

    public function determine($input): array
    {
        $requests = [];

        // determine if the user explicitly asked for a draft
        if (strtolower($this->ask($input)) === 'yes') {
            $requests['draft'] = true;
        }
        Logger::info("[AssistantTemplate] determine() - draft request: " . json_encode($requests));

        // // determine if the user explicitly asked to continue editing the post
        // if (strtolower($this->ask($input)) === 'yes') {
        //     $requests['continue_editing'] = true;
        // }

        // // determine if the user explicitly asked to publish the post
        // $publish = strtolower($this->ask($input));
        // if ($publish === 'yes - public' || $publish === 'yes - not mentioned') {
        //     $requests['public'] = true;
        // }
        // if ($publish === 'yes - private') {
        //     $requests['private'] = true;
        // }

        return $requests;
    }

    /** Composes a full draft (e.g., prayer) based on provided context/history */
    public function draft($history, $context = null)
    {
        $question = empty($context)
            ? static::PROMPT_DRAFT
            : sprintf(static::PROMPT_DRAFT_UPDATE, $context);

        return $this->ask($question, $history, static::SYSTEM_MESSAGE_DRAFT);
    }

    /** Composes a short benediction or closing message */
    public function benediction($context = '')
    {
        $question = static::PROMPT_BENEDICTION
            . ($context ? sprintf(static::PROMPT_BENEDICTION_THEME, $context) : '');
        return $this->ask($question, [], static::SYSTEM_MESSAGE_BENEDICTION);
    }

    /** Suggests a short, meaningful title for the content */
    public function title($content)
    {
        $question = sprintf(static::PROMPT_TITLE, $content);
        return $this->ask($question, [], static::SYSTEM_MESSAGE_TITLE);
    }
}