package ui

import (
	"epochsilicon/pkg/log"
	"net/url"
	"strings"
	"time"

	"epochsilicon/pkg/launcher"
	"epochsilicon/pkg/patching"
	"epochsilicon/pkg/service"
	"epochsilicon/pkg/utils"

	"fyne.io/fyne/v2"
	"fyne.io/fyne/v2/container"
	"fyne.io/fyne/v2/widget"
)

// createOptionsComponents initializes all option-related UI components
func createOptionsComponents() {
	// Load preferences for initial values
	prefs, _ := utils.LoadPrefs()

	metalHudCheckbox = widget.NewCheck("Enable Metal Hud (show FPS)", func(checked bool) {
		launcher.EnableMetalHud = checked
		// Save to preferences
		prefs, _ := utils.LoadPrefs()
		prefs.EnableMetalHud = checked
		utils.SavePrefs(prefs)
		log.Debugf("Metal HUD enabled: %v", launcher.EnableMetalHud)
	})
	metalHudCheckbox.SetChecked(prefs.EnableMetalHud)
	launcher.EnableMetalHud = prefs.EnableMetalHud

	showTerminalCheckbox = widget.NewCheck("Show Terminal", func(checked bool) {
		// Save to preferences
		prefs, _ := utils.LoadPrefs()
		prefs.ShowTerminalNormally = checked
		utils.SavePrefs(prefs)
		log.Debugf("Show terminal normally: %v", checked)
	})
	showTerminalCheckbox.SetChecked(prefs.ShowTerminalNormally)

	advancedLoggingCheckbox = widget.NewCheck("Advanced Logging", func(checked bool) {
		// Save to preferences
		prefs, _ := utils.LoadPrefs()
		prefs.AdvancedLogging = checked
		utils.SavePrefs(prefs)
		log.Debugf("Advanced logging set to %v", checked)

		if checked {
			log.SetLevelDebug()
		} else {
			log.SetLevelInfo()
		}
	})
	advancedLoggingCheckbox.SetChecked(prefs.AdvancedLogging)

	autoDeleteWdbCheckbox = widget.NewCheck("Auto-delete WDB directory on launch", func(checked bool) {
		launcher.AutoDeleteWdb = checked
		// Save to preferences
		prefs, _ := utils.LoadPrefs()
		prefs.AutoDeleteWdb = checked
		utils.SavePrefs(prefs)
		log.Debugf("Auto-delete WDB enabled: %v", launcher.AutoDeleteWdb)
	})
	autoDeleteWdbCheckbox.SetChecked(prefs.AutoDeleteWdb)
	launcher.AutoDeleteWdb = prefs.AutoDeleteWdb

	// Create Wine registry Option-as-Alt buttons and status
	createWineRegistryComponents()

	// Load environment variables from preferences
	if prefs.EnvironmentVariables != "" {
		launcher.CustomEnvVars = prefs.EnvironmentVariables
	}

	envVarsEntry = widget.NewEntry()
	envVarsEntry.SetPlaceHolder(`Custom environment variables (KEY=VALUE format)`)
	envVarsEntry.SetText(launcher.CustomEnvVars)
	envVarsEntry.OnChanged = func(text string) {
		launcher.CustomEnvVars = text
		// Save to preferences
		prefs, _ := utils.LoadPrefs()
		prefs.EnvironmentVariables = text
		utils.SavePrefs(prefs)
		log.Debugf("Environment variables updated: %v", launcher.CustomEnvVars)
	}
}

// createPatchingButtons creates all patching-related buttons
func createPatchingButtons(myWindow fyne.Window) {
	patchEpochButton = widget.NewButton("Patch Epoch", func() {
		patching.PatchEpoch(myWindow, UpdateAllStatuses)
	})
	unpatchEpochButton = widget.NewButton("Unpatch Epoch", func() {
		patching.UnpatchEpoch(myWindow, UpdateAllStatuses)
	})
	patchCrossOverButton = widget.NewButton("Patch CrossOver", func() {
		patching.PatchCrossOver(myWindow, UpdateAllStatuses)
	})
	unpatchCrossOverButton = widget.NewButton("Unpatch CrossOver", func() {
		patching.UnpatchCrossOver(myWindow, UpdateAllStatuses)
	})
}

