// Package state provides game state machine management with event callbacks.
package state

import (
	"image"
	"sync"
	"time"

	"git.cloonar.com/openclawd/iso-bot/pkg/plugin"
)

// Transition records a state change.
type Transition struct {
	From      plugin.GameState
	To        plugin.GameState
	Timestamp time.Time
}

// Manager tracks game state and fires callbacks on transitions.
type Manager struct {
	mu           sync.RWMutex
	current      plugin.GameState
	previous     plugin.GameState
	enterTime    time.Time
	history      []Transition
	callbacks    map[plugin.GameState][]func(Transition)
	detector     plugin.GameDetector
}

// NewManager creates a state manager with the given detector.
func NewManager(detector plugin.GameDetector) *Manager {
	return &Manager{
		current:   plugin.StateUnknown,
		enterTime: time.Now(),
		callbacks: make(map[plugin.GameState][]func(Transition)),
		detector:  detector,
	}
}

// Update analyzes the current frame and updates state.
func (m *Manager) Update(frame image.Image) plugin.GameState {
	newState := m.detector.DetectState(frame)

	m.mu.Lock()
	defer m.mu.Unlock()

	if newState != m.current {
		t := Transition{
			From:      m.current,
			To:        newState,
			Timestamp: time.Now(),
		}
		m.history = append(m.history, t)
		m.previous = m.current
		m.current = newState
		m.enterTime = time.Now()

		// Fire callbacks outside lock? For simplicity, keep in lock for now.
		for _, cb := range m.callbacks[newState] {
			cb(t)
		}
	}

	return m.current
}

// Current returns the current game state.
func (m *Manager) Current() plugin.GameState {
	m.mu.RLock()
	defer m.mu.RUnlock()
	return m.current
}

// TimeInState returns how long we've been in the current state.
func (m *Manager) TimeInState() time.Duration {
	m.mu.RLock()
	defer m.mu.RUnlock()
	return time.Since(m.enterTime)
}

// OnState registers a callback for entering a specific state.
func (m *Manager) OnState(state plugin.GameState, cb func(Transition)) {
	m.mu.Lock()
	defer m.mu.Unlock()
	m.callbacks[state] = append(m.callbacks[state], cb)
}
