package tui

import (
	"strings"

	"gitgud.io/mike/mpv-manager/pkg/config"
	"gitgud.io/mike/mpv-manager/pkg/installer"
	"gitgud.io/mike/mpv-manager/pkg/locale"
	"gitgud.io/mike/mpv-manager/pkg/platform"
	"gitgud.io/mike/mpv-manager/pkg/version"
	"github.com/charmbracelet/bubbles/list"
	"github.com/charmbracelet/bubbles/textinput"
	"github.com/charmbracelet/bubbles/viewport"
	"github.com/charmbracelet/lipgloss"
)

const (
	banner = " ▶ MPV.Rocks"
)

var (
	purple      = lipgloss.Color("#9B59B6")
	lightPurple = lipgloss.Color("#BB8FCE")
	darkPurple  = lipgloss.Color("#6C3483")
	white       = lipgloss.Color("#FFFFFF")
	black       = lipgloss.Color("#000000")
	gray        = lipgloss.Color("#95A5A6")
	green       = lipgloss.Color("#2ECC71")
	blue        = lipgloss.Color("#085dd3")
	red         = lipgloss.Color("#E74C3C")
	yellow      = lipgloss.Color("#F1C40F")
	orange      = lipgloss.Color("#E67E22")

	bannerStyle = lipgloss.NewStyle().
			Foreground(white).
			Background(purple).
			Bold(true)

	titleStyle = lipgloss.NewStyle().
			Foreground(purple).
			Bold(true)

	subtitleStyle = lipgloss.NewStyle().
			Foreground(lightPurple)

	infoStyle = lipgloss.NewStyle().
			Foreground(gray)

	successStyle = lipgloss.NewStyle().
			Foreground(green)

	errorStyle = lipgloss.NewStyle().
			Foreground(red)

	warningStyle = lipgloss.NewStyle().
			Foreground(yellow)

	helpStyle = lipgloss.NewStyle().
			Foreground(gray)

	listStyle = lipgloss.NewStyle().
			Border(lipgloss.RoundedBorder()).
			BorderForeground(purple).
			Padding(1)

	selectedItemStyle = lipgloss.NewStyle().
				Foreground(green).
				Bold(true)

	itemStyle = lipgloss.NewStyle().
			Foreground(white)

	footerStyle = lipgloss.NewStyle().
			Foreground(gray)

	linkStyle = lipgloss.NewStyle().
			Foreground(blue).
			Underline(true)

	recommendedBadgeStyle = lipgloss.NewStyle().
				Foreground(blue).
				Bold(true)

	av2Style    = lipgloss.NewStyle().Foreground(red).Bold(true)
	vvcStyle    = lipgloss.NewStyle().Foreground(blue).Bold(true)
	av1Style    = lipgloss.NewStyle().Foreground(yellow).Bold(true)
	vp9Style    = lipgloss.NewStyle().Foreground(green).Bold(true)
	hevcStyle   = lipgloss.NewStyle().Foreground(blue).Bold(true)
	vp8Style    = lipgloss.NewStyle().Foreground(green).Bold(true)
	proresStyle = lipgloss.NewStyle().Foreground(purple).Bold(true)
	vc1Style    = lipgloss.NewStyle().Foreground(orange).Bold(true)
	avcStyle    = lipgloss.NewStyle().Foreground(red).Bold(true)
	mpeg2Style  = lipgloss.NewStyle().Foreground(purple).Bold(true)
)

var codecDisplayOrder = []string{"av2", "vvc", "av1", "vp9", "hevc", "vp8", "prores", "vc1", "avc", "mpeg2"}

var codecDisplayNames = map[string]string{
	"av2":    "AV2",
	"vvc":    "VVC",
	"av1":    "AV1",
	"vp9":    "VP9",
	"hevc":   "HEVC",
	"vp8":    "VP8",
	"prores": "ProRes",
	"vc1":    "VC-1",
	"avc":    "AVC",
	"mpeg2":  "MPEG-2",
}

var codecStyles = map[string]lipgloss.Style{
	"av2":    av2Style,
	"vvc":    vvcStyle,
	"av1":    av1Style,
	"vp9":    vp9Style,
	"hevc":   hevcStyle,
	"vp8":    vp8Style,
	"prores": proresStyle,
	"vc1":    vc1Style,
	"avc":    avcStyle,
	"mpeg2":  mpeg2Style,
}

type State int

const (
	StateMainMenu State = iota
	StateInstallMenu
	StateInstalling
	StateSuccess
	StateError
	StateUpdateCheck
	StateUpdateInstaller
	StateUpdates
	StateUpdateList
	StateRestoreConfig
	StateUninstall
	StateInstallToPath
	StateLanguagePreferences
	StateLanguageMajorSelect
	StateLanguageRegionSelect
	StateLanguageSelectedList
	StateLanguageConfirm
	StateConfigOptions
	StateHWAOptions
	StateScreenshotOptions
	StateFileAssociations
	StateFileAssociationsMenu
	StateWebUIMenu
	// Screenshot editing sub-states
	StateScreenshotFormatEdit
	StateScreenshotTagColorspaceEdit
	StateScreenshotHighBitDepthEdit
	StateScreenshotTemplateEdit
	StateScreenshotDirectoryEdit
	StateScreenshotJpegQualityEdit
	StateScreenshotPngCompressionEdit
	StateScreenshotWebpLosslessEdit
	StateScreenshotWebpQualityEdit
	StateScreenshotJxlDistanceEdit
	StateScreenshotAvifEncoderEdit
	StateScreenshotAvifPixfmtEdit
	StateScreenshotAvifOptsEdit
	// Additional config editing sub-states
	StateSavePositionOnQuitEdit
	// Hotkeys view
	StateHotkeys
	StateHotkeysCategory
	StateHotkeysPreset // Keybinding preset selection
	StateUISelect      // UI overlay selection state
)

