package tui

import (
	"fmt"
	"os"
	"path/filepath"
	"strings"
	"time"

	"gitgud.io/mike/mpv-manager/internal/assets"
	"gitgud.io/mike/mpv-manager/pkg/config"
	"gitgud.io/mike/mpv-manager/pkg/constants"
	"gitgud.io/mike/mpv-manager/pkg/locale"
	"gitgud.io/mike/mpv-manager/pkg/log"
	"github.com/charmbracelet/bubbles/list"
	tea "github.com/charmbracelet/bubbletea"
	"github.com/charmbracelet/lipgloss"
)

var whiteStyle = lipgloss.NewStyle().Foreground(white)

type langPrefTypeItem struct {
	prefType string
	isAudio  bool
}

func (l langPrefTypeItem) Title() string {
	if l.isAudio {
		current := config.GetConfigValue(constants.ConfigKeyAudioLanguage)
		title := "🔊 Audio Language Preference"
		if len(current) > 0 {
			title += fmt.Sprintf(" (currently: %s)", strings.Join(current, ", "))
		}
		return title
	} else {
		current := config.GetConfigValue(constants.ConfigKeySubtitleLanguage)
		title := "💬 Subtitle Language Preference"
		if len(current) > 0 {
			title += fmt.Sprintf(" (currently: %s)", strings.Join(current, ", "))
		}
		return title
	}
}

func (l langPrefTypeItem) Description() string {
	if l.isAudio {
		return "Configure audio track language priority"
	}
	return "Configure subtitle track language priority"
}

func (l langPrefTypeItem) FilterValue() string {
	return l.prefType
}

type majorLangItem struct {
	entry *locale.LocaleEntry
}

func (m majorLangItem) Title() string {
	flag := locale.GetFlagForLanguageCode(m.entry.LanguageCode)
	return fmt.Sprintf("%s %s - %s (%s)", flag, m.entry.LanguageName, m.entry.LanguageLocal, m.entry.LanguageCode)
}

func (m majorLangItem) Description() string {
	return fmt.Sprintf("Code: %s", m.entry.LanguageCode)
}

func (m majorLangItem) FilterValue() string {
	return fmt.Sprintf("%s %s %s", m.entry.LanguageName, m.entry.LanguageLocal, m.entry.LanguageCode)
}

type regionLangItem struct {
	entry   *locale.LocaleEntry
	region  *locale.RegionEntry
	isMajor bool
}

func (r regionLangItem) Title() string {
	if r.isMajor {
		return fmt.Sprintf("Use %s only (%s)", r.entry.LanguageName, r.entry.LanguageCode)
	}
	// Format: "🇸🇦 Arabic - Saudi Arabia ★" (with star for major variants)
	countryPart := fmt.Sprintf("%s", r.region.CountryName)
	if r.region.MajorRegionalVariant {
		countryPart += " ★"
	}
	return fmt.Sprintf("%s %s - %s",
		r.region.Flag,
		r.entry.LanguageName,
		countryPart)
}

func (r regionLangItem) Description() string {
	if r.isMajor {
		return "Priority #1: Major language (no regional preference)"
	}
	// Format: "العربية - المملكة العربية السعودية / Al-´Arabiya as-Sa´ (ar-SA)"
	// Note: CountryLocal already contains the transliteration separated by " / "
	return fmt.Sprintf("%s - %s (%s)",
		r.entry.LanguageLocal,
		r.region.CountryLocal,
		r.region.Locale)
}

func (r regionLangItem) FilterValue() string {
	if r.isMajor {
		return "major only"
	}
	return fmt.Sprintf("%s %s %s", r.region.CountryName, r.region.CountryLocal, r.region.Locale)
}

type selectedLangItem struct {
	index     int
	locale    string
	display   string
	isAdd     bool
	isRemove  bool
	isConfirm bool
}

func (s selectedLangItem) Title() string {
	return s.display
}

func (s selectedLangItem) Description() string {
	if s.isAdd {
		return "Add a language to your priority list"
	}
	if s.isRemove {
		return "Remove selected language from list"
	}
	return ""
}

func (s selectedLangItem) FilterValue() string {
	return s.display
}

func (m *Model) setupLangPreferenceList() {
	items := []list.Item{
		langPrefTypeItem{prefType: "audio", isAudio: true},
		langPrefTypeItem{prefType: "subtitle", isAudio: false},
	}

	m.langPreferenceList = m.createStyledList("Language Preferences", items)
}

