package web

import (
	"fmt"
	"strings"

	"gitgud.io/mike/mpv-manager/internal/assets"
	"gitgud.io/mike/mpv-manager/pkg/locale"
)

// LanguageOption holds language display data for web UI selection
// This struct includes JSON tags for API responses
type LanguageOption struct {
	Locale        string `json:"locale"`         // Full locale string (e.g., "ja-JP")
	LanguageName  string `json:"language_name"`  // English language name (e.g., "Japanese")
	LanguageLocal string `json:"language_local"` // Native language name (e.g., "日本語")
	FlagEmoji     string `json:"flag_emoji"`     // Flag emoji (e.g., "🇯🇵")
	CountryCode   string `json:"country_code"`   // ISO country code (e.g., "JP")
	CountryName   string `json:"country_name"`   // Country name (e.g., "Japan")
	FullLocale    string `json:"full_locale"`    // Full locale code for display (e.g., "ES-419")
	DisplayText   string `json:"display_text"`   // Formatted display text (e.g., "🇯🇵 JP - 日本語 (Japanese)")
}

// LanguageFilterOptions defines filtering options for language search
// This struct is kept for API compatibility with existing web code
type LanguageFilterOptions struct {
	CommonOnly bool   // Show only common languages
	SearchTerm string // Search by language name or country code
	Limit      int    // Maximum number of results (0 = no limit)
}

// ConvertToWebOption converts a locale.LanguageOption to a web.LanguageOption
// This preserves the JSON tags needed for API responses
func ConvertToWebOption(localeOpt locale.LanguageOption) LanguageOption {
	flagEmoji := extractFlagEmoji(localeOpt)

	return LanguageOption{
		Locale:        localeOpt.Locale,
		LanguageName:  localeOpt.LanguageName,
		LanguageLocal: localeOpt.LanguageLocal,
		FlagEmoji:     flagEmoji,
		CountryCode:   localeOpt.CountryCode,
		CountryName:   localeOpt.CountryName,
		FullLocale:    localeOpt.FullLocale,
		DisplayText:   localeOpt.DisplayText,
	}
}

// ConvertToWebOptionSlice converts a slice of locale.LanguageOption to []web.LanguageOption
func ConvertToWebOptionSlice(localeOpts []locale.LanguageOption) []LanguageOption {
	webOpts := make([]LanguageOption, len(localeOpts))
	for i, opt := range localeOpts {
		webOpts[i] = ConvertToWebOption(opt)
	}
	return webOpts
}

// ConvertToWebOptionSliceWithEntries converts a slice of locale.LanguageOption to []web.LanguageOption
// using the entries to look up flag emojis from regions
func ConvertToWebOptionSliceWithEntries(localeOpts []locale.LanguageOption, entries []locale.LocaleEntry) []LanguageOption {
	webOpts := make([]LanguageOption, len(localeOpts))
	for i, opt := range localeOpts {
		webOpts[i] = ConvertToWebOptionWithEntries(opt, entries)
	}
	return webOpts
}

// ConvertToWebOptionWithEntries converts a locale.LanguageOption to a web.LanguageOption
// using the entries to look up the flag emoji from the region
func ConvertToWebOptionWithEntries(localeOpt locale.LanguageOption, entries []locale.LocaleEntry) LanguageOption {
	flagEmoji := extractFlagEmojiFromEntries(localeOpt, entries)

	return LanguageOption{
		Locale:        localeOpt.Locale,
		LanguageName:  localeOpt.LanguageName,
		LanguageLocal: localeOpt.LanguageLocal,
		FlagEmoji:     flagEmoji,
		CountryCode:   localeOpt.CountryCode,
		CountryName:   localeOpt.CountryName,
		FullLocale:    localeOpt.FullLocale,
		DisplayText:   localeOpt.DisplayText,
	}
}

// extractFlagEmojiFromEntries extracts the flag emoji from entries for a given locale option
func extractFlagEmojiFromEntries(localeOpt locale.LanguageOption, entries []locale.LocaleEntry) string {
	// Try to find the region by locale
	for _, entry := range entries {
		for _, region := range entry.Regions {
			if region.Locale == localeOpt.Locale {
				if region.Flag != "" {
					return region.Flag
				}
			}
		}
	}

	// Fallback to language code flag
	parts := strings.Split(localeOpt.Locale, "-")
	if len(parts) > 0 {
		langCode := parts[0]
		return locale.GetFlagForLanguageCode(langCode)
	}

	return "🏳️"
}

