// The usual utils files with some functions
// I do plan to change the markdownToHTML and addCopyButtonsToCode
// I will take example on openai and gemini and put a header on top of a code part with the button instead of inside
package main

import (
	"bytes"
	"fmt"
	"regexp"

	"github.com/yuin/goldmark"
	highlighting "github.com/yuin/goldmark-highlighting"
)

func markdownToHTML(markdownText string) string {
	var buf bytes.Buffer
	md := goldmark.New(
		goldmark.WithExtensions(
			highlighting.NewHighlighting(highlighting.WithStyle("monokai")),
		),
	)
	if err := md.Convert([]byte(markdownText), &buf); err != nil {
		fmt.Println("failed to convert markdown to HTML")
		panic(err)
	}

	return addCopyButtonsToCode(buf.String())
}

func addCopyButtonsToCode(htmlContent string) string {
	buttonHTML := `<button class="copy-button button is-small is-primary is-outlined" onclick="copyToClipboardCode(this)"><i class="fa-solid fa-copy"></i></button>`

	// Regular expression pattern to match <pre> elements and insert the button right before <code>
	pattern := `(<pre[^>]*>)`

	// Compile the regular expression
	re := regexp.MustCompile(pattern)

	// Replace each matched <pre> element with the updated HTML
	updatedHTML := re.ReplaceAllString(htmlContent, "$1"+buttonHTML)

	return updatedHTML
}

func getExistingKeys() (bool, bool, bool, bool, bool, bool) {
	if edgeClient == nil {
		return false, false, false, false, false, false
	}

	var (
		openaiExists    bool
		anthropicExists bool
		mistralExists   bool
		groqExists      bool
		gooseaiExists   bool
		googleExists    bool
	)

	err := edgeClient.QuerySingle(edgeCtx, `
	select exists (
		select global currentUser.setting.keys
		filter .company.name = "openai"
	  );
	`, &openaiExists)
	if err != nil {
		fmt.Println("Error checking if OpenAI key exists")
		panic(err)
	}

	err = edgeClient.QuerySingle(edgeCtx, `
	select exists (
		select global currentUser.setting.keys
		filter .company.name = "anthropic"
	);
	`, &anthropicExists)
	if err != nil {
		fmt.Println("Error checking if Anthropic key exists")
		panic(err)
	}

	err = edgeClient.QuerySingle(edgeCtx, `
	select exists (
		select global currentUser.setting.keys
		filter .company.name = "mistral"
	);
	`, &mistralExists)
	if err != nil {
		fmt.Println("Error checking if Mistral key exists")
		panic(err)
	}

	err = edgeClient.QuerySingle(edgeCtx, `
	select exists (
		select global currentUser.setting.keys
		filter .company.name = "groq"
	);
	`, &groqExists)
	if err != nil {
		fmt.Println("Error checking if Groq key exists")
		panic(err)
	}

	err = edgeClient.QuerySingle(edgeCtx, `
	select exists (
		select global currentUser.setting.keys
		filter .company.name = "gooseai"
	);
	`, &gooseaiExists)
	if err != nil {
		fmt.Println("Error checking if GooseAI key exists")
		panic(err)
	}

	err = edgeClient.QuerySingle(edgeCtx, `
	select exists (
		select global currentUser.setting.keys
		filter .company.name = "google"
	);
	`, &googleExists)
	if err != nil {
		fmt.Println("Error checking if Google key exists")
		panic(err)
	}

	return openaiExists, anthropicExists, mistralExists, groqExists, gooseaiExists, googleExists
}

func Message2RequestMessage(messages []Message, context string) []RequestMessage {
	// Add context if it exists
	if context != "" {
		m := make([]RequestMessage, len(messages)+1)
		m[0] = RequestMessage{
			Role:    "system",
			Content: context,
		}

		for i, msg := range messages {
			var role string
			switch msg.Role {
			case "user":
				role = "user"
			case "bot":
				role = "assistant"
			default:
				role = "system"
			}
			m[i+1] = RequestMessage{
				Role:    role,
				Content: msg.Content,
			}
		}
		return m
	} else {
		m := make([]RequestMessage, len(messages))

		for i, msg := range messages {
			var role string
			switch msg.Role {
			case "user":
				role = "user"
			case "bot":
				role = "assistant"
			default:
				role = "system"
			}
			m[i] = RequestMessage{
				Role:    role,
				Content: msg.Content,
			}
		}
		return m
	}
}

func GetAvailableModels() []ModelInfo {
	// TODO Filter if key is not available
	var models []ModelInfo
	err := edgeClient.Query(edgeCtx, `
		SELECT ModelInfo {
			modelID,
			name,
			company : {
				name,
				icon
			}
		} FILTER .modelID != 'none' AND .company.name != 'huggingface' AND .company IN global currentUser.setting.keys.company
	`, &models)
	if err != nil {
		fmt.Println("Error getting models")
		panic(err)
	}
	return models
}
