// Package safety provides anti-detection measures: session timing,
// break scheduling, and behavioral pattern randomization.
package safety

import (
	"math/rand"
	"time"
)

// SessionConfig defines play session parameters.
type SessionConfig struct {
	MinSessionHours  float64
	MaxSessionHours  float64
	MinBreakMinutes  float64
	MaxBreakMinutes  float64
	MaxDailyHours    float64
	MicroBreakMinSec int
	MicroBreakMaxSec int
	MicroBreakIntervalMinSec int
	MicroBreakIntervalMaxSec int
}

// DefaultSessionConfig returns realistic session timing.
func DefaultSessionConfig() SessionConfig {
	return SessionConfig{
		MinSessionHours:          1.0,
		MaxSessionHours:          4.0,
		MinBreakMinutes:          10.0,
		MaxBreakMinutes:          45.0,
		MaxDailyHours:            12.0,
		MicroBreakMinSec:         2,
		MicroBreakMaxSec:         8,
		MicroBreakIntervalMinSec: 120,
		MicroBreakIntervalMaxSec: 300,
	}
}

// SessionTimer manages play session duration and breaks.
type SessionTimer struct {
	config         SessionConfig
	sessionStart   time.Time
	dailyPlaytime  time.Duration
	targetDuration time.Duration
	nextMicroBreak time.Time
}

// NewSessionTimer creates a session timer.
func NewSessionTimer(config SessionConfig) *SessionTimer {
	st := &SessionTimer{
		config:       config,
		sessionStart: time.Now(),
	}
	st.targetDuration = st.rollSessionDuration()
	st.nextMicroBreak = st.scheduleMicroBreak()
	return st
}

// ShouldStopSession returns true if the current session should end.
func (s *SessionTimer) ShouldStopSession() bool {
	elapsed := time.Since(s.sessionStart)
	if elapsed >= s.targetDuration {
		return true
	}
	if s.dailyPlaytime+elapsed >= time.Duration(s.config.MaxDailyHours*float64(time.Hour)) {
		return true
	}
	return false
}

// ShouldMicroBreak returns the break duration if it's time, or 0.
func (s *SessionTimer) ShouldMicroBreak() time.Duration {
	if time.Now().After(s.nextMicroBreak) {
		duration := time.Duration(s.config.MicroBreakMinSec+rand.Intn(s.config.MicroBreakMaxSec-s.config.MicroBreakMinSec+1)) * time.Second
		s.nextMicroBreak = s.scheduleMicroBreak()
		return duration
	}
	return 0
}

// BreakDuration returns a randomized long break duration.
func (s *SessionTimer) BreakDuration() time.Duration {
	minMs := int(s.config.MinBreakMinutes * 60 * 1000)
	maxMs := int(s.config.MaxBreakMinutes * 60 * 1000)
	return time.Duration(minMs+rand.Intn(maxMs-minMs)) * time.Millisecond
}

// StartNewSession resets for a new play session.
func (s *SessionTimer) StartNewSession() {
	s.dailyPlaytime += time.Since(s.sessionStart)
	s.sessionStart = time.Now()
	s.targetDuration = s.rollSessionDuration()
}

// Elapsed returns time in current session.
func (s *SessionTimer) Elapsed() time.Duration {
	return time.Since(s.sessionStart)
}

func (s *SessionTimer) rollSessionDuration() time.Duration {
	minMs := int(s.config.MinSessionHours * 3600 * 1000)
	maxMs := int(s.config.MaxSessionHours * 3600 * 1000)
	return time.Duration(minMs+rand.Intn(maxMs-minMs)) * time.Millisecond
}

func (s *SessionTimer) scheduleMicroBreak() time.Time {
	interval := s.config.MicroBreakIntervalMinSec + rand.Intn(s.config.MicroBreakIntervalMaxSec-s.config.MicroBreakIntervalMinSec+1)
	return time.Now().Add(time.Duration(interval) * time.Second)
}