type InstallOperationType int

const (
	OpTypeNone InstallOperationType = iota
	OpTypeInstall
	OpTypeUpdate
	OpTypeConfig
)

type Model struct {
	state        State
	platform     PlatformInfo
	platformInfo *platform.Platform
	installer    *installer.Installer
	methods      []installer.InstallMethod

	menuList              list.Model
	installMenuList       list.Model
	updateList            list.Model
	uninstallList         list.Model
	restoreConfigList     list.Model
	majorLangList         list.Model
	regionLangList        list.Model
	selectedLangList      list.Model
	langPreferenceList    list.Model
	configOptionsList     list.Model
	hwaOptionsList        list.Model
	screenshotOptionsList list.Model
	fileAssociationsList  list.Model
	webUIList             list.Model
	hotkeysList           list.Model
	hotkeysCategoryList   list.Model
	hotkeysPresetList     list.Model
	viewport              viewport.Model
	outputViewport        viewport.Model

	statusMessage           string
	errorMessage            string
	installProgress         int
	showHelp                bool
	showVersion             bool
	selectedMethod          string
	selectedMethodID        string
	installing              bool
	versionCheckResult      *version.VersionCheckResult
	updateCheckResult       *version.UpdateCheckResult
	installOutput           []string
	currentCommand          string
	installComplete         bool
	installError            error
	installSuccess          bool
	loadingConfig           bool
	spinnerFrame            int
	autoScroll              bool
	outputChan              <-chan string
	installDone             <-chan error
	termWidth               int
	termHeight              int
	uninstallItems          []list.Item
	selectedUninstall       *config.InstalledApp
	selectedUpdateItem      *updateItem
	langPreferenceType      string
	currentMajorLanguage    *locale.LocaleEntry
	selectedLanguageCodes   []string
	loadedLocales           []locale.LocaleEntry
	currentMPVAudioLangs    []string
	currentMPVSubtitleLangs []string
	updateItems             []list.Item
	restoreConfigItems      []list.Item
	selectedRestoreBackup   *version.ConfigBackupItem
	installerCheckType      string
	downloadWritten         int64
	downloadTotal           int64
	progressChan            <-chan downloadProgressMsg
	selectedHWAOption       string
	currentHWAValue         string
	installOperationType    InstallOperationType
	postInstallMessage      string
	langSearchTerm          string
	isLangSearching         bool
	langSearchResults       []locale.LanguageOption

	// Screenshot editing fields
	selectedScreenshotOption string
	screenshotTextInput      textinput.Model
	screenshotValueList      list.Model

	// Hotkeys view fields
	hotkeySearchTerm    string
	hotkeySearchResults []hotkeyItem
	presetStatusMessage string // Status message after preset apply

	// UI selection fields
	uiSelectList    list.Model
	pendingMethodID string // Method waiting for UI selection
	pendingAppName  string // App name for display
	selectedUIType  string // Selected UI overlay type
}

// hotkeyItem implements list.Item for hotkey display
type hotkeyItem struct {
	keys        string
	description string
	category    string
}

func (h hotkeyItem) Title() string       { return h.keys }
func (h hotkeyItem) Description() string { return h.description + " (" + h.category + ")" }
func (h hotkeyItem) FilterValue() string { return h.keys + " " + h.description + " " + h.category }

func formatCodecsDisplay(codecs []string) string {
	if len(codecs) == 0 {
		return "Unknown"
	}

	var ordered []string

	for _, codecKey := range codecDisplayOrder {
		for _, detectedCodec := range codecs {
			if strings.ToLower(detectedCodec) == codecKey ||
				strings.ToLower(detectedCodec) == codecKey+"265" ||
				strings.ToLower(detectedCodec) == codecKey+"266" ||
				strings.ToLower(detectedCodec) == "h26"+codecKey[1:] {

				displayName := codecDisplayNames[codecKey]
				style := codecStyles[codecKey]
				ordered = append(ordered, style.Render(displayName))
				break
			}
		}
	}

	if len(ordered) == 0 {
		return "Unknown"
	}

	return strings.Join(ordered, "  ")
}

func getVendorColor(brand string) lipgloss.Style {
	switch strings.ToLower(brand) {
	case "amd":
		return lipgloss.NewStyle().Foreground(red).Bold(true)
	case "nvidia":
		return lipgloss.NewStyle().Foreground(green).Bold(true)
	case "intel":
		return lipgloss.NewStyle().Foreground(blue).Bold(true)
	case "apple":
		return titleStyle
	case "arm", "armel", "qualcomm", "mediatek", "samsung", "hisilicon":
		return lipgloss.NewStyle().Foreground(orange).Bold(true)
	default:
		return infoStyle
	}
}
