package ui

import (
	"epochsilicon/pkg/log"
	"epochsilicon/pkg/patching"
	"errors"
	"fmt"
	"fyne.io/fyne/v2"
	"fyne.io/fyne/v2/container"
	"fyne.io/fyne/v2/dialog"
	"fyne.io/fyne/v2/widget"
	"os"
	"os/exec"
	"path/filepath"
	"strings"

	"howett.net/plist"

	"epochsilicon/pkg/paths"
	"epochsilicon/pkg/utils"
)

// showOptionsPopup creates and shows an integrated popup window for options
func showOptionsPopup() {
	if currentWindow == nil {
		return
	}

	// Create General tab content
	generalTitle := widget.NewLabel("General Settings")
	generalTitle.TextStyle = fyne.TextStyle{Bold: true}

	generalContainer := container.NewVBox(
		generalTitle,
		widget.NewSeparator(),
		advancedLoggingCheckbox,
		metalHudCheckbox,
		showTerminalCheckbox,
		autoDeleteWdbCheckbox,
		widget.NewSeparator(),
		container.NewBorder(nil, nil, nil, container.NewHBox(enableOptionAsAltButton, disableOptionAsAltButton), optionAsAltStatusLabel),
	)

	// Create Environment Variables tab content
	envVarsTitle := widget.NewLabel("Environment Variables")
	envVarsTitle.TextStyle = fyne.TextStyle{Bold: true}
	envVarsContainer := container.NewVBox(
		envVarsTitle,
		widget.NewSeparator(),
		envVarsEntry,
	)

	// Create tabs
	tabs := container.NewAppTabs(
		container.NewTabItem("General", container.NewScroll(generalContainer)),
		container.NewTabItem("Environment", container.NewScroll(envVarsContainer)),
	)

	// Set tab location to top
	tabs.SetTabLocation(container.TabLocationTop)

	// Create close button
	closeButton := widget.NewButton("Close", func() {
		// This will be set when the popup is created
	})

	// Create the popup content with close button
	popupContent := container.NewBorder(
		nil,                              // top
		container.NewCenter(closeButton), // bottom
		nil,                              // left
		nil,                              // right
		container.NewPadded(tabs),        // center
	)

	// Get the window size and calculate 2/3 size
	windowSize := currentWindow.Content().Size()
	popupWidth := windowSize.Width * 5 / 6
	popupHeight := windowSize.Height * 9 / 10

	// Create a modal popup
	popup := widget.NewModalPopUp(popupContent, currentWindow.Canvas())
	popup.Resize(fyne.NewSize(popupWidth, popupHeight))

	// Set the close button action to hide the popup
	closeButton.OnTapped = func() {
		if remapOperationInProgress {
			// Show warning popup instead of closing
			showRemapWarningPopup()
		} else {
			popup.Hide()
		}
	}

	popup.Show()
}

// showRemapWarningPopup shows a warning popup when user tries to close options during remap operation
func showRemapWarningPopup() {
	if currentWindow == nil {
		return
	}

	// Create warning content
	warningTitle := widget.NewRichTextFromMarkdown("# ⚠️ Please Wait")
	warningMessage := widget.NewRichTextFromMarkdown("**Remap operation is in progress.**\n\nThe wine registry is being modified. This will take a moment.\n\nPlease wait for the operation to complete before closing the options.")

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

	// Create warning content container
	warningContent := container.NewVBox(
		container.NewCenter(warningTitle),
		widget.NewSeparator(),
		warningMessage,
		widget.NewSeparator(),
		container.NewCenter(okButton),
	)

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

	// Create the warning popup
	warningPopup := widget.NewModalPopUp(container.NewPadded(warningContent), currentWindow.Canvas())
	warningPopup.Resize(fyne.NewSize(popupWidth, popupHeight))

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

	warningPopup.Show()
}

