package controllers

import (
	"bytes"
	"encoding/json"
	"fmt"
	"io"
	"lost-and-found/internal/utils"
	"net/http"
	"os"

	"github.com/gin-gonic/gin"
	"gorm.io/gorm"
)

type AIMessage struct {
	Role    string `json:"role"`
	Content string `json:"content"`
}

type FrontendMessage struct {
	Text   string `json:"text"`
	Sender string `json:"sender"`
}

type AIController struct {
	DB *gorm.DB
}

func NewAIController(db *gorm.DB) *AIController {
	return &AIController{DB: db}
}

// Groq API structures
type GroqMessage struct {
	Role    string `json:"role"`
	Content string `json:"content"`
}

type GroqRequest struct {
	Model       string        `json:"model"`
	Messages    []GroqMessage `json:"messages"`
	Temperature float64       `json:"temperature,omitempty"`
	MaxTokens   int           `json:"max_tokens,omitempty"`
	TopP        float64       `json:"top_p,omitempty"`
	Stream      bool          `json:"stream"`
}

type GroqResponse struct {
	ID      string `json:"id"`
	Choices []struct {
		Index   int `json:"index"`
		Message struct {
			Role    string `json:"role"`
			Content string `json:"content"`
		} `json:"message"`
		FinishReason string `json:"finish_reason"`
	} `json:"choices"`
	Usage struct {
		PromptTokens     int `json:"prompt_tokens"`
		CompletionTokens int `json:"completion_tokens"`
		TotalTokens      int `json:"total_tokens"`
	} `json:"usage"`
}

func (c *AIController) Chat(ctx *gin.Context) {
	var request struct {
		Message string            `json:"message" binding:"required"`
		History []FrontendMessage `json:"history"`
	}

	if err := ctx.ShouldBindJSON(&request); err != nil {
		utils.ErrorResponse(ctx, http.StatusBadRequest, "Invalid request", err.Error())
		return
	}

	// Get Groq API key from environment
	apiKey := os.Getenv("GROQ_API_KEY")
	if apiKey == "" {
		utils.ErrorResponse(ctx, http.StatusInternalServerError, "Groq API key not configured", "")
		return
	}

	// Get model from environment or use default
	model := os.Getenv("GROQ_MODEL")
	if model == "" {
		model = "llama-3.3-70b-versatile" // Default to best model
	}

	// System prompt for Lost & Found context
	systemPrompt := `Kamu adalah AI Assistant untuk sistem Lost & Found (Barang Hilang & Temuan) bernama "FindItBot".

Konteks Sistem:
- Sistem ini membantu mahasiswa dan staff melaporkan barang hilang dan menemukan barang
- User bisa melaporkan barang hilang mereka
- User bisa melaporkan barang yang mereka temukan
- User bisa klaim barang yang hilang
- Manager dan Admin memverifikasi klaim

Tugasmu:
1. 🔍 Jawab pertanyaan tentang cara menggunakan sistem
2. 📝 Bantu user memahami proses pelaporan dan klaim
3. ✅ Berikan informasi yang jelas dan membantu
4. 💬 Gunakan bahasa Indonesia yang ramah dan profesional
5. 🎯 Fokus pada solusi praktis

Panduan Respons:
- Gunakan emoji yang relevan
- Jawab dengan singkat tapi lengkap
- Jika user mencari barang, tanyakan detail spesifik
- Jika user ingin lapor kehilangan, tanyakan: nama barang, kategori, lokasi, tanggal hilang
- Jika user ingin klaim, jelaskan proses verifikasi

Jawab dengan helpful dan supportive!`

	// Build messages array for Groq
	groqMessages := []GroqMessage{
		{
			Role:    "system",
			Content: systemPrompt,
		},
	}

	// Add conversation history
	for _, msg := range request.History {
		role := "user"
		if msg.Sender == "ai" {
			role = "assistant"
		}
		groqMessages = append(groqMessages, GroqMessage{
			Role:    role,
			Content: msg.Text,
		})
	}

	// Add current user message
	groqMessages = append(groqMessages, GroqMessage{
		Role:    "user",
		Content: request.Message,
	})

	// Prepare Groq request
	groqReq := GroqRequest{
		Model:       model,
		Messages:    groqMessages,
		Temperature: 0.7,
		MaxTokens:   1024,
		TopP:        0.95,
		Stream:      false,
	}

	// Make API call to Groq
	groqURL := "https://api.groq.com/openai/v1/chat/completions"

	jsonData, err := json.Marshal(groqReq)
	if err != nil {
		utils.ErrorResponse(ctx, http.StatusInternalServerError, "Failed to prepare request", err.Error())
		return
	}

	req, err := http.NewRequest("POST", groqURL, bytes.NewBuffer(jsonData))
	if err != nil {
		utils.ErrorResponse(ctx, http.StatusInternalServerError, "Failed to create request", err.Error())
		return
	}

	req.Header.Set("Authorization", "Bearer "+apiKey)
	req.Header.Set("Content-Type", "application/json")

	client := &http.Client{}
	resp, err := client.Do(req)
	if err != nil {
		utils.ErrorResponse(ctx, http.StatusInternalServerError, "Failed to call Groq API", err.Error())
		return
	}
	defer resp.Body.Close()

	body, err := io.ReadAll(resp.Body)
	if err != nil {
		utils.ErrorResponse(ctx, http.StatusInternalServerError, "Failed to read response", err.Error())
		return
	}

	if resp.StatusCode != http.StatusOK {
		utils.ErrorResponse(ctx, http.StatusInternalServerError, 
			fmt.Sprintf("Groq API error (status %d)", resp.StatusCode), string(body))
		return
	}

	var groqResp GroqResponse
	if err := json.Unmarshal(body, &groqResp); err != nil {
		utils.ErrorResponse(ctx, http.StatusInternalServerError, "Failed to parse response", err.Error())
		return
	}

	// Extract AI response
	aiResponse := "Maaf, tidak dapat memproses permintaan Anda."
	if len(groqResp.Choices) > 0 {
		aiResponse = groqResp.Choices[0].Message.Content
	}

	response := AIMessage{
		Role:    "assistant",
		Content: aiResponse,
	}

	utils.SuccessResponse(ctx, http.StatusOK, "AI response generated", gin.H{
		"message":  response,
		"response": aiResponse,
		"model":    model,
		"usage": gin.H{
			"prompt_tokens":     groqResp.Usage.PromptTokens,
			"completion_tokens": groqResp.Usage.CompletionTokens,
			"total_tokens":      groqResp.Usage.TotalTokens,
		},
	})
}

func (c *AIController) GetHistory(ctx *gin.Context) {
	userID, exists := ctx.Get("user_id")
	if !exists {
		utils.ErrorResponse(ctx, http.StatusUnauthorized, "User not authenticated", "")
		return
	}

	// TODO: Implement actual history retrieval from database
	history := []AIMessage{}

	utils.SuccessResponse(ctx, http.StatusOK, "Chat history retrieved", gin.H{
		"user_id": userID,
		"history": history,
		"count":   len(history),
	})
}

func (c *AIController) ClearHistory(ctx *gin.Context) {
	userID, exists := ctx.Get("user_id")
	if !exists {
		utils.ErrorResponse(ctx, http.StatusUnauthorized, "User not authenticated", "")
		return
	}

	// TODO: Implement actual history clearing from database

	utils.SuccessResponse(ctx, http.StatusOK, "Chat history cleared", gin.H{
		"user_id": userID,
		"message": "History successfully deleted",
	})
}