package handlers

import (
	"go-server/internal/models"
	"go-server/internal/service"
	"net/http"
	"strconv"
	"time"

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

type TodoController struct {
	service *service.TodoService
}

func NewTodoController(service *service.TodoService) *TodoController {
	return &TodoController{
		service: service,
	}
}

// CreateTodo creates a new todo
// POST /api/todo/create
func (h *TodoController) CreateTodo(c *gin.Context) {
	userID := getUserIDFromContext(c) // You'll need to implement this helper
	if userID.IsZero() {
		c.JSON(http.StatusUnauthorized, gin.H{"error": "User not authenticated"})
		return
	}

	var req service.CreateTodoRequest
	if err := c.ShouldBindJSON(&req); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid request body"})
		return
	}

	todo, err := h.service.CreateTodo(c.Request.Context(), userID, req)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to create todo"})
		return
	}

	c.JSON(http.StatusCreated, todo)
}

// GetTodos gets all todos with stats for the authenticated user
// GET /api/todo/list
func (h *TodoController) GetTodos(c *gin.Context) {
	userID := getUserIDFromContext(c)
	if userID.IsZero() {
		c.JSON(http.StatusUnauthorized, gin.H{"error": "User not authenticated"})
		return
	}

	todos, err := h.service.GetTodosWithStats(c.Request.Context(), userID)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to get todos"})
		return
	}

	c.JSON(http.StatusOK, todos)
}

// GetTodaysSummary gets today's todo summary
// GET /api/todo/today
func (h *TodoController) GetTodaysSummary(c *gin.Context) {
	userID := getUserIDFromContext(c)
	if userID.IsZero() {
		c.JSON(http.StatusUnauthorized, gin.H{"error": "User not authenticated"})
		return
	}

	summary, err := h.service.GetTodaysSummary(c.Request.Context(), userID)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to get today's summary"})
		return
	}

	c.JSON(http.StatusOK, summary)
}

// UpdateTodo updates a todo
// PUT /api/todo/:id
func (h *TodoController) UpdateTodo(c *gin.Context) {
	userID := getUserIDFromContext(c)
	if userID.IsZero() {
		c.JSON(http.StatusUnauthorized, gin.H{"error": "User not authenticated"})
		return
	}

	todoIDStr := c.Param("id")
	todoID, err := models.ParseULID(todoIDStr)
	if err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid todo ID"})
		return
	}

	var req service.UpdateTodoRequest
	if err := c.ShouldBindJSON(&req); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid request body"})
		return
	}

	todo, err := h.service.UpdateTodo(c.Request.Context(), todoID, userID, req)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to update todo"})
		return
	}

	c.JSON(http.StatusOK, todo)
}

// DeleteTodo deletes a todo
// DELETE /api/todo/:id
func (h *TodoController) DeleteTodo(c *gin.Context) {
	userID := getUserIDFromContext(c)
	if userID.IsZero() {
		c.JSON(http.StatusUnauthorized, gin.H{"error": "User not authenticated"})
		return
	}

	todoIDStr := c.Param("id")
	todoID, err := models.ParseULID(todoIDStr)
	if err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid todo ID"})
		return
	}

	err = h.service.DeleteTodo(c.Request.Context(), todoID, userID)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to delete todo"})
		return
	}

	c.JSON(http.StatusOK, gin.H{"message": "Todo deleted successfully"})
}

// CompleteTodo marks a todo as completed
// POST /api/todo/:id/complete
func (h *TodoController) CompleteTodo(c *gin.Context) {
	userID := getUserIDFromContext(c)
	if userID.IsZero() {
		c.JSON(http.StatusUnauthorized, gin.H{"error": "User not authenticated"})
		return
	}

	todoIDStr := c.Param("id")
	todoID, err := models.ParseULID(todoIDStr)
	if err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid todo ID"})
		return
	}

	var req service.CompleteTodoRequest
	if err := c.ShouldBindJSON(&req); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid request body"})
		return
	}

	err = h.service.CompleteTodo(c.Request.Context(), todoID, userID, req)
	if err != nil {
		if err.Error() == "todo already completed today" {
			c.JSON(http.StatusConflict, gin.H{"error": "Todo already completed today"})
			return
		}
		c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to complete todo"})
		return
	}

	c.JSON(http.StatusOK, gin.H{"message": "Todo completed successfully"})
}

// GetActivityLog gets the user's activity log
// GET /api/todo/activity
func (h *TodoController) GetActivityLog(c *gin.Context) {
	userID := getUserIDFromContext(c)
	if userID.IsZero() {
		c.JSON(http.StatusUnauthorized, gin.H{"error": "User not authenticated"})
		return
	}

	// Parse pagination parameters
	limitStr := c.DefaultQuery("limit", "50")
	offsetStr := c.DefaultQuery("offset", "0")

	limit, err := strconv.Atoi(limitStr)
	if err != nil {
		limit = 50
	}

	offset, err := strconv.Atoi(offsetStr)
	if err != nil {
		offset = 0
	}

	activities, err := h.service.GetActivityLog(c.Request.Context(), userID, limit, offset)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to get activity log"})
		return
	}

	c.JSON(http.StatusOK, activities)
}

// GetActivityLogByDate gets activity log for a specific date
// GET /api/todo/activity/:date
func (h *TodoController) GetActivityLogByDate(c *gin.Context) {
	userID := getUserIDFromContext(c)
	if userID.IsZero() {
		c.JSON(http.StatusUnauthorized, gin.H{"error": "User not authenticated"})
		return
	}

	dateStr := c.Param("date")
	date, err := time.Parse("2006-01-02", dateStr)
	if err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid date format. Use YYYY-MM-DD"})
		return
	}

	activities, err := h.service.GetActivityLogByDate(c.Request.Context(), userID, date)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to get activity log"})
		return
	}

	c.JSON(http.StatusOK, activities)
}

// GetWeeklySummary gets a weekly summary of todo completions
// GET /api/todo/weekly
func (h *TodoController) GetWeeklySummary(c *gin.Context) {
	userID := getUserIDFromContext(c)
	if userID.IsZero() {
		c.JSON(http.StatusUnauthorized, gin.H{"error": "User not authenticated"})
		return
	}

	summary, err := h.service.GetWeeklySummary(c.Request.Context(), userID)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to get weekly summary"})
		return
	}

	c.JSON(http.StatusOK, summary)
}

// Helper function to get user ID from context
// You'll need to implement this based on your authentication middleware
func getUserIDFromContext(c *gin.Context) models.ULID {
	testUserId := models.MustParseULID("01K54QBS528HKQDF985XNW2J6R")
	return testUserId
	// This is a placeholder - implement based on your auth system
	// For example, if you store the user in context after JWT validation:

	// userInterface, exists := c.Get("user")
	// if !exists {
	// 	return models.ULID{} // Return zero value
	// }

	// user, ok := userInterface.(*models.User)
	// if !ok {
	// 	return models.ULID{} // Return zero value
	// }

	// return user.ID
}

