// Package model provides TUI data structures and state management
package model

import (
	"time"

	"github.com/charmbracelet/bubbles/list"
	"github.com/charmbracelet/bubbles/spinner"
	"github.com/charmbracelet/bubbles/textinput"
	"github.com/charmbracelet/bubbles/viewport"
	"github.com/jfraeys/fetch_ml/internal/domain"
)

// Re-export domain types for TUI use
// Task represents a task in the TUI
type Task = domain.Task

// TrackingConfig specifies experiment tracking tools
type TrackingConfig = domain.TrackingConfig

// MLflowTrackingConfig controls MLflow integration
type MLflowTrackingConfig = domain.MLflowTrackingConfig

// TensorBoardTrackingConfig controls TensorBoard integration
type TensorBoardTrackingConfig = domain.TensorBoardTrackingConfig

// WandbTrackingConfig controls Weights & Biases integration
type WandbTrackingConfig = domain.WandbTrackingConfig

// ViewMode represents the current view mode in the TUI
type ViewMode int

// ViewMode constants represent different TUI views
const (
	ViewModeJobs              ViewMode = iota // Jobs view mode
	ViewModeGPU                               // GPU status view mode
	ViewModeQueue                             // Queue status view mode
	ViewModeContainer                         // Container status view mode
	ViewModeSettings                          // Settings view mode
	ViewModeDatasets                          // Datasets view mode
	ViewModeExperiments                       // Experiments view mode
	ViewModeNarrative                         // Narrative/Outcome view mode
	ViewModeTeam                              // Team collaboration view mode
	ViewModeExperimentHistory                 // Experiment history view mode
	ViewModeConfig                            // Config view mode
	ViewModeLogs                              // Logs streaming view mode
)

// DatasetInfo represents dataset information in the TUI
type DatasetInfo struct {
	Name       string    `json:"name"`
	SizeBytes  int64     `json:"size_bytes"`
	Location   string    `json:"location"`
	LastAccess time.Time `json:"last_access"`
}

// State holds the application state
type State struct {
	Jobs                  []Job
	QueuedTasks           []*Task
	Datasets              []DatasetInfo
	JobList               list.Model
	GpuView               viewport.Model
	ContainerView         viewport.Model
	QueueView             viewport.Model
	SettingsView          viewport.Model
	DatasetView           viewport.Model
	ExperimentsView       viewport.Model
	NarrativeView         viewport.Model
	TeamView              viewport.Model
	ExperimentHistoryView viewport.Model
	ConfigView            viewport.Model
	LogsView              viewport.Model
	SelectedJob           Job
	Input                 textinput.Model
	APIKeyInput           textinput.Model
	Status                string
	ErrorMsg              string
	InputMode             bool
	Width                 int
	Height                int
	ShowHelp              bool
	Spinner               spinner.Model
	ActiveView            ViewMode
	LastRefresh           time.Time
	LastFrameTime         time.Time
	RefreshRate           float64 // measured in ms
	FrameCount            int
	LastGPUUpdate         time.Time
	IsLoading             bool
	JobStats              map[JobStatus]int
	APIKey                string
	SettingsIndex         int
	Keys                  KeyMap
}

// InitialState creates the initial application state
func InitialState(apiKey string) State {
	items := []list.Item{}
	delegate := NewJobListDelegate()
	jobList := list.New(items, delegate, 0, 0)
	jobList.Title = "ML Jobs & Queue"
	jobList.SetShowStatusBar(true)
	jobList.SetFilteringEnabled(true)
	jobList.SetShowHelp(false)
	jobList.Styles.Title = JobListTitleStyle()

	input := textinput.New()
	input.Placeholder = "Args: --epochs 100 --lr 0.001 --priority 5"
	input.Width = 60
	input.CharLimit = 200

	apiKeyInput := textinput.New()
	apiKeyInput.Placeholder = "Enter API key..."
	apiKeyInput.Width = 40
	apiKeyInput.CharLimit = 200

	s := spinner.New()
	s.Spinner = spinner.Dot
	s.Style = SpinnerStyle()

	return State{
		JobList:               jobList,
		GpuView:               viewport.New(0, 0),
		ContainerView:         viewport.New(0, 0),
		QueueView:             viewport.New(0, 0),
		SettingsView:          viewport.New(0, 0),
		DatasetView:           viewport.New(0, 0),
		ExperimentsView:       viewport.New(0, 0),
		NarrativeView:         viewport.New(0, 0),
		TeamView:              viewport.New(0, 0),
		ExperimentHistoryView: viewport.New(0, 0),
		ConfigView:            viewport.New(0, 0),
		LogsView:              viewport.New(0, 0),
		Input:                 input,
		APIKeyInput:           apiKeyInput,
		Status:                "Connected",
		InputMode:             false,
		ShowHelp:              false,
		Spinner:               s,
		ActiveView:            ViewModeJobs,
		LastRefresh:           time.Now(),
		IsLoading:             false,
		JobStats:              make(map[JobStatus]int),
		APIKey:                apiKey,
		SettingsIndex:         0,
		Keys:                  DefaultKeys(),
	}
}

// LogMsg represents a log line from a job
type LogMsg struct {
	JobName string `json:"job_name"`
	Line    string `json:"line"`
	Time    string `json:"time"`
}

// JobUpdateMsg represents a real-time job status update via WebSocket
type JobUpdateMsg struct {
	JobName  string `json:"job_name"`
	Status   string `json:"status"`
	TaskID   string `json:"task_id"`
	Progress int    `json:"progress"`
}

// GPUUpdateMsg represents a real-time GPU status update via WebSocket
type GPUUpdateMsg struct {
	DeviceID    int   `json:"device_id"`
	Utilization int   `json:"utilization"`
	MemoryUsed  int64 `json:"memory_used"`
	MemoryTotal int64 `json:"memory_total"`
	Temperature int   `json:"temperature"`
}