func (m *Model) loadLanguageData() {
	locales, err := assets.ReadLocales()
	if err != nil {
		log.Warn(fmt.Sprintf("Failed to load locales: %v", err))
		m.loadedLocales = []locale.LocaleEntry{}
		return
	}
	m.loadedLocales = locales
	m.loadCurrentMPVLanguageValues()
}

func (m *Model) loadCurrentMPVLanguageValues() {
	m.currentMPVAudioLangs = config.GetConfigValue(constants.ConfigKeyAudioLanguage)
	m.currentMPVSubtitleLangs = config.GetConfigValue(constants.ConfigKeySubtitleLanguage)

	if len(m.currentMPVAudioLangs) == 0 {
		m.currentMPVAudioLangs = []string{}
	}
	if len(m.currentMPVSubtitleLangs) == 0 {
		m.currentMPVSubtitleLangs = []string{}
	}
}

func (m *Model) handleLangPreferenceUpdate(msg tea.Msg) (*Model, tea.Cmd) {
	var cmd tea.Cmd
	m.langPreferenceList, cmd = m.langPreferenceList.Update(msg)

	switch msg := msg.(type) {
	case tea.KeyMsg:
		switch msg.Type {
		case tea.KeyEsc:
			m.state = StateMainMenu
			return m, nil

		case tea.KeyEnter:
			selected := m.langPreferenceList.SelectedItem()
			if item, ok := selected.(langPrefTypeItem); ok {
				m.langPreferenceType = item.prefType

				if m.langPreferenceType == "audio" {
					m.selectedLanguageCodes = make([]string, len(m.currentMPVAudioLangs))
					copy(m.selectedLanguageCodes, m.currentMPVAudioLangs)
				} else {
					m.selectedLanguageCodes = make([]string, len(m.currentMPVSubtitleLangs))
					copy(m.selectedLanguageCodes, m.currentMPVSubtitleLangs)
				}

				m.state = StateLanguageSelectedList
				m.setupSelectedLangList()
			}
		}
	}

	return m, cmd
}

func (m *Model) handleMajorLangUpdate(msg tea.Msg) (*Model, tea.Cmd) {
	switch msg := msg.(type) {
	case tea.KeyMsg:
		// Handle search mode
		if m.isLangSearching {
			switch msg.Type {
			case tea.KeyEsc:
				// If search term is not empty, clear it but stay in search mode
				if m.langSearchTerm != "" {
					m.langSearchTerm = ""
					m.setupMajorLangList()
					return m, nil
				}
				// If search term is empty, exit search mode
				m.clearLanguageSearch()
				m.setupMajorLangList()
				return m, nil
			case tea.KeyEnter:
				// Select the currently highlighted item from search results
				selected := m.majorLangList.SelectedItem()
				if selected != nil {
					// Handle both majorLangItem and regionLangItem (from search results)
					switch item := selected.(type) {
					case majorLangItem:
						m.currentMajorLanguage = item.entry
						m.majorLangList.ResetFilter()
						m.clearLanguageSearch()

						if len(item.entry.Regions) == 0 {
							m.selectedLanguageCodes = append(m.selectedLanguageCodes, item.entry.LanguageCode)
							m.saveLanguagePreferences()
							m.state = StateLanguageSelectedList
							m.setupSelectedLangList()
							m.selectedLangList.Select(0)
						} else {
							m.state = StateLanguageRegionSelect
							m.setupRegionLangList()
						}

					case regionLangItem:
						m.majorLangList.ResetFilter()
						m.clearLanguageSearch()

						// Directly add regional variant, skip region selection screen
						var localeCode string
						if item.isMajor {
							localeCode = item.entry.LanguageCode
						} else {
							localeCode = item.region.Locale
						}

						m.selectedLanguageCodes = append(m.selectedLanguageCodes, localeCode)
						m.saveLanguagePreferences()
						m.state = StateLanguageSelectedList
						m.setupSelectedLangList()
						m.selectedLangList.Select(0)
					}
				}
				return m, nil
			case tea.KeyBackspace:
				if len(m.langSearchTerm) > 0 {
					m.langSearchTerm = m.langSearchTerm[:len(m.langSearchTerm)-1]
					m.setupMajorLangList()
				}
				return m, nil
			case tea.KeyRunes:
				if len(msg.Runes) > 0 {
					m.langSearchTerm += string(msg.Runes)
					m.setupMajorLangList()
				}
				return m, nil
			}
			// Pass through up/down arrows to navigate within search results
			// Don't return yet, let the list update happen below
		}

		// Handle normal mode
		switch msg.Type {
		case tea.KeyEsc:
			if m.majorLangList.SettingFilter() || m.majorLangList.IsFiltered() {
				m.majorLangList.ResetFilter()
				return m, nil
			}
			m.state = StateLanguageSelectedList
			m.setupSelectedLangList()
			return m, nil
		case tea.KeyRunes:
			// Press '/' to enter search mode
			if len(msg.Runes) == 1 && msg.Runes[0] == '/' {
				m.isLangSearching = true
				m.langSearchTerm = ""
				return m, nil
			}
		}
	}

	var cmd tea.Cmd
	// Allow up/down navigation even in search mode
	m.majorLangList, cmd = m.majorLangList.Update(msg)

	// Handle Enter key (for normal mode, not search mode)
	// Search mode Enter is handled above in the first switch statement
	if keyMsg, ok := msg.(tea.KeyMsg); ok && keyMsg.Type == tea.KeyEnter && !m.isLangSearching {
		selected := m.majorLangList.SelectedItem()

		// Handle both majorLangItem and regionLangItem (from search results)
		switch item := selected.(type) {
		case majorLangItem:
			m.currentMajorLanguage = item.entry
			m.majorLangList.ResetFilter()
			m.clearLanguageSearch()

			if len(item.entry.Regions) == 0 {
				m.selectedLanguageCodes = append(m.selectedLanguageCodes, item.entry.LanguageCode)
				m.saveLanguagePreferences()
				m.state = StateLanguageSelectedList
				m.setupSelectedLangList()
				m.selectedLangList.Select(0)
			} else {
				m.state = StateLanguageRegionSelect
				m.setupRegionLangList()
			}

		case regionLangItem:
			m.majorLangList.ResetFilter()
			m.clearLanguageSearch()

			// Directly add regional variant, skip region selection screen
			var localeCode string
			if item.isMajor {
				localeCode = item.entry.LanguageCode
			} else {
				localeCode = item.region.Locale
			}

			m.selectedLanguageCodes = append(m.selectedLanguageCodes, localeCode)
			m.saveLanguagePreferences()
			m.state = StateLanguageSelectedList
			m.setupSelectedLangList()
			m.selectedLangList.Select(0)
		}
	}

	return m, cmd
}

