package counter

import (
	"context"
	"time"

	"counter/internal/domain/entities"
	"counter/internal/domain/repositories"
)

// CounterService handles counter business logic
type CounterService struct {
	counterRepo repositories.CounterRepository
}

// NewCounterService creates a new counter service
func NewCounterService(counterRepo repositories.CounterRepository) *CounterService {
	return &CounterService{
		counterRepo: counterRepo,
	}
}

// CreateCounterRequest represents a counter creation request
type CreateCounterRequest struct {
	Name        string `json:"name" binding:"required,min=1,max=100"`
	Description string `json:"description" max:"500"`
}

// UpdateCounterRequest represents a counter update request
type UpdateCounterRequest struct {
	Name        string `json:"name" binding:"required,min=1,max=100"`
	Description string `json:"description" max:"500"`
}

// IncrementRequest represents a counter increment request
type IncrementRequest struct {
	Value int `json:"value" binding:"required"`
}

// Create creates a new counter
func (s *CounterService) Create(ctx context.Context, userID int, req *CreateCounterRequest) (*entities.Counter, error) {
	counter := &entities.Counter{
		UserID:      userID,
		Name:        req.Name,
		Description: req.Description,
	}

	if err := counter.Validate(); err != nil {
		return nil, err
	}

	if err := s.counterRepo.Create(ctx, counter); err != nil {
		return nil, err
	}

	return counter, nil
}

// Get retrieves a counter by ID
func (s *CounterService) Get(ctx context.Context, counterID, userID int) (*entities.CounterWithStats, error) {
	return s.counterRepo.FindByID(ctx, counterID, userID)
}

// List retrieves all counters for a user
func (s *CounterService) List(ctx context.Context, userID int, search string) ([]*entities.CounterWithStats, error) {
	return s.counterRepo.FindByUserID(ctx, userID, search)
}

// Update updates a counter
func (s *CounterService) Update(ctx context.Context, counterID, userID int, req *UpdateCounterRequest) (*entities.Counter, error) {
	counter := &entities.Counter{
		ID:          counterID,
		UserID:      userID,
		Name:        req.Name,
		Description: req.Description,
	}

	if err := counter.Validate(); err != nil {
		return nil, err
	}

	if err := s.counterRepo.Update(ctx, counter); err != nil {
		return nil, err
	}

	return counter, nil
}

// Delete deletes a counter
func (s *CounterService) Delete(ctx context.Context, counterID, userID int) error {
	return s.counterRepo.Delete(ctx, counterID, userID)
}

// Increment increments/decrements a counter
func (s *CounterService) Increment(ctx context.Context, counterID, userID int, req *IncrementRequest) (*entities.CounterEntry, error) {
	// Verify counter exists and belongs to user
	exists, err := s.counterRepo.Exists(ctx, counterID, userID)
	if err != nil {
		return nil, err
	}
	if !exists {
		return nil, entities.ErrCounterNotFound
	}

	entry := &entities.CounterEntry{
		CounterID: counterID,
		Value:     req.Value,
		Date:      time.Now().Truncate(24 * time.Hour), // Truncate to date only
	}

	if err := entry.Validate(); err != nil {
		return nil, err
	}

	if err := s.counterRepo.AddEntry(ctx, entry); err != nil {
		return nil, err
	}

	return entry, nil
}

// GetEntries retrieves entries for a counter
func (s *CounterService) GetEntries(ctx context.Context, counterID, userID int, startDate, endDate *time.Time) ([]*entities.CounterEntry, error) {
	return s.counterRepo.GetEntries(ctx, counterID, userID, startDate, endDate)
}

// GetStats retrieves statistics for a counter
func (s *CounterService) GetStats(ctx context.Context, counterID, userID int, days int) ([]*entities.DailyStat, error) {
	if days <= 0 {
		days = 30 // Default to 30 days
	}
	return s.counterRepo.GetDailyStats(ctx, counterID, userID, days)
}
