// Package view provides TUI rendering functionality
package view

import (
	"fmt"
	"strings"

	"github.com/charmbracelet/lipgloss"
	"github.com/jfraeys/fetch_ml/cmd/tui/internal/model"
)

const (
	headerfgLight       = "#d35400"
	headerfgDark        = "#ff9e64"
	activeBorderfgLight = "#3498db"
	activeBorderfgDark  = "#7aa2f7"
	errorbgLight        = "#fee"
	errorbgDark         = "#633"
	errorfgLight        = "#a00"
	errorfgDark         = "#faa"
	titlefgLight        = "#d35400"
	titlefgDark         = "#ff9e64"
	statusfgLight       = "#2e3440"
	statusfgDark        = "#d8dee9"
	statusbgLight       = "#e5e9f0"
	statusbgDark        = "#2e3440"
	borderfgLight       = "#d8dee9"
	borderfgDark        = "#4c566a"
	helpfgLight         = "#4c566a"
	helpfgDark          = "#88c0d0"
)

var (
	docStyle = lipgloss.NewStyle().Margin(1, 2)

	activeBorderStyle = lipgloss.NewStyle().
				Border(lipgloss.RoundedBorder()).
				BorderForeground(lipgloss.AdaptiveColor{Light: activeBorderfgLight, Dark: activeBorderfgDark}).
				Padding(1, 2)

	errorStyle = lipgloss.NewStyle().
			Background(lipgloss.AdaptiveColor{Light: errorbgLight, Dark: errorbgDark}).
			Foreground(lipgloss.AdaptiveColor{Light: errorfgLight, Dark: errorfgDark}).
			Padding(0, 1).
			Bold(true)

	titleStyle = (lipgloss.NewStyle().
			Bold(true).
			Foreground(lipgloss.AdaptiveColor{Light: titlefgLight, Dark: titlefgDark}).
			MarginBottom(1))

	statusStyle = (lipgloss.NewStyle().
			Background(lipgloss.AdaptiveColor{Light: statusbgLight, Dark: statusbgDark}).
			Foreground(lipgloss.AdaptiveColor{Light: statusfgLight, Dark: statusfgDark}).
			Padding(0, 1))

	borderStyle = (lipgloss.NewStyle().
			Border(lipgloss.RoundedBorder()).
			BorderForeground(lipgloss.AdaptiveColor{Light: borderfgLight, Dark: borderfgDark}).
			Padding(0, 1))

	helpStyle = (lipgloss.NewStyle().
			Foreground(lipgloss.AdaptiveColor{Light: helpfgLight, Dark: helpfgDark}))
)

// Render renders the TUI view
func Render(m model.State) string {
	if m.Width == 0 {
		return "Loading..."
	}

	// Title
	title := titleStyle.Width(m.Width - 4).Render("🤖 ML Experiment Manager")

	// Left panel - Job list (30% width)
	leftWidth := int(float64(m.Width) * 0.3)
	leftPanel := getJobListPanel(m, leftWidth)

	// Right panel - Dynamic content (70% width)
	rightWidth := m.Width - leftWidth - 4
	rightPanel := getRightPanel(m, rightWidth)

	// Main content
	main := lipgloss.JoinHorizontal(lipgloss.Top, leftPanel, rightPanel)

	// Status bar
	statusBar := getStatusBar(m)

	// Error bar (if present)
	var errorBar string
	if m.ErrorMsg != "" {
		errorBar = errorStyle.Width(m.Width - 4).Render("⚠ Error: " + m.ErrorMsg)
	}

	// Help view (toggleable)
	var helpView string
	if m.ShowHelp {
		helpView = helpStyle.Width(m.Width-4).
			Padding(1, 2).
			Render(helpText(m))
	}

	// Quick help bar
	quickHelp := helpStyle.Width(m.Width - 4).Render(getQuickHelp(m))

	// Compose final layout
	parts := []string{title, main, statusBar}
	if errorBar != "" {
		parts = append(parts, errorBar)
	}
	if helpView != "" {
		parts = append(parts, helpView)
	}
	parts = append(parts, quickHelp)

	return docStyle.Render(lipgloss.JoinVertical(lipgloss.Left, parts...))
}

func getJobListPanel(m model.State, width int) string {
	style := borderStyle
	if m.ActiveView == model.ViewModeJobs {
		style = activeBorderStyle
	}
	// Ensure the job list has proper dimensions to prevent rendering issues
	// Note: We can't modify the model here as it's passed by value,
	// but the View() method of list.Model uses its internal state.
	// Ideally, the controller should have set the size.
	// For now, we assume the controller handles resizing or we act on a copy.
	// But list.Model.SetSize modifies the model.
	// Since we receive 'm' by value, modifications to m.JobList won't persist.
	// However, we need to render it with the correct size.
	// So we can modify our local copy 'm'.
	h, v := style.GetFrameSize()
	m.JobList.SetSize(width-h, m.Height-v-4) // Adjust height for title/help/status

	// Custom empty state
	if len(m.JobList.Items()) == 0 {
		return style.Width(width - h).Render(
			lipgloss.JoinVertical(lipgloss.Left,
				m.JobList.Styles.Title.Render(m.JobList.Title),
				"\n  No jobs found.",
				"  Press 't' to queue.",
			),
		)
	}

	return style.Width(width - h).Render(m.JobList.View())
}