// createServiceButtons creates service-related buttons
func createServiceButtons(myWindow fyne.Window) {
	startServiceButton = widget.NewButton("Start Service", func() {
		service.StartRosettaX87Service(myWindow, UpdateAllStatuses)
	})
	stopServiceButton = widget.NewButton("Stop Service", func() {
		service.StopRosettaX87Service(myWindow, UpdateAllStatuses)
	})
}

// createLaunchButton creates the legacy launch button
func createLaunchButton(myWindow fyne.Window) {
	launchButton = widget.NewButton("Launch Game", func() {
		launcher.LaunchGame(myWindow)
	})
}

// createBottomBar creates the bottom bar with Options, GitHub, and PLAY buttons
func createBottomBar(myWindow fyne.Window) fyne.CanvasObject {
	// Set the current window for popup functionality
	currentWindow = myWindow

	// Options button
	optionsButton := widget.NewButton("Options", func() {
		showOptionsPopup()
	})

	// Troubleshooting button
	troubleshootingButton = widget.NewButton("Troubleshooting", func() {
		showTroubleshootingPopup()
	})

	// Git button
	gitButton := widget.NewButton("Website", func() {
		githubURL := "https://git.burkey.co/eburk/epochsilicon"
		parsedURL, err := url.Parse(githubURL)
		if err != nil {
			log.Debugf("Error parsing git URL: %v", err)
			return
		}
		fyne.CurrentApp().OpenURL(parsedURL)
	})
	playButtonText = widget.NewRichTextFromMarkdown("# PLAY")
	playButtonText.Wrapping = fyne.TextWrapOff

	playButton = widget.NewButton("", func() {
		launcher.LaunchGame(myWindow)
	})
	playButton.Importance = widget.HighImportance
	playButton.Disable()

	playButtonWithText := container.NewStack(
		playButton,
		container.NewCenter(playButtonText),
	)

	leftButtons := container.NewHBox(
		optionsButton,
		troubleshootingButton,
		gitButton,
	)

	// Create the large play button with fixed size
	buttonWidth := float32(120)
	buttonHeight := float32(80)
	playButtonWithText.Resize(fyne.NewSize(buttonWidth, buttonHeight))

	// Create a container for the play button that ensures it's positioned at bottom-right
	playButtonContainer := container.NewWithoutLayout(playButtonWithText)
	playButtonContainer.Resize(fyne.NewSize(buttonWidth+40, buttonHeight+20)) // Add padding

	playButtonWithText.Move(fyne.NewPos(-50, -32))

	// Use border layout to position elements
	bottomContainer := container.NewBorder(
		nil,                 // top
		nil,                 // bottom
		leftButtons,         // left
		playButtonContainer, // right - our large play button
		nil,                 // center
	)

	return container.NewPadded(bottomContainer)
}

