package tui

import (
	"fmt"
	"strings"

	"gitgud.io/mike/mpv-manager/pkg/config"
	"gitgud.io/mike/mpv-manager/pkg/constants"
	"gitgud.io/mike/mpv-manager/pkg/version"
)

type configBackupItem struct {
	backup *version.ConfigBackupItem
}

func (c configBackupItem) Title() string {
	return fmt.Sprintf("Restore %s MPV Config", c.backup.BackupName)
}

func (c configBackupItem) Description() string {
	return fmt.Sprintf("From: %s - %s", c.backup.BackupDate, c.backup.BackupPath)
}

func (c configBackupItem) FilterValue() string {
	return c.backup.BackupName
}

type PlatformInfo struct {
	AppVersion   string
	OSType       string
	Arch         string
	Distro       string
	DistroFamily string
	CPU          string
	CPUVendor    string
	GPU          string
	GPUVendor    string
	HWA          string
}

type menuItem struct {
	id          string
	title       string
	description string
	recommended bool
	methodID    string // Used for badge type determination in install menu
}

func (m menuItem) Title() string {
	title := m.title
	// If methodID is set, use badge type based on method ID
	if m.methodID != "" {
		badge := getBadgeForMethodID(m.methodID)
		if badge != "" {
			title += " " + recommendedBadgeStyle.Render(badge)
		}
	} else if m.recommended {
		title += " " + recommendedBadgeStyle.Render("[ Recommended ]")
	}
	return title
}

func (m menuItem) Description() string {
	return m.description
}

func (m menuItem) FilterValue() string {
	return m.title
}

type hwaOptionItem struct {
	id          string
	title       string
	description string
	recommended bool
}

func (h hwaOptionItem) Title() string {
	title := h.title
	if h.recommended {
		title += " " + recommendedBadgeStyle.Render("[ Recommended ]")
	}
	return title
}

func (h hwaOptionItem) Description() string {
	return h.description
}

func (h hwaOptionItem) FilterValue() string {
	return h.title
}

type uninstallAppItem struct {
	app *config.InstalledApp
}

func (u uninstallAppItem) Title() string {
	return u.app.AppName
}

func (u uninstallAppItem) Description() string {
	// Get human-readable type name
	var typeDesc string
	switch u.app.AppType {
	case "app":
		typeDesc = "App"
	case "executable":
		typeDesc = "Executable"
	case "package-manager":
		typeDesc = "Package Manager"
	case "flatpak":
		typeDesc = "Flatpak"
	case "frontend":
		typeDesc = "Frontend"
	default:
		typeDesc = u.app.AppType
	}

	// Build description
	var descBuilder strings.Builder
	descBuilder.WriteString(fmt.Sprintf("Type: %s", typeDesc))

	// Add install method for reference
	if u.app.InstallMethod != "" {
		descBuilder.WriteString(fmt.Sprintf(" | Method: %s", u.app.InstallMethod))
	}

	// Add path only if it exists and is not empty
	if u.app.InstallPath != "" {
		descBuilder.WriteString(fmt.Sprintf(" | Path: %s", u.app.InstallPath))
	}

	return descBuilder.String()
}

func (u uninstallAppItem) FilterValue() string {
	return u.app.AppName
}

type updateItem struct {
	AppName          string
	CurrentVersion   string
	AvailableVersion string
	UpdateType       string
	PackageManager   string
	MethodID         string
}

func (u updateItem) Title() string {
	return u.AppName
}

func (u updateItem) Description() string {
	if u.UpdateType == "package-update" {
		return fmt.Sprintf("Check via %s", u.PackageManager)
	}
	return fmt.Sprintf("Current: %s - Available: %s", u.CurrentVersion, u.AvailableVersion)
}

func (u updateItem) FilterValue() string {
	return u.AppName
}

type installProgressMsg struct{ progress int }

type downloadProgressMsg struct {
	written int64
	total   int64
}