func (m *Model) handleRegionLangUpdate(msg tea.Msg) (*Model, tea.Cmd) {
	switch msg := msg.(type) {
	case tea.KeyMsg:
		// Handle search mode
		if m.isLangSearching {
			switch msg.Type {
			case tea.KeyEsc:
				// If search term is not empty, clear it but stay in search mode
				if m.langSearchTerm != "" {
					m.langSearchTerm = ""
					m.setupRegionLangList()
					return m, nil
				}
				// If search term is empty, exit search mode
				m.clearLanguageSearch()
				m.setupRegionLangList()
				return m, nil
			case tea.KeyEnter:
				// Select the currently highlighted item from search results
				selected := m.regionLangList.SelectedItem()
				if selected != nil {
					if item, ok := selected.(regionLangItem); ok {
						m.regionLangList.ResetFilter()
						m.clearLanguageSearch()

						var localeCode string
						if item.isMajor {
							localeCode = item.entry.LanguageCode
						} else {
							localeCode = item.region.Locale
						}

						m.selectedLanguageCodes = append(m.selectedLanguageCodes, localeCode)
						m.saveLanguagePreferences()
						m.state = StateLanguageSelectedList
						m.setupSelectedLangList()
						m.selectedLangList.Select(0)
					}
				}
				return m, nil
			case tea.KeyBackspace:
				if len(m.langSearchTerm) > 0 {
					m.langSearchTerm = m.langSearchTerm[:len(m.langSearchTerm)-1]
					m.setupRegionLangList()
				}
				return m, nil
			case tea.KeyRunes:
				if len(msg.Runes) > 0 {
					m.langSearchTerm += string(msg.Runes)
					m.setupRegionLangList()
				}
				return m, nil
			}
			// Pass through up/down arrows to navigate within search results
			// Don't return yet, let the list update happen below
		}

		// Handle normal mode
		switch msg.Type {
		case tea.KeyEsc:
			if m.regionLangList.SettingFilter() || m.regionLangList.IsFiltered() {
				m.regionLangList.ResetFilter()
				return m, nil
			}
			m.state = StateLanguageMajorSelect
			m.clearLanguageSearch()
			m.setupMajorLangList()
			return m, nil
		case tea.KeyRunes:
			// Press '/' to enter search mode
			if len(msg.Runes) == 1 && msg.Runes[0] == '/' {
				m.isLangSearching = true
				m.langSearchTerm = ""
				return m, nil
			}
		}
	}

	var cmd tea.Cmd
	// Allow up/down navigation even in search mode
	m.regionLangList, cmd = m.regionLangList.Update(msg)

	// Handle Enter key (for normal mode, not search mode)
	// Search mode Enter is handled above in the first switch statement
	if keyMsg, ok := msg.(tea.KeyMsg); ok && keyMsg.Type == tea.KeyEnter && !m.isLangSearching {
		selected := m.regionLangList.SelectedItem()
		if item, ok := selected.(regionLangItem); ok {
			m.regionLangList.ResetFilter()
			m.clearLanguageSearch()

			var localeCode string
			if item.isMajor {
				localeCode = item.entry.LanguageCode
			} else {
				localeCode = item.region.Locale
			}

			m.selectedLanguageCodes = append(m.selectedLanguageCodes, localeCode)
			m.saveLanguagePreferences()
			m.state = StateLanguageSelectedList
			m.setupSelectedLangList()
			m.selectedLangList.Select(0)
		}
	}

	return m, cmd
}

