package service

import (
	"context"
	"errors"
	"go-server/internal/models"
	"go-server/internal/repository"
	"time"
)

type TodoService struct {
	todoRepo *repository.TodoRepository
}

func NewTodoService(todoRepo *repository.TodoRepository) *TodoService {
	return &TodoService{
		todoRepo: todoRepo,
	}
}

// CreateTodoRequest represents the request to create a new todo
type CreateTodoRequest struct {
	Title       string `json:"title" validate:"required,min=1,max=200"`
	Description string `json:"description" validate:"max=1000"`
	Color       string `json:"color" validate:"required,hexcolor"`
}

// UpdateTodoRequest represents the request to update a todo
type UpdateTodoRequest struct {
	Title       string `json:"title" validate:"required,min=1,max=200"`
	Description string `json:"description" validate:"max=1000"`
	Color       string `json:"color" validate:"required,hexcolor"`
}

// CompleteTodoRequest represents the request to complete a todo
type CompleteTodoRequest struct {
	Description string `json:"description" validate:"max=1000"`
}

// CreateTodo creates a new todo for a user
func (s *TodoService) CreateTodo(ctx context.Context, userID models.ULID, req CreateTodoRequest) (*models.Todo, error) {
	todo := &models.Todo{
		UserID:      userID,
		Title:       req.Title,
		Description: req.Description,
		Color:       req.Color,
		IsActive:    true,
	}

	err := s.todoRepo.CreateTodo(ctx, todo)
	if err != nil {
		return nil, err
	}

	return todo, nil
}

// GetTodosWithStats gets all todos for a user with completion statistics
func (s *TodoService) GetTodosWithStats(ctx context.Context, userID models.ULID) ([]models.TodoWithStats, error) {
	return s.todoRepo.GetTodosWithStats(ctx, userID)
}

// GetTodoByID gets a todo by ID (with user verification)
func (s *TodoService) GetTodoByID(ctx context.Context, todoID, userID models.ULID) (*models.Todo, error) {
	return s.todoRepo.GetTodoByID(ctx, todoID, userID)
}

// UpdateTodo updates a todo
func (s *TodoService) UpdateTodo(ctx context.Context, todoID, userID models.ULID, req UpdateTodoRequest) (*models.Todo, error) {
	todo, err := s.todoRepo.GetTodoByID(ctx, todoID, userID)
	if err != nil {
		return nil, err
	}

	todo.Title = req.Title
	todo.Description = req.Description
	todo.Color = req.Color

	err = s.todoRepo.UpdateTodo(ctx, todo)
	if err != nil {
		return nil, err
	}

	return todo, nil
}

// DeleteTodo deletes (deactivates) a todo
func (s *TodoService) DeleteTodo(ctx context.Context, todoID, userID models.ULID) error {
	return s.todoRepo.DeleteTodo(ctx, todoID, userID)
}

// CompleteTodo marks a todo as completed for today
func (s *TodoService) CompleteTodo(ctx context.Context, todoID, userID models.ULID, req CompleteTodoRequest) error {
	// First check if the todo exists and belongs to the user
	todo, err := s.todoRepo.GetTodoByID(ctx, todoID, userID)
	if err != nil {
		return err
	}

	// Check if already completed today
	completedToday, err := s.todoRepo.CheckTodoCompletedToday(ctx, todoID, userID)
	if err != nil {
		return err
	}

	if completedToday {
		return errors.New("todo already completed today")
	}

	// Create completion record
	completion := &models.TodoCompletion{
		TodoID:      todo.ID,
		UserID:      userID,
		CompletedAt: time.Now(),
		Description: req.Description,
	}

	return s.todoRepo.CompleteTodo(ctx, completion)
}

// GetTodaysSummary gets today's todo summary
func (s *TodoService) GetTodaysSummary(ctx context.Context, userID models.ULID) (*models.DailyTodoSummary, error) {
	todos, err := s.todoRepo.GetTodosWithStats(ctx, userID)
	if err != nil {
		return nil, err
	}

	completedCount := 0
	for _, todo := range todos {
		if todo.CompletedToday {
			completedCount++
		}
	}

	summary := &models.DailyTodoSummary{
		Date:           time.Now(),
		Todos:          todos,
		CompletedCount: completedCount,
		TotalCount:     len(todos),
	}

	return summary, nil
}

// GetActivityLog gets the user's activity log with pagination
func (s *TodoService) GetActivityLog(ctx context.Context, userID models.ULID, limit, offset int) ([]models.TodoCompletion, error) {
	if limit <= 0 {
		limit = 50 // Default limit
	}
	if limit > 200 {
		limit = 200 // Max limit
	}

	return s.todoRepo.GetActivityLog(ctx, userID, limit, offset)
}

// GetActivityLogByDate gets activity log for a specific date
func (s *TodoService) GetActivityLogByDate(ctx context.Context, userID models.ULID, date time.Time) ([]models.TodoCompletion, error) {
	return s.todoRepo.GetActivityLogByDate(ctx, userID, date)
}

// GetWeeklySummary gets a summary of the past 7 days
func (s *TodoService) GetWeeklySummary(ctx context.Context, userID models.ULID) (map[string][]models.TodoCompletion, error) {
	endDate := time.Now().Add(24 * time.Hour)     // Include today
	startDate := endDate.Add(-7 * 24 * time.Hour) // 7 days ago

	completions, err := s.todoRepo.GetCompletionsByDateRange(ctx, userID, startDate, endDate)
	if err != nil {
		return nil, err
	}

	// Group by date
	dailyCompletions := make(map[string][]models.TodoCompletion)
	for _, completion := range completions {
		dateKey := completion.CompletedAt.Format("2006-01-02")
		dailyCompletions[dateKey] = append(dailyCompletions[dateKey], completion)
	}

	return dailyCompletions, nil
}