// extractFlagEmoji extracts the flag emoji from a locale option
// This is a simpler version that doesn't require entries
func extractFlagEmoji(localeOpt locale.LanguageOption) string {
	// Extract language code from locale
	parts := strings.Split(localeOpt.Locale, "-")
	if len(parts) > 0 {
		langCode := parts[0]
		return locale.GetFlagForLanguageCode(langCode)
	}

	return "🏳️"
}

// GetFlagImageURL returns the URL path for a flag image based on locale string
// Returns "/static/flags/JP.png" for "ja-JP" locale
// This is web-specific and not available in the locale package
func GetFlagImageURL(localeStr string) string {
	parts := strings.Split(localeStr, "-")
	if len(parts) == 2 {
		// Region code is the second part (e.g., "JP" from "ja-JP")
		return fmt.Sprintf("/static/flags/%s.png", parts[1])
	}

	// Try to find entry by language code and use first region
	entries, err := assets.ReadLocales()
	if err != nil {
		return ""
	}

	entry := locale.FindByLanguageCode(localeStr, entries)
	if entry != nil && len(entry.Regions) > 0 {
		return fmt.Sprintf("/static/flags/%s.png", entry.Regions[0].CountryCode)
	}

	return ""
}

// GetCommonLanguageOptions returns a list of common language options for quick selection
func GetCommonLanguageOptions() ([]LanguageOption, error) {
	entries, err := assets.ReadLocales()
	if err != nil {
		return nil, fmt.Errorf("failed to load languages: %w", err)
	}

	localeOpts := locale.GetCommonLanguages(entries)
	return ConvertToWebOptionSliceWithEntries(localeOpts, entries), nil
}

// GetAllLanguageOptions returns all language options sorted alphabetically
func GetAllLanguageOptions() ([]LanguageOption, error) {
	entries, err := assets.ReadLocales()
	if err != nil {
		return nil, fmt.Errorf("failed to load languages: %w", err)
	}

	localeOpts := locale.GetAllLanguages(entries)
	return ConvertToWebOptionSliceWithEntries(localeOpts, entries), nil
}

// GetLanguagesByCountry returns all languages available for a specific country
func GetLanguagesByCountry(countryCode string) ([]LanguageOption, error) {
	entries, err := assets.ReadLocales()
	if err != nil {
		return nil, fmt.Errorf("failed to load languages: %w", err)
	}

	localeOpts := locale.GetLanguagesByCountry(entries, countryCode)
	return ConvertToWebOptionSliceWithEntries(localeOpts, entries), nil
}

// FindLanguageByLocale finds a specific language option by locale string
func FindLanguageByLocale(localeStr string) (*LanguageOption, error) {
	entries, err := assets.ReadLocales()
	if err != nil {
		return nil, fmt.Errorf("failed to load languages: %w", err)
	}

	localeOpt, err := locale.FindLanguageByLocale(entries, localeStr)
	if err != nil {
		return nil, err
	}

	webOpt := ConvertToWebOptionWithEntries(*localeOpt, entries)
	return &webOpt, nil
}

// IsCommonLanguage checks if a language code is in the common languages list
func IsCommonLanguage(languageCode string) bool {
	return locale.IsCommonLanguage(languageCode)
}

// GetCommonLanguageCodes returns the list of common language codes
func GetCommonLanguageCodes() []string {
	return locale.GetCommonLanguageCodes()
}

// SearchLanguages searches and filters languages based on provided options
// This is kept for API compatibility but delegates to locale.SearchLanguages
func SearchLanguages(opts LanguageFilterOptions) ([]LanguageOption, error) {
	entries, err := assets.ReadLocales()
	if err != nil {
		return nil, fmt.Errorf("failed to load languages: %w", err)
	}

	localeOpts := locale.SearchLanguages(entries, locale.LanguageFilterOptions{
		CommonOnly: opts.CommonOnly,
		SearchTerm: opts.SearchTerm,
		Limit:      opts.Limit,
	})

	return ConvertToWebOptionSliceWithEntries(localeOpts, entries), nil
}
