<?php

namespace OtomaticAi\Controllers\Settings;

use Exception;
use OtomaticAi\Api\OpenAi\Client as OpenAiClient;
use OtomaticAi\Api\OpenAi\Exceptions\AuthentificationException as OpenAiAuthentificationException;
use OtomaticAi\Api\MistralAi\Client as MistralAiClient;
use OtomaticAi\Api\MistralAi\Exceptions\AuthentificationException as MistralAiAuthentificationException;
use OtomaticAi\Api\XAi\Client as XAiClient;
use OtomaticAi\Api\XAi\Exceptions\AuthentificationException as XAiAuthentificationException;
use OtomaticAi\Api\Groq\Client as GroqClient;
use OtomaticAi\Api\Groq\Exceptions\AuthentificationException as GroqAuthentificationException;
use OtomaticAi\Api\StabilityAi\Client as StabilityAiClient;
use OtomaticAi\Api\StabilityAi\Exceptions\AuthentificationException as StabilityAiAuthentificationException;
use OtomaticAi\Api\DeepSeek\Client as DeepSeekClient;
use OtomaticAi\Api\DeepSeek\Exceptions\AuthentificationException as DeepSeekAuthentificationException;
use OtomaticAi\Api\Gemini\Client as GeminiClient;
use OtomaticAi\Api\Gemini\Exceptions\AuthentificationException as GeminiAuthentificationException;
use OtomaticAi\Controllers\Controller;
use OtomaticAi\Utils\Auth;
use OtomaticAi\Utils\Settings;

class ApiController extends Controller
{
    /**
     * Get the api settings
     *
     * @return void
     */
    public function index()
    {
        $this->verifyNonce();

        $this->response(Settings::get('api'));
    }

    /**
     * Validate the openai signature.
     * 
     * @return void
     */
    public function validateOpenAI()
    {
        $this->verifyNonce();

        $this->validate([
            "api_key" => ["required", "string"],
            "force" => ["boolean"],
        ]);

        // validate openai api key
        try {
            $api = new OpenAiClient($this->input("api_key"));
            $models = $api->listModels();
        } catch (OpenAiAuthentificationException $e) {
            $this->response(["message" => $e->getMessage(), "errors" => ['api_key' => [$e->getMessage()]]], 422);
        } catch (Exception $e) {
            $this->response(["message" => "An error occurred", "error" => $e->getMessage()], 503);
        }

        // valisate openai signature
        try {
            $response = Auth::validateOpenAISignature($this->input("api_key"), $this->input("force", false));
            $this->response($response);
        } catch (Exception $e) {
            $this->response(["message" => "An error occurred", "error" => $e->getMessage()], 503);
        }

        $this->emptyResponse([
            "success" => false
        ]);
    }

    /**
     * Set the openai settings.
     * 
     * @return void
     */
    public function setOpenAI()
    {
        $this->verifyNonce();

        $this->validate([
            "api_key" => ["required", "string"],
        ]);

        // validate openai api key
        if (!empty($this->input("api_key"))) {
            try {
                $api = new OpenAiClient($this->input("api_key"));
                $models = $api->listModels();
            } catch (OpenAiAuthentificationException $e) {
                $this->response(["message" => $e->getMessage(), "errors" => ['api_key' => [$e->getMessage()]]], 422);
            } catch (Exception $e) {
                $this->response(["message" => "An error occurred", "error" => $e->getMessage()], 503);
            }
        }

        Settings::update($this->request, 'api.openai');
        Settings::save();

        $this->emptyResponse();
    }

    /**
     * Update the openai settings.
     * 
     * @return void
     */
    public function updateOpenAI()
    {
        $this->verifyNonce();

        $this->validate([
            "api_key" => ["nullable", "string"],
        ]);

        // validate openai api key
        if (!empty($this->input("api_key"))) {
            try {
                $api = new OpenAiClient($this->input("api_key"));
                $models = $api->listModels();
            } catch (OpenAiAuthentificationException $e) {
                $this->response(["message" => $e->getMessage(), "errors" => ['api_key' => [$e->getMessage()]]], 422);
            } catch (Exception $e) {
                $this->response(["message" => "An error occurred", "error" => $e->getMessage()], 503);
            }
        }

        Settings::update($this->request, 'api.openai');
        Settings::save();

        $this->emptyResponse();
    }

    /**
     * Update the mistral ai settings.
     * 
     * @return void
     */
    public function updateMistralAi()
    {
        $this->verifyNonce();

        $this->validate([
            "api_key" => ["nullable", "string"],
        ]);

        // validate mistral ai api key
        if (!empty($this->input("api_key"))) {
            try {
                $api = new MistralAiClient($this->input("api_key"));
                $models = $api->listModels();
            } catch (MistralAiAuthentificationException $e) {
                $this->response(["message" => "Incorrect API key provided", "errors" => ['api_key' => ["Incorrect API key provided"]]], 422);
            } catch (Exception $e) {
                $this->response(["message" => "An error occurred", "error" => $e->getMessage()], 503);
            }
        }

        Settings::update($this->request, 'api.mistral_ai');
        Settings::save();

        $this->emptyResponse();
    }

    /**
     * Update the xai settings.
     * 
     * @return void
     */
    public function updateXAi()
    {
        $this->verifyNonce();

        $this->validate([
            "api_key" => ["nullable", "string"],
        ]);

        // validate mistral ai api key
        if (!empty($this->input("api_key"))) {
            try {
                $api = new XAiClient($this->input("api_key"));
                $models = $api->listModels();
            } catch (XAiAuthentificationException $e) {
                $this->response(["message" => "Incorrect API key provided", "errors" => ['api_key' => ["Incorrect API key provided"]]], 422);
            } catch (Exception $e) {
                $this->response(["message" => "An error occurred", "error" => $e->getMessage()], 503);
            }
        }

        Settings::update($this->request, 'api.x_ai');
        Settings::save();

        $this->emptyResponse();
    }

