<?php

namespace App\Controllers;

use App\Models\ConversationModel;
use App\Models\GptModel_2;
use App\Models\DoThisModel;
use App\Models\GptModelsModel;
use Tectalic\OpenAi\Manager as OpenAiManager;
use GuzzleHttp\Client as GuzzleClient;

class Conversations extends BaseController
{
    public function create()
    {
        $model = new ConversationModel();

        // Insert a new conversation
        $data = [
            'title' => '' // Placeholder, will update with ID
        ];

        $model->insert($data);
        $insertedId = $model->getInsertID();

        // Update title with ID
        $updatedData = [
            'title' => 'New Conversation (' . $insertedId . ')'
        ];
        $model->update($insertedId, $updatedData);

        // Redirect to the view page
        return redirect()->to("/conversations/view/$insertedId");
    }

    public function edit($id)
    {
        $model = new ConversationModel();

        $conversation = $model->find($id);

        if (!$conversation) {
            throw new \CodeIgniter\Exceptions\PageNotFoundException('Conversation not found');
        }

        // Load the edit view
        return view('conversations/edit', [
            'conversation' => $conversation
        ]);
    }

    public function update($id)
    {
        $model = new ConversationModel();

        $title = $this->request->getPost('title');

        $model->update($id, ['title' => $title]);

        // Redirect back to the main page
        return redirect()->back();
    }

    public function delete($id)
    {
        $model = new ConversationModel();

        // Check if conversation exists
        if (!$model->find($id)) {
            throw new \CodeIgniter\Exceptions\PageNotFoundException('Conversation not found');
        }

        // Delete conversation
        $model->delete($id);

        return redirect()->to('/')->with('message', 'Conversation deleted successfully.');
    }

    public function view($id)
    {
        $conversationModel = new ConversationModel();
        $gptModel = new GptModel_2();
        $doThisModel = new DoThisModel();
        $gptModelsModel = new GptModelsModel();

        $conversation = $conversationModel->find($id);

        if (!$conversation) {
            throw new \CodeIgniter\Exceptions\PageNotFoundException('Conversation not found');
        }

        // Fetch all conversations for the sidebar
        $conversations = $conversationModel->orderBy('id', 'DESC')->findAll();

        // Fetch all messages for this conversation
        $messages = $gptModel->where('conversation_id', $id)
                             ->orderBy('id', 'ASC')
                             ->findAll();

        // Fetch all 'do_this' entries for dropdown
        $doThisOptions = $doThisModel->findAll();

        // Fetch all GPT models for dropdown
        $gptModels = $gptModelsModel->findAll();

        // Pass data to view
        return view('conversations/view', [
            'conversation' => $conversation,
            'messages' => $messages,
            'conversations' => $conversations,
            'doThisOptions' => $doThisOptions,
            'gptModels' => $gptModels,
        ]);
    }

    public function sendMessage()
    {
        $gptModel = new GptModel_2();
        $gptModelsModel = new GptModelsModel();

        $conversationId = $this->request->getPost('conversation_id');
        $doThis = $this->request->getPost('do_this');
        $toThis = $this->request->getPost('to_this');
        $selectedGptModelId = $this->request->getPost('gpt_model');

        // Retrieve selected items
        $selectedDoThisIds = $this->request->getPost('selected_do_this'); // Array of message IDs
        $selectedToThisIds = $this->request->getPost('selected_to_this'); // Array of message IDs
        $selectedGptResponseIds = $this->request->getPost('selected_gpt_response'); // Array of message IDs

        // Validate required fields
        if (!$toThis) {
            return redirect()->back()->withInput()->with('error', 'To This field is required.');
        }

        // Retrieve the GPT model
        $gptModelEntry = $gptModelsModel->find($selectedGptModelId);

        if (!$gptModelEntry) {
            // Handle error, model not found
            return redirect()->back()->withInput()->with('error', 'Invalid GPT Model selected.');
        }

        $gptModelName = $gptModelEntry['model'];

        // Create new entry in the 'gpt' table
        $data = [
            'conversation_id' => $conversationId,
            'do_this' => $doThis,
            'to_this' => $toThis,
            'gpt_response' => '',
        ];

        $gptModel->insert($data);
        $insertedId = $gptModel->getInsertID();

        // Build the conversation history
        $conversationHistory = [];

        // Fetch and process selected items
        $messageIds = array_unique(array_merge(
            $selectedDoThisIds ?? [],
            $selectedToThisIds ?? [],
            $selectedGptResponseIds ?? []
        ));

        if (!empty($messageIds)) {
            // Ensure the IDs are integers to prevent SQL injection
            $messageIds = array_map('intval', $messageIds);

            // Retrieve the selected messages in the order they were created
            $selectedMessages = $gptModel->whereIn('id', $messageIds)
                                         ->orderBy('id', 'ASC')
                                         ->findAll();

            foreach ($selectedMessages as $msg) {
                // Build the user's message
                $userContentParts = [];

                if (in_array($msg['id'], $selectedDoThisIds ?? [])) {
                    $userContentParts[] = "Instruction: " . $msg['do_this'];
                }

                if (in_array($msg['id'], $selectedToThisIds ?? [])) {
                    $userContentParts[] = "Input: " . $msg['to_this'];
                }

                if (!empty($userContentParts)) {
                    $conversationHistory[] = [
                        'role' => 'user',
                        'content' => implode("\n", $userContentParts),
                    ];
                }

                // Add assistant's response if selected
                if (in_array($msg['id'], $selectedGptResponseIds ?? [])) {
                    $conversationHistory[] = [
                        'role' => 'assistant',
                        'content' => $msg['gpt_response'],
                    ];
                }
            }
        }

        // Add the new message
        $newUserContentParts = [];

        if (!empty($doThis)) {
            $newUserContentParts[] = "Instruction: " . $doThis;
        }

        if (!empty($toThis)) {
            $newUserContentParts[] = "Input: " . $toThis;
        }

        $conversationHistory[] = [
            'role' => 'user',
            'content' => implode("\n", $newUserContentParts),
        ];

        // Send to GPT with the selected model
        $response = $this->sendToGPT($conversationHistory, $gptModelName);

        // Update the new message with GPT's response
        $gptModel->update($insertedId, ['gpt_response' => $response]);

        // Redirect back to the conversation view
        return redirect()->to('/conversations/view/' . $conversationId);
    }

    public function getDoThisText($id)
    {
        $doThisModel = new DoThisModel();
        $doThisEntry = $doThisModel->find($id);

        if ($doThisEntry) {
            return $this->response->setJSON(['do_this' => $doThisEntry['do_this']]);
        } else {
            return $this->response->setJSON(['do_this' => '']);
        }
    }

    private function sendToGPT($messages, $modelName)
    {
        // Build the OpenAI client
        $openaiClient = OpenAiManager::build(
            new GuzzleClient(),
            new \Tectalic\OpenAi\Authentication('sk-hxKXip4XIKoZSsryz4sEVPafxoT1z4MXOMZpQhX_uDT3BlbkFJebXJbeJVxqg5mZH2DyBVwvocDwjExlDJE11Nr9kMAA') // Replace with your actual API key
        );

        try {
            // Send data to OpenAI with the selected model
            $apiResponse = $openaiClient->chatCompletions()->create(
                new \Tectalic\OpenAi\Models\ChatCompletions\CreateRequest([
                    'model' => $modelName,
                    'messages' => $messages,
                ])
            )->toModel();

            // Return the response from GPT
            return $apiResponse->choices[0]->message->content;
        } catch (\Exception $e) {
            // Log or handle the exception
            return 'Error communicating with GPT: ' . $e->getMessage();
        }
    }
}