func (m *Model) handleSelectedLangUpdate(msg tea.Msg) (*Model, tea.Cmd) {
	switch msg := msg.(type) {
	case tea.KeyMsg:
		switch msg.Type {
		case tea.KeyEsc:
			if m.selectedLangList.SettingFilter() || m.selectedLangList.IsFiltered() {
				m.selectedLangList.ResetFilter()
				return m, nil
			}
			m.state = StateMainMenu
			return m, nil

		case tea.KeyRunes:
			if len(msg.Runes) == 1 && msg.Runes[0] == 'r' {
				m.removeSelectedLanguage()
				m.setupSelectedLangList()
				return m, nil
			}

		// Handle priority list reordering with Ctrl+↑/Ctrl+↓
		case tea.KeyCtrlUp:
			// Get current index before moving
			selected := m.selectedLangList.SelectedItem()
			if item, ok := selected.(selectedLangItem); ok {
				currentIndex := item.index
				// Only move if not a special item and not at top
				if currentIndex > 0 && !item.isAdd && !item.isRemove && !item.isConfirm {
					m.moveSelectedLanguageUp()
					m.setupSelectedLangList()
					// Restore selection - item moved up in selectedLanguageCodes
					// List structure: [0: Add, 1-N: languages, N+1: Confirm]
					// Language index 'currentIndex' in selectedLanguageCodes maps to list index 'currentIndex + 1'
					// After moving up, item is at 'currentIndex - 1' in selectedLanguageCodes
					// Which maps to list index '(currentIndex - 1) + 1 = currentIndex'
					m.selectedLangList.Select(currentIndex)
				}
			}
			return m, nil

		case tea.KeyCtrlDown:
			// Get current index before moving
			selected := m.selectedLangList.SelectedItem()
			if item, ok := selected.(selectedLangItem); ok {
				currentIndex := item.index
				// Only move if not a special item and not at bottom
				if currentIndex >= 0 && currentIndex < len(m.selectedLanguageCodes)-1 && !item.isAdd && !item.isRemove && !item.isConfirm {
					m.moveSelectedLanguageDown()
					m.setupSelectedLangList()
					// Restore selection - item moved down in selectedLanguageCodes
					// List structure: [0: Add, 1-N: languages, N+1: Confirm]
					// Language index 'currentIndex' in selectedLanguageCodes maps to list index 'currentIndex + 1'
					// After moving down, item is at 'currentIndex + 1' in selectedLanguageCodes
					// Which maps to list index '(currentIndex + 1) + 1 = currentIndex + 2'
					m.selectedLangList.Select(currentIndex + 2)
				}
			}
			return m, nil
		}
	}

	var cmd tea.Cmd
	m.selectedLangList, cmd = m.selectedLangList.Update(msg)

	switch msg := msg.(type) {
	case tea.KeyMsg:
		switch msg.Type {
		case tea.KeyEnter:
			selected := m.selectedLangList.SelectedItem()
			if item, ok := selected.(selectedLangItem); ok {
				if item.isAdd {
					m.state = StateLanguageMajorSelect
					m.setupMajorLangList()
				} else if item.isRemove {
					m.removeSelectedLanguage()
					m.setupSelectedLangList()
				} else if item.isConfirm {
					m.applyLanguagePreferences()
					m.loadCurrentMPVLanguageValues()
					m.state = StateLanguageConfirm
				}
			}

		case tea.KeyRunes:
			if len(msg.Runes) == 1 && msg.Runes[0] == 'r' {
				m.removeSelectedLanguage()
				m.setupSelectedLangList()
			}
		}
	}

	return m, cmd
}