// showTroubleshootingPopup creates and shows a popup window for troubleshooting actions
func showTroubleshootingPopup() {
	if currentWindow == nil {
		return
	}

	// --- CrossOver Version Check ---
	crossoverVersion := getCrossoverVersion(paths.CrossoverPath)
	var crossoverStatusShort *widget.Label
	var crossoverStatusDetail *widget.Label
	if crossoverVersion == "" {
		crossoverStatusShort = widget.NewLabel("Not found")
		crossoverStatusDetail = widget.NewLabel("")
	} else if isCrossoverVersionRecommended(crossoverVersion) {
		crossoverStatusShort = widget.NewLabelWithStyle("✔ "+crossoverVersion, fyne.TextAlignTrailing, fyne.TextStyle{Bold: true})
		crossoverStatusDetail = widget.NewLabelWithStyle("✔ Recommended version of CrossOver installed", fyne.TextAlignLeading, fyne.TextStyle{Italic: true})
	} else {
		crossoverStatusShort = widget.NewLabelWithStyle("⚠️ "+crossoverVersion, fyne.TextAlignTrailing, fyne.TextStyle{Italic: true})
		crossoverStatusDetail = widget.NewLabelWithStyle("⚠️ Please update to CrossOver 25.0.1 or later!", fyne.TextAlignLeading, fyne.TextStyle{Italic: true})
	}
	crossoverStatusDetail.Wrapping = fyne.TextWrapWord

	// --- Delete WDB Directory ---
	wdbDeleteButton = widget.NewButton("Delete", func() {
		wdbPath := filepath.Join(paths.EpochPath, "WDB")
		if !utils.DirExists(wdbPath) {
			dialog.ShowInformation("WDB Not Found", "No WDB directory found in your Epoch folder.", currentWindow)
			return
		}
		dialog.NewConfirm("Delete WDB Directory", "Are you sure you want to delete the WDB directory? This will remove all cached data. No important data will be lost.", func(confirm bool) {
			if confirm {
				err := os.RemoveAll(wdbPath)
				if err != nil {
					dialog.ShowError(fmt.Errorf("Failed to delete WDB: %v", err), currentWindow)
				} else {
					dialog.ShowInformation("WDB Deleted", "WDB directory deleted successfully.", currentWindow)
				}
			}
		}, currentWindow).Show()
	})

	// --- Delete Wine Prefixes ---
	wineDeleteButton = widget.NewButton("Delete", func() {
		homeDir, _ := os.UserHomeDir()
		userWine := filepath.Join(homeDir, ".wine")
		turtleWine := filepath.Join(paths.EpochPath, ".wine")
		msg := "Are you sure you want to delete the following Wine prefixes?\n\n- " + userWine + "\n- " + turtleWine + "\n\nThis cannot be undone."
		dialog.NewConfirm("Delete Wine Prefixes", msg, func(confirm bool) {
			if confirm {
				err1 := os.RemoveAll(userWine)
				err2 := os.RemoveAll(turtleWine)
				if err1 != nil && !os.IsNotExist(err1) {
					dialog.ShowError(fmt.Errorf("Failed to delete ~/.wine: %v", err1), currentWindow)
					return
				}
				if err2 != nil && !os.IsNotExist(err2) {
					dialog.ShowError(fmt.Errorf("Failed to delete Epoch/.wine: %v", err2), currentWindow)
					return
				}
				dialog.ShowInformation("Wine Prefixes Deleted", "Wine prefixes deleted successfully.", currentWindow)
			}
		}, currentWindow).Show()
	})

	// --- Build Rosettax87 Locally ---
	buildRosettaButton = widget.NewButton("Build", func() {
		msg := "Building rosettax87 on your computer may speed up launch times. This requires xcode-commandline-tools and Cmake to be installed. See the instructions at https://git.burkey.co/eburk/epochsilicon/README.md\n\n"
		msg += "Click YES to start the build process. This could take up to a minute depending on the the speed of your Mac. A popup will let you know when the files have been built and copied to the right place."
		dialog.NewConfirm("Build rosettax87", msg, func(confirm bool) {
			if confirm {
				// Check for dependencies
				if err := exec.Command(patching.ClangPath, "--version").Run(); err != nil {
					m := fmt.Errorf("xcode command line tools are not installed on your computer. Click the Website button in the app and read the instructions on building rosettax87 before trying again. Error: %v", err)
					log.Error(m.Error())
					dialog.ShowError(m, currentWindow)
					return
				}
				if err := exec.Command(patching.CmakePath, "--version").Run(); err != nil {
					m := fmt.Errorf("Cmake is not installed on your computer. Click the Website button in the app and read the instructions on building rosettax87 before trying again. Error: %v", err)
					log.Error(m.Error())
					dialog.ShowError(m, currentWindow)
					return
				}

				xPath, lPath, err := patching.BuildRosetta()
				if err != nil {
					m := fmt.Errorf("Error building rosettax87: %v\nClick Website for information on getting help", err)
					log.Error(m.Error())
					dialog.ShowError(m, currentWindow)
					return
				}

				d := filepath.Join(paths.EpochPath, "rosettax87")
				if err = os.RemoveAll(d); err != nil {
					m := fmt.Errorf("Error removing existing rosettax87 directory: %v", err)
					log.Error(m.Error())
					dialog.ShowError(m, currentWindow)
					return
				}

				if err = os.MkdirAll(d, 0755); err != nil {
					m := fmt.Errorf("Error creating existing rosettax87 directory: %v", err)
					log.Error(m.Error())
					dialog.ShowError(m, currentWindow)
					return
				}

				pathMap := map[string]string{
					xPath: filepath.Join(paths.EpochPath, "rosettax87", "rosettax87"),
					lPath: filepath.Join(paths.EpochPath, "rosettax87", "libRuntimeRosettax87"),
				}

				for srcPath, destPath := range pathMap {
					fBytes, err := os.ReadFile(srcPath)
					if err != nil {
						errMsg := fmt.Sprintf("failed to read source file %s: %v", srcPath, err)
						dialog.ShowError(errors.New(errMsg), currentWindow)
						log.Debug(errMsg)
						return
					}

					err = os.WriteFile(destPath, fBytes, 0755)
					if err != nil {
						errMsg := fmt.Sprintf("failed to write file %s: %v", destPath, err)
						dialog.ShowError(errors.New(errMsg), currentWindow)
						log.Debug(errMsg)
						return
					}
					log.Debugf("Successfully copied %s to %s", srcPath, destPath)
				}
				dialog.ShowInformation("Build Successful", "Rosettax87 installed successfully.", currentWindow)
			}
		}, currentWindow).Show()
	})

	troubleshootingTitle := widget.NewLabel("Troubleshooting")
	troubleshootingTitle.TextStyle = fyne.TextStyle{Bold: true}

	rowCrossover := container.NewBorder(nil, nil, widget.NewLabel("CrossOver version:"), crossoverStatusShort, nil)
	rowWDB := container.NewBorder(nil, nil, widget.NewLabel("Delete WDB directory (cache):"), wdbDeleteButton, nil)
	rowWine := container.NewBorder(nil, nil, widget.NewLabel("Delete Wine prefixes (~/.wine & Epoch/.wine):"), wineDeleteButton, nil)
	rowBuildRosetta := container.NewBorder(nil, nil, widget.NewLabel("Build Rosettax87 locally:"), buildRosettaButton, nil)
	appMgmtNote := widget.NewLabel("Please ensure EpochSilicon is enabled in System Settings > Privacy & Security > App Management.")
	appMgmtNote.Wrapping = fyne.TextWrapWord
	appMgmtNote.TextStyle = fyne.TextStyle{Italic: true}

	content := container.NewVBox(
		troubleshootingTitle,
		widget.NewSeparator(),
		rowCrossover,
		crossoverStatusDetail,
		rowWDB,
		rowWine,
		rowBuildRosetta,
		appMgmtNote,
	)

	scrollContainer := container.NewScroll(content)

	troubleshootingCloseButton = widget.NewButton("Close", func() {})

	popupContent := container.NewBorder(
		nil, // top
		container.NewCenter(troubleshootingCloseButton), // bottom
		nil,                                  // left
		nil,                                  // right
		container.NewPadded(scrollContainer), // center
	)

	windowSize := currentWindow.Content().Size()
	popupWidth := windowSize.Width * 5 / 6
	popupHeight := windowSize.Height * 5 / 6

	popup := widget.NewModalPopUp(popupContent, currentWindow.Canvas())
	popup.Resize(fyne.NewSize(popupWidth, popupHeight))

	troubleshootingCloseButton.OnTapped = func() {
		popup.Hide()
	}

	popup.Show()
}

// getCrossoverVersion reads the Info.plist and returns the version string, or "" if not found
func getCrossoverVersion(appPath string) string {
	if appPath == "" {
		return ""
	}
	plistPath := filepath.Join(appPath, "Contents", "Info.plist")
	f, err := os.Open(plistPath)
	if err != nil {
		return ""
	}
	defer f.Close()
	var data struct {
		Version string `plist:"CFBundleShortVersionString"`
	}
	decoder := plist.NewDecoder(f)
	if err := decoder.Decode(&data); err != nil {
		return ""
	}
	return data.Version
}

// isCrossoverVersionRecommended returns true if version >= 25.0.1
func isCrossoverVersionRecommended(version string) bool {
	parts := strings.Split(version, ".")
	if len(parts) < 3 {
		return false
	}
	major := parts[0]
	minor := parts[1]
	patch := parts[2]
	if major > "25" {
		return true
	}
	if major == "25" && minor >= "0" && patch >= "1" {
		return true
	}
	return false
}
