<?php
/**
 * Sandbox Controller
 *
 * Handles sessions, prompt rendering and configuration export.
 *
 * @package SlideMind
 * @since 2.0.0
 */

namespace SlideMind\Admin;

use SlideMind\Core\PromptEngine;
use SlideMind\Core\ConfigRepository;

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

class SandboxController {

    /**
     * Transient prefix
     * @var string
     */
    private $transient_prefix = 'slidemind_sandbox_';

    /**
     * Session lifetime (1 hour)
     * @var int
     */
    private $session_expiry = 3600;

    /**
     * PromptEngine instance
     * @var PromptEngine
     */
    private $prompt_engine;

    /**
     * ConfigRepository instance
     * @var ConfigRepository
     */
    private $config_repository;

    /**
     * Constructor
     *
     * @param PromptEngine $prompt_engine
     * @param ConfigRepository $config_repository
     */
    public function __construct(PromptEngine $prompt_engine, ConfigRepository $config_repository) {
        $this->prompt_engine = $prompt_engine;
        $this->config_repository = $config_repository;

        $this->init_hooks();
    }

    /**
     * Initialize AJAX hooks
     */
    private function init_hooks() {
        add_action('wp_ajax_slidemind_sandbox_get_session', [$this, 'ajax_get_session']);
        add_action('wp_ajax_slidemind_sandbox_save_session', [$this, 'ajax_save_session']);
        add_action('wp_ajax_slidemind_sandbox_clear_session', [$this, 'ajax_clear_session']);
        add_action('wp_ajax_slidemind_sandbox_render_prompt', [$this, 'ajax_render_prompt']);
        add_action('wp_ajax_slidemind_sandbox_export_config', [$this, 'ajax_export_config']);
    }

    /**
     * Generate or retrieve the user session ID
     *
     * @return string Session ID
     */
    public function get_session_id() {
        $user_id = get_current_user_id();
        $session_key = $this->transient_prefix . 'session_' . $user_id;

        $session_id = get_transient($session_key);

        if (!$session_id) {
            $session_id = wp_hash($user_id . time() . wp_rand());
            set_transient($session_key, $session_id, $this->session_expiry);
        }

        return $session_id;
    }

    /**
     * Retrieve conversation history
     *
     * @param string $session_id
     * @return array Messages
     */
    public function get_conversation_history($session_id) {
        $key = $this->transient_prefix . 'history_' . $session_id;
        $history = get_transient($key);

        return is_array($history) ? $history : [];
    }

    /**
     * Save conversation history
     *
     * @param string $session_id
     * @param array $messages
     * @return bool
     */
    public function save_conversation_history($session_id, array $messages) {
        $key = $this->transient_prefix . 'history_' . $session_id;

        // Limit to 50 messages maximum to avoid oversized transients
        if (count($messages) > 50) {
            $messages = array_slice($messages, -50);
        }

        return set_transient($key, $messages, $this->session_expiry);
    }

    /**
     * Clear conversation
     *
     * @param string $session_id
     * @return bool
     */
    public function clear_conversation($session_id) {
        $key = $this->transient_prefix . 'history_' . $session_id;
        return delete_transient($key);
    }

    /**
     * Render a prompt with variables and return debug info
     *
     * @param string $prompt
     * @param array $variables
     * @return array
     */
    public function render_prompt($prompt, array $variables) {
        $extracted = $this->prompt_engine->extract_variables($prompt);
        $rendered = $this->prompt_engine->inject_variables($prompt, $variables);
        $validation = $this->prompt_engine->validate_variables($prompt, $variables);

        // Variables used (those present in the prompt AND provided)
        $variables_used = [];
        foreach ($extracted as $var_name) {
            if (isset($variables[$var_name])) {
                $variables_used[$var_name] = $variables[$var_name];
            }
        }

        return [
            'original'          => $prompt,
            'rendered'          => $rendered,
            'variables_found'   => $extracted,
            'variables_used'    => $variables_used,
            'variables_missing' => $validation['missing'],
        ];
    }

    /**
     * Export a configuration as JSON
     *
     * @param array $config
     * @return string JSON
     */
    public function export_config(array $config) {
        $export = [
            'export_version' => '1.0',
            'exported_at'    => current_time('c'),
            'exported_by'    => 'SlideMind Sandbox',
            'config'         => [
                'model_id'      => isset($config['model_id']) ? $config['model_id'] : '',
                'system_prompt' => isset($config['system_prompt']) ? $config['system_prompt'] : '',
                'temperature'   => isset($config['temperature']) ? floatval($config['temperature']) : 0.7,
                'max_tokens'    => isset($config['max_tokens']) ? intval($config['max_tokens']) : 1024,
                'variables'     => isset($config['variables']) ? $config['variables'] : [],
            ],
        ];

        // Add a conversation sample if provided
        if (!empty($config['conversation'])) {
            $export['conversation_sample'] = array_slice($config['conversation'], -6);
        }

        return wp_json_encode($export, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE);
    }

    /**
     * Generate a filename for the export
     *
     * @param array $config
     * @return string
     */
    public function generate_export_filename(array $config) {
        $model = isset($config['model_id']) ? sanitize_file_name($config['model_id']) : 'config';
        $model = str_replace('/', '-', $model);
        $date = gmdate('Y-m-d');

        return "sandbox-{$model}-{$date}.json";
    }

