package services

import (
	"bufio"
	"bytes"
	"encoding/json"
	"fmt"
	"net/http"
	"os"
	"strings"
	"whatsapp-bot/db"
)

// NOTA: struct Message ya NO está aquí, está en types.go

// StreamAIResponse handles the streaming connection
func StreamAIResponse(userID int, userMessage string, systemPrompt string, onToken func(string)) (string, error) {
	apiKey := os.Getenv("OPENROUTER_API_KEY")
	url := "https://openrouter.ai/api/v1/chat/completions"

	messages := []map[string]string{
		{"role": "system", "content": systemPrompt},
		{"role": "user", "content": userMessage},
	}

	payload := map[string]interface{}{
		"model":    "arcee-ai/trinity-large-preview:free", //stepfun/step-3.5-flash:free
		"messages": messages,
		"stream":   true,
		"tools": []map[string]interface{}{
			{
				"type": "function",
				"function": map[string]interface{}{
					"name":        "create_appointment",
					"description": "Schedules a new appointment. ONLY use when you have date, time, and phone.",
					"parameters": map[string]interface{}{
						"type": "object",
						"properties": map[string]interface{}{
							"customer_phone": map[string]string{"type": "string"},
							"date":           map[string]string{"type": "string"},
						},
						"required": []string{"customer_phone", "date"},
					},
				},
			},
		},
	}

	jsonData, _ := json.Marshal(payload)
	req, _ := http.NewRequest("POST", url, bytes.NewBuffer(jsonData))
	req.Header.Set("Authorization", "Bearer "+apiKey)
	req.Header.Set("Content-Type", "application/json")

	client := &http.Client{}
	resp, err := client.Do(req)
	if err != nil {
		return "", err
	}
	defer resp.Body.Close()

	scanner := bufio.NewScanner(resp.Body)
	var fullContentBuffer strings.Builder
	var toolCallBuffer strings.Builder
	var toolName string
	isToolCall := false

	for scanner.Scan() {
		line := scanner.Text()
		if !strings.HasPrefix(line, "data: ") {
			continue
		}
		jsonStr := strings.TrimPrefix(line, "data: ")
		if jsonStr == "[DONE]" {
			break
		}

		var chunk struct {
			Choices []struct {
				Delta struct {
					Content   string `json:"content"`
					ToolCalls []struct {
						Function struct {
							Name      string `json:"name"`
							Arguments string `json:"arguments"`
						} `json:"function"`
					} `json:"tool_calls"`
				} `json:"delta"`
			} `json:"choices"`
		}
		json.Unmarshal([]byte(jsonStr), &chunk)

		if len(chunk.Choices) > 0 {
			delta := chunk.Choices[0].Delta
			if delta.Content != "" {
				fullContentBuffer.WriteString(delta.Content)
				if onToken != nil {
					onToken(delta.Content)
				}
			}
			if len(delta.ToolCalls) > 0 {
				isToolCall = true
				if delta.ToolCalls[0].Function.Name != "" {
					toolName = delta.ToolCalls[0].Function.Name
				}
				toolCallBuffer.WriteString(delta.ToolCalls[0].Function.Arguments)
			}
		}
	}

	// EXECUTE TOOL
	if isToolCall && toolName == "create_appointment" {
		var args struct {
			Phone string `json:"customer_phone"`
			Date  string `json:"date"`
		}
		if err := json.Unmarshal([]byte(toolCallBuffer.String()), &args); err == nil {
			err := db.SaveAppointment(userID, args.Phone, args.Date)
			resultMsg := ""
			if err != nil {
				resultMsg = "\n(System: Failed to book appointment)"
			} else {
				resultMsg = fmt.Sprintf("\n✅ Appointment Confirmed: %s", args.Date)
			}
			fullContentBuffer.WriteString(resultMsg)
			if onToken != nil {
				onToken(resultMsg)
			}
		}
	}

	return fullContentBuffer.String(), nil
}
