package handlers

import (
	"log"
	"net/http"
	"strconv"
	"whatsapp-bot/db"
	"whatsapp-bot/services"

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

// ShowDashboard renders the Chat Interface (Discord View)
// NOTE: The main SaaS Dashboard is now at /dashboard (UserDashboard in saas.go).
// You might want to rename this route to /chat-interface or keep it as a sub-view.
func ShowDashboard(c *gin.Context) {
	userID := c.MustGet("userID").(int)

	// 1. Fetch Appointments (Only for this user)
	type Appt struct {
		ID            int
		CustomerPhone string
		Date          string
		Status        string
	}
	var appts []Appt

	approws, err := db.Conn.Query("SELECT id, customer_phone, appointment_time, status FROM appointments WHERE user_id = ? ORDER BY id DESC", userID)
	if err != nil {
		log.Println("Appt Query Error:", err)
	} else {
		defer approws.Close()
		for approws.Next() {
			var a Appt
			approws.Scan(&a.ID, &a.CustomerPhone, &a.Date, &a.Status)
			appts = append(appts, a)
		}
	}

	// 2. Fetch Chats (Only for this user)
	// We need to add user_id to chats table to make this strict,
	// but for now, we'll assume all chats are visible to the admin/user
	// or filter if you add user_id to the chats table later.
	type Chat struct {
		ID    int
		Title string
	}
	var chats []Chat

	chatrows, err := db.Conn.Query("SELECT id, title FROM chats ORDER BY id DESC")
	if err != nil {
		log.Println("Chat Query Error:", err)
	} else {
		defer chatrows.Close()
		for chatrows.Next() {
			var ch Chat
			chatrows.Scan(&ch.ID, &ch.Title)
			if ch.Title == "" {
				ch.Title = "Chat #" + strconv.Itoa(ch.ID)
			}
			chats = append(chats, ch)
		}
	}

	// 3. Render the Chat Template
	// Note: We are using "dashboard.html" for the SaaS view now.
	// You might want to rename your old chat template to "chat_view.html"
	// if you want to keep both views separate.
	// For now, I'll point this to the new SaaS dashboard template to avoid errors,
	// but realistically you should merge them or have two separate HTML files.
	c.HTML(http.StatusOK, "dashboard.html", gin.H{
		"Appointments": appts,
		"Chats":        chats,
		// Pass minimal context so the template doesn't crash if it expects user info
		"UserEmail": "Chat Mode",
		"Tier":      "Pro",
		"BotConfig": map[string]string{"PhoneID": "N/A"},
	})
}

// POST /admin/appointment
func CreateAppointmentHandler(c *gin.Context) {
	userID := c.MustGet("userID").(int)
	var body struct {
		Phone string `json:"phone"`
		Date  string `json:"date"`
	}
	if err := c.BindJSON(&body); err != nil {
		c.Status(400)
		return
	}

	if err := db.SaveAppointment(userID, body.Phone, body.Date); err != nil {
		c.JSON(500, gin.H{"error": err.Error()})
		return
	}

	c.Status(200)
}

// DELETE /admin/appointment/:id
func DeleteAppointmentHandler(c *gin.Context) {
	id := c.Param("id")
	userID := c.MustGet("userID").(int)

	// Ensure user only deletes their own appointments
	_, err := db.Conn.Exec("DELETE FROM appointments WHERE id = ? AND user_id = ?", id, userID)
	if err != nil {
		c.Status(http.StatusInternalServerError)
		return
	}
	c.Status(http.StatusOK)
}

// PUT /admin/appointment/:id
func UpdateAppointmentHandler(c *gin.Context) {
	id := c.Param("id")
	userID := c.MustGet("userID").(int)
	var body struct {
		Phone string `json:"phone"`
		Date  string `json:"date"`
	}
	if err := c.BindJSON(&body); err != nil {
		c.Status(400)
		return
	}

	_, err := db.Conn.Exec(
		"UPDATE appointments SET customer_phone = ?, appointment_time = ? WHERE id = ? AND user_id = ?",
		body.Phone, body.Date, id, userID,
	)
	if err != nil {
		c.JSON(500, gin.H{"error": err.Error()})
		return
	}
	c.Status(200)
}

// POST /admin/chat
func NewChatHandler(c *gin.Context) {
	// You might want to associate chats with users too: INSERT INTO chats (user_id, title)...
	res, err := db.Conn.Exec("INSERT INTO chats (title) VALUES ('New Chat')")
	if err != nil {
		c.JSON(500, gin.H{"error": err.Error()})
		return
	}
	id, _ := res.LastInsertId()
	c.JSON(200, gin.H{"id": id, "title": "New Chat"})
}

// DELETE /admin/chat/:id
func DeleteChatHandler(c *gin.Context) {
	id := c.Param("id")
	db.Conn.Exec("DELETE FROM messages WHERE chat_id = ?", id)
	db.Conn.Exec("DELETE FROM chats WHERE id = ?", id)
	c.Status(200)
}

// PUT /admin/chat/:id/rename
func RenameChatHandler(c *gin.Context) {
	id := c.Param("id")
	var body struct {
		Title string `json:"title"`
	}
	if err := c.BindJSON(&body); err != nil {
		c.Status(400)
		return
	}
	db.Conn.Exec("UPDATE chats SET title = ? WHERE id = ?", body.Title, id)
	c.Status(200)
}

// GET /admin/chat/:id/messages
func GetMessagesHandler(c *gin.Context) {
	id := c.Param("id")
	rows, _ := db.Conn.Query("SELECT role, content FROM messages WHERE chat_id = ? ORDER BY created_at ASC", id)
	defer rows.Close()

	var msgs []services.Message
	for rows.Next() {
		var m services.Message
		rows.Scan(&m.Role, &m.Content)
		msgs = append(msgs, m)
	}
	c.JSON(200, msgs)
}

// POST /admin/chat/:id/message
func PostMessageHandler(c *gin.Context) {
	chatId := c.Param("id")
	userID := c.MustGet("userID").(int)

	var body struct {
		Content string `json:"content"`
	}
	if err := c.BindJSON(&body); err != nil {
		c.Status(400)
		return
	}

	// 1. Save User Message
	db.Conn.Exec("INSERT INTO messages (chat_id, role, content) VALUES (?, 'user', ?)", chatId, body.Content)

	// 2. Fetch History
	rows, _ := db.Conn.Query("SELECT role, content FROM messages WHERE chat_id = ? ORDER BY created_at ASC", chatId)
	var history []services.Message
	defer rows.Close()
	for rows.Next() {
		var m services.Message
		rows.Scan(&m.Role, &m.Content)
		history = append(history, m)
	}

	// 3. Load User's Custom System Prompt for the AI
	// We need the AI to behave like the User's bot, even in the chat interface
	var systemPrompt string
	err := db.Conn.QueryRow("SELECT system_prompt FROM bot_configs WHERE user_id = ?", userID).Scan(&systemPrompt)
	if err != nil {
		systemPrompt = "You are a helpful assistant." // Fallback
	}

	// 4. Stream Response
	c.Writer.Header().Set("Content-Type", "text/event-stream")
	c.Writer.Header().Set("Cache-Control", "no-cache")
	c.Writer.Header().Set("Connection", "keep-alive")
	c.Writer.Header().Set("Transfer-Encoding", "chunked")

	// We use the new StreamAIResponse signature that takes (userID, message, prompt, callback)
	fullResponse, _ := services.StreamAIResponse(userID, body.Content, systemPrompt, func(chunk string) {
		c.Writer.Write([]byte(chunk))
		c.Writer.Flush()
	})

	// 5. Save Assistant Message
	db.Conn.Exec("INSERT INTO messages (chat_id, role, content) VALUES (?, 'assistant', ?)", chatId, fullResponse)
}
