"use strict";

import {__} from "@wordpress/i18n";
import OpenAI from "openai";

export default class DeepSeek {
    /**
     * API client credentials
     * @type {{baseURL: string|null, apiKey: string|null, organization: string|null, project: string|null, model: string|null}}
     */
    #credentials = {
        baseURL: null,
        apiKey: null,
        organization: null,
        project: null,
        model: null,
    };

    /**
     * API client
     *
     * @type {OpenAI|null}
     */
    #client = null;

    /**
     * Construct
     *
     * @param {string} base_url API base URL
     * @param {string} apiKey API key
     * @param {string} organization API client organization
     * @param {string} project API client project
     * @param {string} model AI client model
     */
    constructor({baseUrl = "https://api.deepseek.com", apiKey, organization, project, model}) {
        /**
         * Init properties
         */
        this.#credentials.baseURL = baseUrl;
        this.#credentials.apiKey = apiKey;
        this.#credentials.organization = organization;
        this.#credentials.project = project;
        this.#credentials.model = model;
        // Init API client
        this.#initApiClient();
    }

    /**
     * Initialize the API client
     */
    #initApiClient() {
        // Set configs to init the AI
        const config = {
            apiKey: this.#credentials.apiKey,
        };
        // Base URL
        if (this.#credentials.baseURL) {
            config.baseURL = this.#credentials.baseURL;
        }
        // Organization
        if (this.#credentials.organization) {
            config.organization = this.#credentials.organization;
        }
        // Project
        if (this.#credentials.project) {
            config.project = this.#credentials.project;
        }
        // Init API client
        this.#client = new OpenAI({
            ...config,
            dangerouslyAllowBrowser: true
        });
    }

    /**
     * Is the API client initialized successfully
     *
     * @returns {boolean}
     */
    isApiClientInitialized() {
        return !!this.#client;
    }

    /**
     * Generate content
     *
     * @param {string} systemInfo AI description
     * @param {string} prompt Request
     * @returns {{status: boolean,data: string}}
     */
    async generateContent({systemInfo = "You are a helpful assistant.", prompt}) {
        try {
            const result = await this.chatCompletion({systemInfo, content: prompt});
            return {
                status: result.status,
                data: result.status ? result.data?.message.content : result.data
            };
        } catch (e) {
            return {
                status: false,
                data: e.message
            };
        }
    }

    /**
     * The chat completion endpoint request
     *
     * @param {string} role Role
     * @param {string} content Content
     * @returns {Promise<ChatCompletion.Choice>|null}
     */
    async chatCompletion({systemInfo = "You are a helpful assistant.", content}) {
        try {
            if (!this.isApiClientInitialized()) {
                return {
                    status: false,
                    data: __("The DeepSeek API client isn't initialized.", 'limb-chatbot')
                };
            }
            const completion = await this.#client.chat.completions.create({
                messages: [
                    {role: "system", content: systemInfo},
                    {role: "user", content},
                ],
                model: this.#credentials.model,
            });

            // TODO: track usage
            // {
            //     "choices": [...]
            //     "id":"chatcmpl-7QyqpwdfhqwajicIEznoc6Q47XAyW",
            //     "model":"gpt-4o-mini",
            //     "object":"chat.completion",
            //     "usage":{
            //         "completion_tokens":17,
            //         "prompt_tokens":57,
            //         "total_tokens":74
            //     }
            // }

            return {
                status: true,
                data: completion.choices[0]
            };
        } catch (e) {
            return {
                status: false,
                data: e.message
            };
        }
    }

    /**
     * The embedding endpoint request
     *
     * @param {string} model Model
     * @param {string} input Input
     * @returns {Promise<CreateEmbeddingResponse>}
     */
    async embedding({model = 'text-embedding-ada-002', input}) {
        try {
            const embedding = await this.#client.embeddings.create({model, input});

            return embedding;
        } catch (e) {
            console.error(e);
        }
    }

    /**
     * The image endpoint request
     *
     * @param {string} prompt Prompt
     * @returns {Promise<Array<Image>>}
     */
    async image({prompt}) {
        try {
            const image = await this.#client.images.generate({prompt});

            return image.data;
        } catch (e) {
            console.error(e);
        }
    }
}
