package desktop

import (
	"bufio"
	"log/slog"
	"os"
	"path/filepath"
	"strings"
)

const DirLauncherDest = "/usr/share/applications/"

func GetXPackageName(path string) (string, error) {
	file, err := os.Open(path)
	if err != nil {
		return "", err
	}
	defer func(file *os.File) {
		err := file.Close()
		if err != nil {
			slog.Error("failed to close file", "path", path, "err", err)
		}
	}(file)

	scanner := bufio.NewScanner(file)
	for scanner.Scan() {
		line := scanner.Text()
		if strings.HasPrefix(line, "X-Parrot-Package") {
			if parts := strings.SplitN(line, "=", 2); len(parts) == 2 {
				return strings.TrimSpace(parts[1]), nil
			}
		}
	}

	if err := scanner.Err(); err != nil {
		slog.Error("failed to read desktop file", "path", path, "err", err)
		return "", err
	}
	return "", nil
}

func IsManaged(path string) bool {
	pkg, err := GetXPackageName(path)
	return err == nil && pkg != ""
}

func FixOldLaunchers(fileName string) {
	// If a new launcher (e.g., "serv-tool.desktop") is installed, this function
	// ensures that the older version (e.g., "parrot-toolname.desktop") is removed
	// to avoid duplicates in the application menu.

	newNamePrefixes := []string{"serv-"}
	for _, checkName := range newNamePrefixes {
		if suffix, found := strings.CutPrefix(fileName, checkName); found {
			oldFileName := "parrot-" + suffix
			destPath := filepath.Join(DirLauncherDest, oldFileName)
			if _, err := os.Stat(destPath); err == nil {
				if err := os.Remove(destPath); err != nil {
					slog.Error("could not remove duplicate launcher", "destPath", destPath, "err", err)
				}
			}
			break
		}
	}
}

func CopyFile(src, dst string) error {
	source, err := os.Open(src)
	if err != nil {
		return err
	}
	defer func(source *os.File) {
		err := source.Close()
		if err != nil {
			slog.Error("failed to close file", "src", src, "err", err)
		}
	}(source)

	destination, err := os.Create(dst)
	if err != nil {
		return err
	}
	defer func(destination *os.File) {
		err := destination.Close()
		if err != nil {
			slog.Error("failed to close file", "dst", dst, "err", err)
		}
	}(destination)

	scanner := bufio.NewScanner(source)
	writer := bufio.NewWriter(destination)

	for scanner.Scan() {
		line := scanner.Text()

		_, err := writer.WriteString(line + "\n")
		if err != nil {
			return err
		}
	}

	if err := scanner.Err(); err != nil {
		slog.Error("error reading file", "src", src, "err", err)
		return err
	}

	return writer.Flush()
}

func CopyTemplateLauncher(src, dst, pkgName string) error {
	source, err := os.Open(src)
	if err != nil {
		return err
	}
	defer func(source *os.File) {
		if err := source.Close(); err != nil {
			slog.Error("failed to close file", "src", src, "err", err)
		}
	}(source)

	destination, err := os.Create(dst)
	if err != nil {
		return err
	}
	defer func(destination *os.File) {
		if err := destination.Close(); err != nil {
			slog.Error("failed to close file", "dst", dst, "err", err)
		}
	}(destination)

	scanner := bufio.NewScanner(source)
	writer := bufio.NewWriter(destination)

	hasTerminal := false

	for scanner.Scan() {
		line := scanner.Text()

		if strings.HasPrefix(line, "Name=") {
			line = "Name=[not installed] " + strings.TrimPrefix(line, "Name=")
		} else if strings.HasPrefix(line, "Icon=") {
			line = "Icon=software-manager"
		} else if strings.HasPrefix(line, "Exec=") {
			line = "Exec=parrot-exec --install " + pkgName
		} else if strings.HasPrefix(line, "Terminal=") {
			line = "Terminal=true"
			hasTerminal = true
		}

		_, err := writer.WriteString(line + "\n")
		if err != nil {
			return err
		}
	}

	if err := scanner.Err(); err != nil {
		slog.Error("error reading file", "src", src, "err", err)
		return err
	}

	if !hasTerminal {
		_, err = writer.WriteString("Terminal=true\n")
		if err != nil {
			return err
		}
	}

	return writer.Flush()
}