func (m *Model) removeSelectedLanguage() {
	selected := m.selectedLangList.SelectedItem()
	if item, ok := selected.(selectedLangItem); ok && !item.isAdd && !item.isRemove && !item.isConfirm {
		index := item.index
		if index >= 0 && index < len(m.selectedLanguageCodes) {
			m.selectedLanguageCodes = append(
				m.selectedLanguageCodes[:index],
				m.selectedLanguageCodes[index+1:]...)

			m.saveLanguagePreferences()
			m.setupSelectedLangList()
			m.selectedLangList.Select(0)
		}
	}
}

// moveSelectedLanguageUp moves the selected language up in the priority list
func (m *Model) moveSelectedLanguageUp() {
	selected := m.selectedLangList.SelectedItem()
	if item, ok := selected.(selectedLangItem); ok {
		index := item.index
		// Can only move if not a special item (Add/Remove/Confirm) and not at top
		if index > 0 && !item.isAdd && !item.isRemove && !item.isConfirm {
			// Swap with previous item
			m.selectedLanguageCodes[index-1], m.selectedLanguageCodes[index] =
				m.selectedLanguageCodes[index], m.selectedLanguageCodes[index-1]

			// Save to mpv.conf
			var err error
			if m.langPreferenceType == "audio" {
				err = config.SetConfigValue(constants.ConfigKeyAudioLanguage, m.selectedLanguageCodes, true)
			} else {
				err = config.SetConfigValue(constants.ConfigKeySubtitleLanguage, m.selectedLanguageCodes, true)
			}

			if err != nil {
				log.Error(fmt.Sprintf("Failed to update language priority: %v", err))
			}
		}
	}
}

// moveSelectedLanguageDown moves the selected language down in the priority list
func (m *Model) moveSelectedLanguageDown() {
	selected := m.selectedLangList.SelectedItem()
	if item, ok := selected.(selectedLangItem); ok {
		index := item.index
		// Can only move if not a special item (Add/Remove/Confirm) and not at bottom
		if index >= 0 && index < len(m.selectedLanguageCodes)-1 && !item.isAdd && !item.isRemove && !item.isConfirm {
			// Swap with next item
			m.selectedLanguageCodes[index], m.selectedLanguageCodes[index+1] =
				m.selectedLanguageCodes[index+1], m.selectedLanguageCodes[index]

			// Save to mpv.conf
			var err error
			if m.langPreferenceType == "audio" {
				err = config.SetConfigValue(constants.ConfigKeyAudioLanguage, m.selectedLanguageCodes, true)
			} else {
				err = config.SetConfigValue(constants.ConfigKeySubtitleLanguage, m.selectedLanguageCodes, true)
			}

			if err != nil {
				log.Error(fmt.Sprintf("Failed to update language priority: %v", err))
			}
		}
	}
}

func (m *Model) setupMajorLangList() {
	delegate := list.NewDefaultDelegate()
	delegate.ShowDescription = true
	delegate.Styles.SelectedTitle = selectedItemStyle
	delegate.Styles.SelectedDesc = infoStyle

	var items []list.Item

	// Use search results if in search mode
	if m.langSearchTerm != "" {
		opts := locale.LanguageFilterOptions{
			SearchTerm: m.langSearchTerm,
		}
		searchResults := locale.SearchLanguages(m.loadedLocales, opts)
		m.langSearchResults = searchResults

		// Convert search results to regionLangItem to preserve regional info
		convertedItems := ConvertLanguageOptionsToRegionItems(searchResults, m.loadedLocales)
		items = make([]list.Item, len(convertedItems))
		for i, item := range convertedItems {
			items[i] = item
		}
	} else {
		// Use major languages only (33 common languages, not all 123+ locales)
		majorLangs := locale.GetMajorLanguages(m.loadedLocales)
		items = make([]list.Item, 0, len(majorLangs)+10) // +10 for Spanish (Latin America) and others

		for _, entry := range majorLangs {
			items = append(items, majorLangItem{entry: &entry})

			// Special case: Add Spanish (Latin America) after Spanish
			if entry.LanguageCode == "es" && strings.Contains(strings.ToLower(entry.LanguageName), "spanish") {
				// Find Spanish (Latin America) entry (search case-insensitively and check for variations)
				for _, latinEntry := range m.loadedLocales {
					entryLower := strings.ToLower(latinEntry.LanguageName)
					// Check for multiple possible name variations
					if latinEntry.LanguageCode == "es" &&
						(entryLower == "spanish (latin america)" ||
							entryLower == "spanish latin america" ||
							entryLower == "latin american spanish" ||
							strings.Contains(entryLower, "latin")) {
						items = append(items, majorLangItem{entry: &latinEntry})
						break
					}
				}
			}
		}
	}

	m.majorLangList = m.createStyledList("Select Major Language", items)
}