    /**
     * AJAX: Retrieve session and history
     */
    public function ajax_get_session() {
        check_ajax_referer('slidemind_admin_nonce', 'nonce');

        if (!current_user_can('manage_slidemind_configs')) {
            wp_send_json_error(['message' => __('Permission denied', 'slidemind')], 403);
        }

        $session_id = $this->get_session_id();
        $messages = $this->get_conversation_history($session_id);

        wp_send_json_success([
            'session_id' => $session_id,
            'messages'   => $messages,
            'expires_in' => $this->session_expiry,
        ]);
    }

    /**
     * AJAX: Save session
     */
    public function ajax_save_session() {
        check_ajax_referer('slidemind_admin_nonce', 'nonce');

        if (!current_user_can('manage_slidemind_configs')) {
            wp_send_json_error(['message' => __('Permission denied', 'slidemind')], 403);
        }

        $session_id = isset($_POST['session_id']) ? sanitize_text_field(wp_unslash($_POST['session_id'])) : '';
        // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- JSON data, sanitized after decode
        $messages_raw = isset($_POST['messages']) ? wp_unslash($_POST['messages']) : [];

        if (empty($session_id)) {
            $session_id = $this->get_session_id();
        }

        // Sanitize messages
        $messages = [];
        if (is_array($messages_raw)) {
            foreach ($messages_raw as $msg) {
                if (isset($msg['role']) && isset($msg['content'])) {
                    $messages[] = [
                        'role'    => sanitize_text_field($msg['role']),
                        'content' => sanitize_textarea_field($msg['content']),
                    ];
                }
            }
        }

        $saved = $this->save_conversation_history($session_id, $messages);

        if ($saved) {
            wp_send_json_success(['session_id' => $session_id]);
        } else {
            wp_send_json_error(['message' => __('Error saving session', 'slidemind')]);
        }
    }

    /**
     * AJAX: Clear session
     */
    public function ajax_clear_session() {
        check_ajax_referer('slidemind_admin_nonce', 'nonce');

        if (!current_user_can('manage_slidemind_configs')) {
            wp_send_json_error(['message' => __('Permission denied', 'slidemind')], 403);
        }

        $session_id = $this->get_session_id();
        $this->clear_conversation($session_id);

        // Generate a new session ID
        $user_id = get_current_user_id();
        $session_key = $this->transient_prefix . 'session_' . $user_id;
        delete_transient($session_key);

        $new_session_id = $this->get_session_id();

        wp_send_json_success([
            'session_id' => $new_session_id,
            'message'    => __('Session reset', 'slidemind'),
        ]);
    }

    /**
     * AJAX: Render a prompt with variables
     */
    public function ajax_render_prompt() {
        check_ajax_referer('slidemind_admin_nonce', 'nonce');

        if (!current_user_can('manage_slidemind_configs')) {
            wp_send_json_error(['message' => __('Permission denied', 'slidemind')], 403);
        }

        $prompt = isset($_POST['prompt']) ? sanitize_textarea_field(wp_unslash($_POST['prompt'])) : '';
        // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- JSON data, sanitized after decode
        $variables_raw = isset($_POST['variables']) ? wp_unslash($_POST['variables']) : [];

        // Sanitize variables
        $variables = [];
        if (is_array($variables_raw)) {
            foreach ($variables_raw as $key => $value) {
                $safe_key = sanitize_text_field($key);
                if (!empty($safe_key)) {
                    $variables[$safe_key] = sanitize_textarea_field($value);
                }
            }
        }

        $result = $this->render_prompt($prompt, $variables);

        wp_send_json_success($result);
    }

    /**
     * AJAX: Export configuration
     */
    public function ajax_export_config() {
        check_ajax_referer('slidemind_admin_nonce', 'nonce');

        if (!current_user_can('manage_slidemind_configs')) {
            wp_send_json_error(['message' => __('Permission denied', 'slidemind')], 403);
        }

        $config = [
            'model_id'      => isset($_POST['model_id']) ? sanitize_text_field(wp_unslash($_POST['model_id'])) : '',
            'system_prompt' => isset($_POST['system_prompt']) ? sanitize_textarea_field(wp_unslash($_POST['system_prompt'])) : '',
            'temperature'   => isset($_POST['temperature']) ? floatval($_POST['temperature']) : 0.7,
            'max_tokens'    => isset($_POST['max_tokens']) ? intval($_POST['max_tokens']) : 1024,
            'variables'     => [],
            'conversation'  => [],
        ];

        // Variables
        // phpcs:disable WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- Array data, sanitized in loop
        if (isset($_POST['variables']) && is_array($_POST['variables'])) {
            foreach (wp_unslash($_POST['variables']) as $key => $value) {
                $safe_key = sanitize_text_field($key);
                if (!empty($safe_key)) {
                    $config['variables'][$safe_key] = sanitize_textarea_field($value);
                }
            }
        }

        // Conversation
        if (isset($_POST['conversation']) && is_array($_POST['conversation'])) {
            foreach (wp_unslash($_POST['conversation']) as $msg) {
                if (isset($msg['role']) && isset($msg['content'])) {
                    $config['conversation'][] = [
                        'role'    => sanitize_text_field($msg['role']),
                        'content' => sanitize_textarea_field($msg['content']),
                    ];
                }
            }
        }
        // phpcs:enable WordPress.Security.ValidatedSanitizedInput.InputNotSanitized

        $json = $this->export_config($config);
        $filename = $this->generate_export_filename($config);

        wp_send_json_success([
            'json'     => $json,
            'filename' => $filename,
        ]);
    }
}
