package tui

import (
	"sort"
	"strings"

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

func (m *Model) Init() tea.Cmd {
	return checkForUpdateCmd()
}

func NewModel() *Model {
	platformInfo := PlatformInfo{
		AppVersion:   "",
		OSType:       "Detecting...",
		Arch:         "Detecting...",
		Distro:       "",
		DistroFamily: "",
		CPU:          "Detecting...",
		GPU:          "Detecting...",
		HWA:          "auto",
	}

	outputViewport := viewport.New(0, 0)
	outputViewport.Style = lipgloss.NewStyle()

	delegate := list.NewDefaultDelegate()
	delegate.ShowDescription = true
	delegate.Styles.SelectedTitle = selectedItemStyle
	delegate.Styles.SelectedDesc = infoStyle

	// Initialize textinput for screenshot string options
	ti := textinput.New()
	ti.Placeholder = "Enter value..."
	ti.CharLimit = 156
	ti.Width = 50

	return &Model{
		state:                 StateMainMenu,
		platform:              platformInfo,
		menuList:              list.New(nil, list.NewDefaultDelegate(), 0, 0),
		installMenuList:       list.New(nil, list.NewDefaultDelegate(), 0, 0),
		uninstallList:         list.New(nil, delegate, 0, 0),
		updateList:            list.New(nil, list.NewDefaultDelegate(), 0, 0),
		restoreConfigList:     list.New(nil, list.NewDefaultDelegate(), 0, 0),
		outputViewport:        outputViewport,
		statusMessage:         "Initializing...",
		installOutput:         []string{},
		autoScroll:            true,
		majorLangList:         list.New(nil, list.NewDefaultDelegate(), 0, 0),
		regionLangList:        list.New(nil, list.NewDefaultDelegate(), 0, 0),
		selectedLangList:      list.New(nil, list.NewDefaultDelegate(), 0, 0),
		langPreferenceList:    list.New(nil, list.NewDefaultDelegate(), 0, 0),
		configOptionsList:     list.New(nil, list.NewDefaultDelegate(), 0, 0),
		hwaOptionsList:        list.New(nil, list.NewDefaultDelegate(), 0, 0),
		webUIList:             list.New(nil, list.NewDefaultDelegate(), 0, 0),
		screenshotOptionsList: list.New(nil, list.NewDefaultDelegate(), 0, 0),
		uiSelectList:          list.New(nil, list.NewDefaultDelegate(), 0, 0),
		installerCheckType:    "",
		screenshotTextInput:   ti,
		screenshotValueList:   list.New(nil, list.NewDefaultDelegate(), 0, 0),
	}
}

func (m *Model) SetPlatform(info PlatformInfo) {
	m.platform = info
}

func NewMenuItemsFromInstaller(methods []installer.InstallMethod) []menuItem {
	items := make([]menuItem, len(methods))
	for i, method := range methods {
		items[i] = menuItem{
			id:          method.ID,
			title:       method.Name,
			description: method.Description,
			recommended: method.Recommended,
			methodID:    method.ID, // Set methodID for badge determination
		}
	}
	return items
}

func NewMainMenuItems(installedAppsCount int) []menuItem {
	inPath := isInstallMPVInPATH()
	var pathTitle, pathDesc string

	if inPath {
		pathTitle = "🗑️ Remove mpv-manager from PATH"
		pathDesc = "Remove mpv-manager from your system PATH"
	} else {
		pathTitle = "📥 Add mpv-manager to your PATH"
		pathDesc = "Add mpv-manager to your system PATH for easy access"
	}

	if installedAppsCount == 0 {
		return []menuItem{
			{
				id:          "mpv-manager",
				title:       "📥 Install an MPV Player",
				description: "See options for installing MPV and MPV-based media players",
				recommended: false,
			},
			{
				id:          "updates",
				title:       "🔄 Updates",
				description: "Update installer or load config backups",
				recommended: false,
			},
			{
				id:          "set-language-preferences",
				title:       "💬 Set Language Preferences",
				description: "Configure audio and subtitle language priority for MPV",
				recommended: false,
			},
			{
				id:          "config-options",
				title:       "⚙️ MPV Config Options",
				description: "Configure MPV player settings and hardware acceleration",
				recommended: false,
			},
			{
				id:          "hotkeys",
				title:       "⌨️ Keyboard Shortcuts",
				description: "View all MPV keyboard shortcuts",
				recommended: false,
			},
			{
				id:          "web-ui",
				title:       "🌐 Web UI",
				description: "Create desktop shortcuts for Web UI mode",
				recommended: false,
			},
			{
				id:          "install-to-path",
				title:       pathTitle,
				description: pathDesc,
				recommended: false,
			},
		}
	}

	menuItems := []menuItem{
		{
			id:          "updates",
			title:       "🔄 Updates",
			description: "Update MPV installer or load config backups",
			recommended: false,
		},
		{
			id:          "set-language-preferences",
			title:       "💬 Set Language Preferences",
			description: "Configure audio and subtitle language priority for MPV",
			recommended: false,
		},
		{
			id:          "config-options",
			title:       "⚙️ MPV Config Options",
			description: "Configure MPV player settings and hardware acceleration",
			recommended: false,
		},
		{
			id:          "hotkeys",
			title:       "⌨️ Keyboard Shortcuts",
			description: "View all MPV keyboard shortcuts",
			recommended: false,
		},
		{
			id:          "mpv-manager",
			title:       "📥 Install an MPV Player",
			description: "See options for installing MPV and MPV-based media players",
			recommended: false,
		},
		{
			id:          "unmpv-manager",
			title:       "🗑️ Uninstall an MPV Player",
			description: "Remove MPV clients",
			recommended: false,
		},
		{
			id:          "web-ui",
			title:       "🌐 Web UI",
			description: "Create desktop shortcuts for Web UI mode",
			recommended: false,
		},
		{
			id:          "install-to-path",
			title:       pathTitle,
			description: pathDesc,
			recommended: false,
		},
	}

	return menuItems
}

func (m *Model) SetInstaller(inst *installer.Installer, p *platform.Platform) {
	m.installer = inst
	m.platformInfo = p
}

func (m *Model) SetMenuItems(items []menuItem, title string) {
	listItems := make([]list.Item, len(items))
	for i, item := range items {
		listItems[i] = item
	}

	m.menuList = m.createStyledList(title, listItems)
}

func (m *Model) RefreshMainMenu() {
	apps := config.GetInstalledApps()
	menuItems := NewMainMenuItems(len(apps))
	m.SetMenuItems(menuItems, "Main Menu")
}

func (m *Model) SetInstallMenuItems(items []menuItem, title string) {
	listItems := make([]list.Item, len(items))
	for i, item := range items {
		listItems[i] = item
	}

	m.installMenuList = m.createStyledList(title, listItems)
}

func (m *Model) SetInstallerWithMethods(inst *installer.Installer, p *platform.Platform, methods []installer.InstallMethod) {
	m.installer = inst
	m.platformInfo = p
	m.methods = methods
}

func (m *Model) setupInstallMenuList() {
	if len(m.methods) == 0 {
		m.statusMessage = "No installation methods available"
		return
	}

	items := NewMenuItemsFromInstaller(m.methods)

	// Sort items: MPV methods (Best Playback) first, then GUI methods (Easy UI)
	sort.Slice(items, func(i, j int) bool {
		iIsMPV := isMPVMethod(items[i].methodID)
		jIsMPV := isMPVMethod(items[j].methodID)

		// MPV methods come first
		if iIsMPV && !jIsMPV {
			return true
		}
		if !iIsMPV && jIsMPV {
			return false
		}

		// Within same category, sort by name
		if items[i].title != items[j].title {
			return items[i].title < items[j].title
		}

		// Same name, sort by ID (e.g., package before flatpak)
		return items[i].id < items[j].id
	})

	listItems := make([]list.Item, len(items))
	for i, item := range items {
		listItems[i] = item
	}

	m.installMenuList = m.createStyledList("Select Installation Method", listItems)
}

func (m *Model) SetState(state State) {
	m.state = state
}

func (m *Model) SetStatusMessage(msg string) {
	m.statusMessage = msg
}

func (m *Model) SetErrorMessage(msg string) {
	m.errorMessage = msg
}

func (m *Model) SetProgress(progress int) {
	m.installProgress = progress
}

func (m *Model) Installing() bool {
	return m.installing
}

func (m *Model) GetSelectedMethodID() string {
	return m.selectedMethodID
}

func (m *Model) GetSelectedMethod() string {
	return m.selectedMethod
}

func (m *Model) updateOutputViewport() {
	content := strings.Join(m.installOutput, "\n")
	m.outputViewport.SetContent(content)
}

func (m *Model) createStyledList(title string, items []list.Item) list.Model {
	delegate := list.NewDefaultDelegate()
	delegate.ShowDescription = true
	delegate.Styles.SelectedTitle = selectedItemStyle
	delegate.Styles.SelectedDesc = infoStyle

	l := list.New(items, delegate, 0, 0)
	l.Title = title
	l.Styles.Title = titleStyle
	l.Styles.FilterPrompt = infoStyle
	l.Styles.FilterCursor = selectedItemStyle

	if m.termWidth > 0 && m.termHeight > 0 {
		l.SetWidth(m.termWidth - 10)
		l.SetHeight(m.termHeight - 15)
	}

	return l
}

func (m *Model) setupWebUIList() {
	items := []list.Item{
		menuItem{
			id:          "create-webui-shortcut",
			title:       "🌐 Create Web UI Shortcut",
			description: "Create a shortcut to launch MPV Installer in Web UI mode",
			recommended: false,
		},
	}

	m.webUIList = m.createStyledList("Web UI Options", items)
}
