package litellm

import (
	"bytes"
	"encoding/json"
	"fmt"
	"log"
	"os"
	"strings"

	http "github.com/bogdanfinn/fhttp"

	"github.com/aandrew-me/tgpt/v2/src/client"
	"github.com/aandrew-me/tgpt/v2/src/structs"
)

type RequestBody struct {
	Model    string `json:"model"`
	Stream   bool   `json:"stream"`
	Messages []any  `json:"messages"`
	Tools    []any  `json:"tools,omitempty"`
}

func NewRequest(input string, params structs.Params) (*http.Response, error) {
	client, err := client.NewClient()
	if err != nil {
		fmt.Println(err)
		os.Exit(1)
	}

	model := params.ApiModel
	if model == "" {
		model = os.Getenv("LITELLM_MODEL")
	}
	if model == "" {
		fmt.Println("Error: LiteLLM requires a model to be specified.")
		fmt.Println("LiteLLM is a gateway proxy — the available models depend on your proxy configuration.")
		fmt.Println("Set it via --model flag or LITELLM_MODEL environment variable.")
		fmt.Println("Examples: gpt-4o, anthropic/claude-sonnet-4-6, bedrock/anthropic.claude-3-haiku")
		os.Exit(1)
	}

	apiKey := params.ApiKey
	if apiKey == "" {
		apiKey = os.Getenv("LITELLM_API_KEY")
	}
	if apiKey == "" {
		apiKey = os.Getenv("AI_API_KEY")
	}

	url := params.Url
	if url == "" {
		url = os.Getenv("LITELLM_URL")
	}
	if url == "" {
		url = "http://localhost:4000/v1/chat/completions"
	}

	messages := make([]any, 0, len(params.PrevMessages)+2)
	if params.SystemPrompt != "" {
		messages = append(messages, structs.DefaultMessage{
			Content: params.SystemPrompt,
			Role:    "system",
		})
	}

	requestInfo := RequestBody{
		Model:    model,
		Stream:   true,
		Messages: messages,
		Tools:    params.Tools,
	}

	if len(params.PrevMessages) > 0 {
		requestInfo.Messages = append(requestInfo.Messages, params.PrevMessages...)
	}

	if input != "" {
		requestInfo.Messages = append(requestInfo.Messages, structs.DefaultMessage{
			Role:    "user",
			Content: input,
		})
	}

	jsonRequest, err := json.Marshal(requestInfo)
	if err != nil {
		log.Fatal("Failed to build user request")
	}

	req, err := http.NewRequest("POST", url, bytes.NewBuffer(jsonRequest))
	if err != nil {
		log.Fatal("Some error has occured.\nError:", err)
	}

	req.Header.Set("Content-Type", "application/json")

	if apiKey != "" {
		req.Header.Set("Authorization", "Bearer "+apiKey)
	}

	return client.Do(req)
}

func GetMainText(line string) (mainText string) {
	obj := "{}"
	if after, ok := strings.CutPrefix(line, "data: "); ok {
		obj = after
	}

	var d structs.CommonResponse
	if err := json.Unmarshal([]byte(obj), &d); err != nil {
		return ""
	}

	if len(d.Choices) > 0 {
		return d.Choices[0].Delta.Content
	}
	return ""
}