// clearLanguageSearch resets the search state
func (m *Model) clearLanguageSearch() {
	m.langSearchTerm = ""
	m.isLangSearching = false
	m.langSearchResults = nil
}

// applyLanguageSearch updates the search term and refreshes the list
func (m *Model) applyLanguageSearch(term string) {
	m.langSearchTerm = term
	m.setupMajorLangList()
}

func (m *Model) setupRegionLangList() {
	var items []list.Item

	// Add "major language only" option
	items = append(items, regionLangItem{
		entry:   m.currentMajorLanguage,
		region:  nil,
		isMajor: true,
	})

	// If search term is provided, filter regions by search term
	if m.langSearchTerm != "" {
		// Search languages with country filter (use language code from current major language)
		opts := locale.LanguageFilterOptions{
			SearchTerm:  m.langSearchTerm,
			CountryCode: "", // Don't filter by country, allow all regions
		}
		searchResults := locale.SearchLanguages(m.loadedLocales, opts)

		// Filter to only include regions that match the current major language
		for _, opt := range searchResults {
			// Extract language code from the search result locale
			langCode := extractLanguageCode(opt.Locale)
			if langCode == m.currentMajorLanguage.LanguageCode {
				// Convert to regionLangItem
				item := LanguageOptionToRegionLangItem(opt, m.loadedLocales)
				if !item.isMajor { // Skip the "major language only" entry
					items = append(items, item)
				}
			}
		}
	} else {
		// Use sorted regions (major variants first, then by population)
		sortedRegions := locale.GetMajorRegionalVariants(m.currentMajorLanguage)
		for _, region := range sortedRegions {
			items = append(items, regionLangItem{
				entry:   m.currentMajorLanguage,
				region:  &region,
				isMajor: false, // Always false for regional variants (only the top "use language only" entry is major)
			})
		}
	}

	m.regionLangList = m.createStyledList(fmt.Sprintf("Select %s Regional Variant", m.currentMajorLanguage.LanguageName), items)
}

func (m *Model) setupSelectedLangList() {
	delegate := list.NewDefaultDelegate()
	delegate.ShowDescription = true
	delegate.Styles.SelectedTitle = selectedItemStyle
	delegate.Styles.SelectedDesc = infoStyle

	items := []list.Item{
		selectedLangItem{
			index:   -1,
			locale:  "",
			display: "+ Select another language",
			isAdd:   true,
		},
	}

	for i, code := range m.selectedLanguageCodes {
		var entry *locale.LocaleEntry
		var region *locale.RegionEntry
		var flag string
		var languageName string
		var nativeName string
		var displayCode string
		var display string

		// Parse the locale code
		if strings.Contains(code, "-") {
			// Regional variant (e.g., "ja-JP", "en-US")
			entry, region = locale.FindByLocale(code, m.loadedLocales)
			if entry != nil && region != nil {
				flag = region.Flag
				if flag == "" {
					flag = locale.GetFlagForLanguageCode(entry.LanguageCode)
				}
				languageName = entry.LanguageName
				nativeName = entry.LanguageLocal
				displayCode = region.Locale
			} else if entry != nil {
				// Entry found but region is nil (fallback)
				flag = locale.GetFlagForLanguageCode(entry.LanguageCode)
				languageName = entry.LanguageName
				nativeName = entry.LanguageLocal
				displayCode = code
			}
		} else {
			// Major language only (e.g., "ja", "en")
			entry = locale.FindByLanguageCode(code, m.loadedLocales)
			if entry != nil {
				flag = locale.GetFlagForLanguageCode(entry.LanguageCode)
				languageName = entry.LanguageName
				nativeName = entry.LanguageLocal
				displayCode = entry.LanguageCode
			}
		}

		// Create display string matching selection list format
		if entry != nil {
			// Use the same format as selection lists: "🇯🇵 Japanese - 日本語 (にほんご) (ja)"
			// For priority list, we omit the number prefix to keep it clean
			display = fmt.Sprintf("%s %s - %s (%s)",
				flag,
				languageName,
				nativeName,
				displayCode)

			items = append(items, selectedLangItem{
				index:   i,
				locale:  code,
				display: display,
				isAdd:   false,
			})
		} else {
			// Entry not found (fallback)
			display = fmt.Sprintf("%s (%s)", code, code)
			items = append(items, selectedLangItem{
				index:   i,
				locale:  code,
				display: display,
				isAdd:   false,
			})
		}
	}

	items = append(items, selectedLangItem{
		index:     -1,
		locale:    "",
		display:   "✓ Confirm & Apply to mpv.conf",
		isConfirm: true,
	})

	m.selectedLangList = m.createStyledList("Language Priority List", items)
}