// createWineRegistryComponents creates Wine registry Option-as-Alt buttons and status
func createWineRegistryComponents() {
	// Create status label to show current state
	optionAsAltStatusLabel = widget.NewRichText()

	// Create enable button
	enableOptionAsAltButton = widget.NewButton("Enable", func() {
		enableOptionAsAltButton.Disable()
		disableOptionAsAltButton.Disable()
		remapOperationInProgress = true

		// Show loading state in status label
		fyne.Do(func() {
			optionAsAltStatusLabel.ParseMarkdown("**Remap Option key as Alt key:** Enabling...")
			startPulsingEffect()
		})

		// Run in goroutine to avoid blocking UI
		go func() {
			defer func() {
				remapOperationInProgress = false
			}()

			if err := utils.SetOptionAsAltEnabled(true); err != nil {
				log.Debugf("Failed to enable Option-as-Alt mapping: %v", err)
				// Update UI on main thread
				fyne.Do(func() {
					stopPulsingEffect()
					optionAsAltStatusLabel.ParseMarkdown("**Remap Option key as Alt key:** Enable Failed")
				})
				time.Sleep(2 * time.Second) // Show error briefly
			} else {
				log.Debugf("Successfully enabled Option-as-Alt mapping")
				// Update preferences
				prefs, _ := utils.LoadPrefs()
				prefs.RemapOptionAsAlt = true
				utils.SavePrefs(prefs)
			}

			// Update UI on main thread
			fyne.Do(func() {
				stopPulsingEffect()
				updateWineRegistryStatusWithMethod(true) // Use Wine command for accurate check after modifications
			})
		}()
	})

	// Create disable button
	disableOptionAsAltButton = widget.NewButton("Disable", func() {
		enableOptionAsAltButton.Disable()
		disableOptionAsAltButton.Disable()
		remapOperationInProgress = true

		// Show loading state in status label
		fyne.Do(func() {
			optionAsAltStatusLabel.ParseMarkdown("**Remap Option key as Alt key:** Disabling...")
			startPulsingEffect()
		})

		// Run in goroutine to avoid blocking UI
		go func() {
			defer func() {
				remapOperationInProgress = false
			}()

			if err := utils.SetOptionAsAltEnabled(false); err != nil {
				log.Debugf("Failed to disable Option-as-Alt mapping: %v", err)
				// Update UI on main thread
				fyne.Do(func() {
					stopPulsingEffect()
					optionAsAltStatusLabel.ParseMarkdown("**Remap Option key as Alt key:** Disable Failed")
				})
				time.Sleep(2 * time.Second) // Show error briefly
			} else {
				log.Debugf("Successfully disabled Option-as-Alt mapping")
				// Update preferences
				prefs, _ := utils.LoadPrefs()
				prefs.RemapOptionAsAlt = false
				utils.SavePrefs(prefs)
			}

			// Update UI on main thread
			fyne.Do(func() {
				stopPulsingEffect()
				updateWineRegistryStatusWithMethod(true) // Use Wine command for accurate check after modifications
			})
		}()
	})

	// Style the buttons similar to other action buttons
	enableOptionAsAltButton.Importance = widget.MediumImportance
	disableOptionAsAltButton.Importance = widget.MediumImportance

	// Initialize status and button states
	updateWineRegistryStatus()
}

// updateWineRegistryStatus updates the Wine registry status label and button states
func updateWineRegistryStatus() {
	updateWineRegistryStatusWithMethod(false)
}

// updateWineRegistryStatusWithMethod updates status with choice of checking method
func updateWineRegistryStatusWithMethod(useWineCommand bool) {
	if useWineCommand {
		// Use Wine command for accurate check after modifications
		currentWineRegistryEnabled = utils.CheckOptionAsAltEnabled()
	} else {
		// Use fast file-based check for regular status updates
		currentWineRegistryEnabled = utils.CheckOptionAsAltEnabledFast()
	}

	// Update UI with simple white text
	if currentWineRegistryEnabled {
		optionAsAltStatusLabel.ParseMarkdown("**Remap Option key as Alt key:** Enabled")
	} else {
		optionAsAltStatusLabel.ParseMarkdown("**Remap Option key as Alt key:** Disabled")
	}

	// Update button states based on current status
	if currentWineRegistryEnabled {
		// If enabled, only show disable button as clickable
		enableOptionAsAltButton.Disable()
		disableOptionAsAltButton.Enable()
	} else {
		// If disabled, only show enable button as clickable
		enableOptionAsAltButton.Enable()
		disableOptionAsAltButton.Disable()
	}
}