type installSuccessMsg struct{}

type installErrorMsg struct{ err error }

type versionCheckMsg struct {
	result *version.VersionCheckResult
}

type updateCheckResultMsg struct {
	result *version.UpdateCheckResult
}

type cmdStartMsg struct {
	command string
}

type cmdOutputMsg struct {
	line    string
	isError bool
}

type cmdDoneMsg struct {
	err error
}

type tickMsg struct{}

type saveChannelsMsg struct {
	outputChan   <-chan string
	installDone  <-chan error
	progressChan <-chan downloadProgressMsg
}

type uninstallAppsLoadedMsg struct {
	apps []config.InstalledApp
}

type refreshMenuMsg struct{}

// presetApplyMsg is sent when a hotkey preset has been applied (or failed)
type presetApplyMsg struct {
	presetID string
	preset   string // Human-readable preset name
	err      error
}

type MethodMetadata struct {
	Type    string
	AppName string
	Version string
}

// uiOptionItem represents a UI overlay option for MPV
type uiOptionItem struct {
	id          string
	title       string
	description string
	recommended bool
}

func (u uiOptionItem) Title() string {
	title := u.title
	if u.recommended {
		title += " " + recommendedBadgeStyle.Render("[ Recommended ]")
	}
	return title
}

func (u uiOptionItem) Description() string {
	return u.description
}

func (u uiOptionItem) FilterValue() string {
	return u.title
}

var MethodIDMetadata = map[string]MethodMetadata{
	constants.MethodMPVBinary:        {Type: "exe-binary", AppName: "mpv"},
	constants.MethodMPVBinaryV3:      {Type: "exe-binary", AppName: "mpv"},
	constants.MethodMPCQT:            {Type: "exe-installer", AppName: "MPC-QT"},
	constants.MethodMPVApp:           {Type: "app", AppName: "MPV", Version: "mpv"},
	constants.MethodMPVBrew:          {Type: "brew", AppName: "mpv"},
	constants.MethodIINA:             {Type: "app", AppName: "IINA", Version: "iina"},
	constants.MethodMPVFlatpak:       {Type: "flatpak", AppName: "io.mpv.Mpv"},
	constants.MethodCelluloidFlatpak: {Type: "flatpak", AppName: "io.github.celluloid_player.Celluloid"},
	constants.MethodMPVPackage:       {Type: "package-manager", AppName: "mpv"},
	constants.MethodCelluloidPackage: {Type: "package-manager", AppName: "celluloid"},
}

// mpvMethodIDs contains method IDs for MPV-based players (Best Playback badge)
var mpvMethodIDs = map[string]bool{
	constants.MethodMPVBinary:   true,
	constants.MethodMPVBinaryV3: true,
	constants.MethodMPVApp:      true,
	constants.MethodMPVBrew:     true,
	constants.MethodMPVFlatpak:  true,
	constants.MethodMPVPackage:  true,
}

// guiMethodIDs contains method IDs for GUI frontends (Easy UI badge)
var guiMethodIDs = map[string]bool{
	constants.MethodCelluloidFlatpak: true,
	constants.MethodCelluloidPackage: true,
	constants.MethodIINA:             true,
}

// mpcHcMethodIDs contains method IDs for MPC-HC style UI (MPC-HC UI badge)
var mpcHcMethodIDs = map[string]bool{
	constants.MethodMPCQT: true,
}

// getBadgeForMethodID returns the badge text for an install method ID
func getBadgeForMethodID(methodID string) string {
	if mpvMethodIDs[methodID] {
		return "[ Best Playback ]"
	}
	if mpcHcMethodIDs[methodID] {
		return "[ MPC-HC UI ]"
	}
	if guiMethodIDs[methodID] {
		return "[ Easy UI ]"
	}
	return ""
}

// isMPVMethod returns true if the method ID is for an MPV-based player
func isMPVMethod(methodID string) bool {
	return mpvMethodIDs[methodID]
}