func (m *Model) saveLanguagePreferences() {
	// No longer need to save to JSON - mpv.conf is single source of truth
	// Language preferences will be applied via applyLanguagePreferences()
}

func (m *Model) applyLanguagePreferences() {
	configPath := config.GetConfigPath()

	// Backup before modification
	m.backupMPVConfig(configPath)

	// Apply language preferences
	var err error
	if m.langPreferenceType == "audio" {
		err = config.SetConfigValue(constants.ConfigKeyAudioLanguage, m.selectedLanguageCodes, true)
	} else {
		err = config.SetConfigValue(constants.ConfigKeySubtitleLanguage, m.selectedLanguageCodes, true)
	}

	if err != nil {
		log.Error(fmt.Sprintf("Failed to apply language preferences: %v", err))
		return
	}

	log.Info("Language preferences applied to mpv.conf")
}

func (m *Model) backupMPVConfig(configPath string) {
	timestamp := time.Now().Format("2006-01-02")
	backupPath := filepath.Join(filepath.Dir(configPath), fmt.Sprintf("%s-mpv.conf.bak", timestamp))

	if err := os.Rename(configPath, backupPath); err != nil {
		log.Warn(fmt.Sprintf("Failed to create backup: %v", err))
	} else {
		log.Info(fmt.Sprintf("Backup created: %s", backupPath))
	}
}

func (m Model) langPreferenceSelectView() string {
	var content strings.Builder

	content.WriteString(infoStyle.Render("Configure MPV language priority for:"))
	content.WriteString("\n\n")

	content.WriteString(m.langPreferenceList.View())

	return m.wrapContentInViewport(content.String())
}

func (m Model) majorLangSelectViewRaw() string {
	var content strings.Builder

	title := "Select Audio Language"
	if m.langPreferenceType == "subtitle" {
		title = "Select Subtitle Language"
	}

	content.WriteString(titleStyle.Render(title))
	content.WriteString("\n")
	content.WriteString(subtitleStyle.Render("═══════════════════════"))
	content.WriteString("\n\n")

	// Show search input if in search mode
	if m.isLangSearching {
		content.WriteString(infoStyle.Render("Search: "))
		// Yellow/bold search text for better visibility
		searchTextStyle := lipgloss.NewStyle().Foreground(lipgloss.Color("214")).Bold(true) // Orange/Yellow
		content.WriteString(searchTextStyle.Render("/" + m.langSearchTerm + "█"))
		content.WriteString("\n")
		content.WriteString(infoStyle.Render("Type to search, ↑↓ to navigate, Enter to select"))
		content.WriteString("\n")
		content.WriteString(infoStyle.Render("Esc to clear search"))
		content.WriteString("\n\n")
	} else {
		// Show normal help text
		if m.langSearchTerm != "" {
			// Yellow/bold search term for better visibility
			searchTextStyle := lipgloss.NewStyle().Foreground(lipgloss.Color("214")).Bold(true) // Orange/Yellow
			content.WriteString(infoStyle.Render("Search results for: "))
			content.WriteString(searchTextStyle.Render(m.langSearchTerm))
			if len(m.langSearchResults) > 0 {
				content.WriteString(infoStyle.Render(fmt.Sprintf(" (%d results found)", len(m.langSearchResults))))
			} else {
				content.WriteString(infoStyle.Render(" (no results)"))
			}
			content.WriteString("\n")
			content.WriteString(infoStyle.Render("Press / to clear search"))
			content.WriteString("\n")
		} else {
			content.WriteString(infoStyle.Render("Press / then type to filter languages"))
			content.WriteString("\n")
		}
		content.WriteString(infoStyle.Render("↑↓ to navigate, Enter to select"))
		content.WriteString("\n")
		content.WriteString(infoStyle.Render("Esc to cancel"))
		content.WriteString("\n\n")
	}

	// Always display the list (in both search mode and normal mode)
	content.WriteString(m.majorLangList.View())

	return content.String()
}