// startPulsingEffect starts a pulsing animation for the status label during loading
func startPulsingEffect() {
	if pulsingActive {
		return // Already pulsing
	}

	pulsingActive = true
	pulsingTicker = time.NewTicker(500 * time.Millisecond)

	go func() {
		dots := ""

		for pulsingActive {
			<-pulsingTicker.C
			if pulsingActive {
				// Cycle through different dot patterns for visual effect
				switch len(dots) {
				case 0:
					dots = "."
				case 1:
					dots = ".."
				case 2:
					dots = "..."
				default:
					dots = ""
				}

				// Update the label with pulsing dots
				fyne.Do(func() {
					if pulsingActive && optionAsAltStatusLabel != nil {
						// Use the dots directly in the status text
						if strings.Contains(optionAsAltStatusLabel.String(), "Enabling") {
							optionAsAltStatusLabel.ParseMarkdown("**Remap Option key as Alt key:** Enabling" + dots)
						} else if strings.Contains(optionAsAltStatusLabel.String(), "Disabling") {
							optionAsAltStatusLabel.ParseMarkdown("**Remap Option key as Alt key:** Disabling" + dots)
						}
					}
				})
			}
		}
	}()
}

// stopPulsingEffect stops the pulsing animation
func stopPulsingEffect() {
	if !pulsingActive {
		return
	}

	pulsingActive = false
	if pulsingTicker != nil {
		pulsingTicker.Stop()
		pulsingTicker = nil
	}
}

// updateRecommendedSettingsButton updates the state of the recommended settings button
func updateRecommendedSettingsButton() {
	if applyRecommendedSettingsButton == nil {
		return
	}

	// Check if all recommended settings are already applied
	if launcher.CheckRecommendedSettings() {
		applyRecommendedSettingsButton.Disable()
		applyRecommendedSettingsButton.SetText("Settings applied")
	} else {
		applyRecommendedSettingsButton.Enable()
		applyRecommendedSettingsButton.SetText("Apply recommended settings")
	}

	// Help button should always be enabled
	if recommendedSettingsHelpButton != nil {
		recommendedSettingsHelpButton.Enable()
	}
}

// showRecommendedSettingsHelpPopup shows a popup explaining the recommended graphics settings
func showRecommendedSettingsHelpPopup() {
	if currentWindow == nil {
		return
	}

	// Create help content
	helpTitle := widget.NewRichTextFromMarkdown("# 📋 Recommended Graphics Settings")

	// Create individual setting labels for better formatting
	settingsTitle := widget.NewLabel("The following settings will be applied to your Config.wtf file:")
	settingsTitle.TextStyle = fyne.TextStyle{Bold: true}

	setting1 := widget.NewLabel("• Terrain Distance (farclip): 177 - Reduces CPU overhead - more fps")
	setting2 := widget.NewLabel("• Vertex Animation Shaders (M2UseShaders): Enabled - Prevents graphic glitches")
	setting3 := widget.NewLabel("• Multisampling (gxMultisample): 2x - Makes portraits load properly")

	settingsContainer := container.NewVBox(
		settingsTitle,
		widget.NewSeparator(),
		setting1,
		setting2,
		setting3,
		widget.NewSeparator(),
	)

	// Create OK button
	okButton := widget.NewButton("OK", func() {
		// This will be set when the popup is created
	})
	okButton.Importance = widget.MediumImportance

	// Create help content container
	helpContentContainer := container.NewVBox(
		container.NewCenter(helpTitle),
		widget.NewSeparator(),
		settingsContainer,
		widget.NewSeparator(),
		container.NewCenter(okButton),
	)

	// Calculate popup size
	windowSize := currentWindow.Content().Size()
	popupWidth := windowSize.Width * 3 / 4
	popupHeight := windowSize.Height * 3 / 4

	// Create the help popup
	helpPopup := widget.NewModalPopUp(container.NewPadded(helpContentContainer), currentWindow.Canvas())
	helpPopup.Resize(fyne.NewSize(popupWidth, popupHeight))

	// Set the OK button action to hide the help popup
	okButton.OnTapped = func() {
		helpPopup.Hide()
	}

	helpPopup.Show()
}