func getRightPanel(m model.State, width int) string {
	var content string
	var viewTitle string
	style := borderStyle

	switch m.ActiveView {
	case model.ViewModeGPU:
		style = activeBorderStyle
		viewTitle = "🎮 GPU Status"
		content = m.GpuView.View()
	case model.ViewModeContainer:
		style = activeBorderStyle
		viewTitle = "🐳 Container Status"
		content = m.ContainerView.View()
	case model.ViewModeQueue:
		style = activeBorderStyle
		viewTitle = "⏳ Task Queue"
		content = m.QueueView.View()
	case model.ViewModeSettings:
		style = activeBorderStyle
		viewTitle = "⚙️ Settings"
		content = m.SettingsView.View()
	case model.ViewModeExperiments:
		style = activeBorderStyle
		viewTitle = "🧪 Experiments"
		content = m.ExperimentsView.View()
	case model.ViewModeJobs:
		style = activeBorderStyle
		viewTitle = "📋 Job Details"
		content = m.JobList.View()
	case model.ViewModeDatasets:
		style = activeBorderStyle
		viewTitle = "📦 Datasets"
		content = m.DatasetView.View()
	case model.ViewModeNarrative:
		style = activeBorderStyle
		viewTitle = "📊 Research Context"
		narrativeView := &NarrativeView{Width: width, Height: m.Height}
		content = narrativeView.View(m.SelectedJob)
	case model.ViewModeTeam:
		style = activeBorderStyle
		viewTitle = "👥 Team Jobs"
		content = "Team collaboration view - shows jobs from all team members\n\n(Requires API: GET /api/jobs?all_users=true)"
	case model.ViewModeExperimentHistory:
		style = activeBorderStyle
		viewTitle = "📜 Experiment History"
		content = m.ExperimentHistoryView.View()
	case model.ViewModeConfig:
		style = activeBorderStyle
		viewTitle = "⚙️ Config"
		content = m.ConfigView.View()
	case model.ViewModeLogs:
		style = activeBorderStyle
		viewTitle = "📜 Logs"
		content = m.LogsView.View()
	default:
		viewTitle = "📊 System Overview"
		content = getOverviewPanel(m)
	}

	header := lipgloss.NewStyle().
		Bold(true).
		Foreground(lipgloss.AdaptiveColor{Light: headerfgLight, Dark: headerfgDark}).
		Render(viewTitle)

	h, _ := style.GetFrameSize()
	return style.Width(width - h).Render(header + "\n\n" + content)
}

func getOverviewPanel(m model.State) string {
	var sections []string

	sections = append(sections, "🎮 GPU\n"+strings.Repeat("─", 40))
	sections = append(sections, m.GpuView.View())
	sections = append(sections, "\n🐳 Containers\n"+strings.Repeat("─", 40))
	sections = append(sections, m.ContainerView.View())

	return strings.Join(sections, "\n")
}

func getStatusBar(m model.State) string {
	spinnerStr := m.Spinner.View()
	if !m.IsLoading {
		if m.ShowHelp {
			spinnerStr = "?"
		} else {
			spinnerStr = "●"
		}
	}
	statusText := m.Status
	if m.ShowHelp {
		statusText = "Press 'h' to hide help"
	}

	// Add refresh rate indicator
	refreshInfo := ""
	if m.RefreshRate > 0 {
		refreshInfo = fmt.Sprintf(" | %.0fms", m.RefreshRate)
	}

	return statusStyle.Width(m.Width - 4).Render(spinnerStr + " " + statusText + refreshInfo)
}

func helpText(m model.State) string {
	if m.ActiveView == model.ViewModeSettings {
		return `╔═══════════════════════════════════════════════════════════════╗
║                     Settings Shortcuts                        ║
╠═══════════════════════════════════════════════════════════════╣
║ Navigation                                                    ║
║   j/k, ↑/↓  : Move selection                                  ║
║   Enter     : Edit / Save                                     ║
║   Esc       : Exit Settings                                   ║
║                                                               ║
║ General                                                       ║
║   h or ?    : Toggle this help  q/Ctrl+C : Quit               ║
╚═══════════════════════════════════════════════════════════════╝`
	}

	return `╔═══════════════════════════════════════════════════════════════╗
║                     Keyboard Shortcuts                        ║
╠═══════════════════════════════════════════════════════════════╣
║ Navigation                                                    ║
║   j/k, ↑/↓  : Move selection    /        : Filter jobs        ║
║   1         : Job list view     2        : Datasets view      ║
║   3         : Experiments view  q        : Queue view         ║
║   g         : GPU view          o        : Container view     ║
║   s         : Settings view     n        : Narrative view     ║
║   m         : Team view         e        : Experiment history ║
║   c         : Config view       l        : Logs (job stream)  ║
║   E         : Export job        @        : Filter by team     ║
║                                                               ║
║ Actions                                                       ║
║   t         : Queue job         a        : Queue w/ args      ║
║   x         : Cancel task       d        : Delete pending     ║
║   f         : Mark as failed    r        : Refresh all        ║
║   G         : Refresh GPU only                                ║
║                                                               ║
║ General                                                       ║
║   h or ?    : Toggle this help  Ctrl+C   : Quit               ║
╚═══════════════════════════════════════════════════════════════╝`
}

func getQuickHelp(m model.State) string {
	if m.ActiveView == model.ViewModeSettings {
		return "  ↑/↓:move  enter:select  esc:exit settings  Ctrl+C:quit"
	}
	return "  h:help  1:jobs  2:datasets  3:experiments q:queue g:gpu o:containers " +
		"n:narrative m:team e:history c:config l:logs E:export @:filter s:settings t:trigger r:refresh Ctrl+C:quit"
}