    /**
     * Update the groq settings.
     * 
     * @return void
     */
    public function updateGroq()
    {
        $this->verifyNonce();

        $this->validate([
            "api_key" => ["nullable", "string"],
        ]);

        // validate groq api key
        if (!empty($this->input("api_key"))) {
            try {
                $api = new GroqClient($this->input("api_key"));
                $models = $api->listModels();
            } catch (GroqAuthentificationException $e) {
                $this->response(["message" => "Incorrect API key provided", "errors" => ['api_key' => ["Incorrect API key provided"]]], 422);
            } catch (Exception $e) {
                $this->response(["message" => "An error occurred", "error" => $e->getMessage()], 503);
            }
        }

        Settings::update($this->request, 'api.groq');
        Settings::save();

        $this->emptyResponse();
    }

    /**
     * Update the anthropic settings.
     * 
     * @return void
     */
    public function updateAnthropic()
    {
        $this->verifyNonce();

        $this->validate([
            "api_key" => ["nullable", "string"],
        ]);

        Settings::update($this->request, 'api.anthropic');
        Settings::save();

        $this->emptyResponse();
    }

    /**
     * Update the stability ai settings.
     * 
     * @return void
     */
    public function updateStabilityAI()
    {
        $this->verifyNonce();

        $this->validate([
            "api_key" => ["nullable", "string"],
        ]);

        // validate stability ai api key
        if (!empty($this->input("api_key"))) {

            try {
                $api = new StabilityAiClient($this->input("api_key"));
                $api->account();
            } catch (StabilityAiAuthentificationException $e) {
                $this->response(["message" => $e->getMessage(), "errors" => ['api_key' => [$e->getMessage()]]], 422);
            } catch (Exception $e) {
                $this->response(["message" => "An error occurred", "error" => $e->getMessage()], 503);
            }
        }

        Settings::update($this->request, 'api.stability_ai');
        Settings::save();

        $this->emptyResponse();
    }

    /**
     * Update the ideogram settings.
     * 
     * @return void
     */
    public function updateIdeogram()
    {
        $this->verifyNonce();

        $this->validate([
            "api_key" => ["nullable", "string"],
        ]);

        Settings::update($this->request, 'api.ideogram');
        Settings::save();

        $this->emptyResponse();
    }

    /**
     * Update the Flux settings.
     * 
     * @return void
     */
    public function updateFlux()
    {
        $this->verifyNonce();

        $this->validate([
            "api_key" => ["nullable", "string"],
        ]);

        Settings::update($this->request, 'api.flux');
        Settings::save();

        $this->emptyResponse();
    }

    /**
     * Update the unsplash settings.
     * 
     * @return void
     */
    public function updateUnsplash()
    {
        $this->verifyNonce();

        $this->validate([
            "api_key" => ["nullable", "string"],
        ]);

        Settings::update($this->request, 'api.unsplash');
        Settings::save();

        $this->emptyResponse();
    }

    /**
     * Update the pexels settings.
     * 
     * @return void
     */
    public function updatePexels()
    {
        $this->verifyNonce();

        $this->validate([
            "api_key" => ["nullable", "string"],
        ]);

        Settings::update($this->request, 'api.pexels');
        Settings::save();

        $this->emptyResponse();
    }

    /**
     * Update the pixabay settings.
     * 
     * @return void
     */
    public function updatePixabay()
    {
        $this->verifyNonce();

        $this->validate([
            "api_key" => ["nullable", "string"],
        ]);

        Settings::update($this->request, 'api.pixabay');
        Settings::save();

        $this->emptyResponse();
    }

    /**
     * Update the haloscan settings.
     * 
     * @return void
     */
    public function updateHaloscan()
    {
        $this->verifyNonce();

        $this->validate([
            "api_key" => ["nullable", "string"],
        ]);

        Settings::update($this->request, 'api.haloscan');
        Settings::save();

        $this->emptyResponse();
    }

    /**
     * Update the deepseek settings.
     * 
     * @return void
     */
    public function updateDeepSeek()
    {
        $this->verifyNonce();

        $this->validate([
            "api_key" => ["nullable", "string"],
        ]);

        // validate deepseek api key
        if (!empty($this->input("api_key"))) {
            try {
                $api = new DeepSeekClient($this->input("api_key"));
                $models = $api->listModels();
            } catch (DeepSeekAuthentificationException $e) {
                $this->response(["message" => "Incorrect API key provided", "errors" => ['api_key' => ["Incorrect API key provided"]]], 422);
            } catch (Exception $e) {
                $this->response(["message" => "An error occurred", "error" => $e->getMessage()], 503);
            }
        }

        Settings::update($this->request, 'api.deepseek');
        Settings::save();

        $this->emptyResponse();
    }

    /**
     * Update the gemini settings.
     * 
     * @return void
     */
    public function updateGemini()
    {
        $this->verifyNonce();

        $this->validate([
            "api_key" => ["nullable", "string"],
        ]);

        // validate gemini api key
        if (!empty($this->input("api_key"))) {
            try {
                $api = new GeminiClient($this->input("api_key"));
                $models = $api->listModels();
            } catch (GeminiAuthentificationException $e) {
                $this->response(["message" => "Incorrect API key provided", "errors" => ['api_key' => ["Incorrect API key provided"]]], 422);
            } catch (Exception $e) {
                $this->response(["message" => "An error occurred", "error" => $e->getMessage()], 503);
            }
        }

        Settings::update($this->request, 'api.gemini');
        Settings::save();

        $this->emptyResponse();
    }
}