func (m Model) regionLangSelectViewRaw() string {
	var content strings.Builder

	title := fmt.Sprintf("Select %s Regional Variant", m.currentMajorLanguage.LanguageName)

	content.WriteString(titleStyle.Render(title))
	content.WriteString("\n")
	content.WriteString(subtitleStyle.Render("═════════════════════════"))
	content.WriteString("\n\n")

	// Show search input if in search mode
	if m.isLangSearching {
		content.WriteString(infoStyle.Render("Search: "))
		// Yellow/bold search text for better visibility
		searchTextStyle := lipgloss.NewStyle().Foreground(lipgloss.Color("214")).Bold(true) // Orange/Yellow
		content.WriteString(searchTextStyle.Render("/" + m.langSearchTerm + "█"))
		content.WriteString("\n")
		content.WriteString(infoStyle.Render("Type to search, ↑↓ to navigate, Enter to select"))
		content.WriteString("\n")
		content.WriteString(infoStyle.Render("Esc to clear search"))
		content.WriteString("\n\n")
	} else {
		// Show normal help text
		if m.langSearchTerm != "" {
			// Yellow/bold search term for better visibility
			searchTextStyle := lipgloss.NewStyle().Foreground(lipgloss.Color("214")).Bold(true) // Orange/Yellow
			content.WriteString(infoStyle.Render("Search results for: "))
			content.WriteString(searchTextStyle.Render(m.langSearchTerm))
			content.WriteString("\n")
			content.WriteString(infoStyle.Render("Press / to clear search"))
			content.WriteString("\n")
		} else {
			content.WriteString(infoStyle.Render("Press / then type to filter regions"))
			content.WriteString("\n")
		}
		content.WriteString(infoStyle.Render("↑↓ to navigate, Enter to select"))
		content.WriteString("\n")
		content.WriteString(infoStyle.Render("Esc to go back"))
		content.WriteString("\n\n")
	}

	// Always display the list (in both search mode and normal mode)
	content.WriteString(m.regionLangList.View())

	return content.String()
}

func (m Model) selectedLangListViewRaw() string {
	var content strings.Builder

	content.WriteString(infoStyle.Render("This is your priority list. "))
	content.WriteString(infoStyle.Render("MPV will use these languages in order of priority."))
	content.WriteString("\n\n")

	content.WriteString(infoStyle.Render("Select '+ Select another language' at top to add more languages"))
	content.WriteString("\n")
	content.WriteString(infoStyle.Render("↑↓ to navigate, Enter to select, 'r' to remove"))
	content.WriteString("\n")
	content.WriteString(infoStyle.Render("Ctrl+↑/Ctrl+↓ to reorder priority list"))
	content.WriteString("\n\n")

	content.WriteString(m.selectedLangList.View())

	return content.String()
}

func (m Model) languageConfirmView() string {
	var content strings.Builder

	title := "Audio Preferences Applied"
	if m.langPreferenceType == "subtitle" {
		title = "Subtitle Preferences Applied"
	}

	content.WriteString(titleStyle.Render(title))
	content.WriteString("\n")
	content.WriteString(subtitleStyle.Render("═════════════════════════"))
	content.WriteString("\n\n")

	content.WriteString(successStyle.Render("✓ Language preferences saved"))
	content.WriteString("\n\n")

	content.WriteString(infoStyle.Render("MPV configuration updated with:"))
	content.WriteString("\n")

	if len(m.selectedLanguageCodes) == 0 {
		content.WriteString(infoStyle.Render("  (empty - language preference disabled)"))
	} else {
		for i, code := range m.selectedLanguageCodes {
			entry, _ := locale.FindByLocale(code, m.loadedLocales)
			flag := ""
			if entry != nil {
				flag = locale.GetFlagForLanguageCode(entry.LanguageCode)
			}
			display := fmt.Sprintf("  %d. %s %s",
				i+1,
				flag,
				code)
			content.WriteString(infoStyle.Render(display))
			content.WriteString("\n")
		}
	}

	content.WriteString("\n")
	content.WriteString(infoStyle.Render("Press "))
	content.WriteString(subtitleStyle.Render("Enter"))
	content.WriteString(infoStyle.Render(" to return to main menu"))

	return m.wrapContentInViewport(content.String())
}
