package main

import (
	"fmt"
	"os"
	"os/exec"
	"path/filepath"
	"regexp"
	"strings"
)

func instanceDir(dataDir, instanceID string) string {
	return filepath.Join(dataDir, "instances", instanceID)
}

func getContainerEngine() string {
	if _, err := exec.LookPath("podman"); err == nil {
		return "podman"
	}
	return "docker"
}

func writeCompose(dataDir, instanceID, compose string) error {
	dir := instanceDir(dataDir, instanceID)
	if err := os.MkdirAll(dir, 0755); err != nil {
		return err
	}

	// Ensure the EduBox mu-plugin is available and substitute its path
	muDir, err := writeMUPlugin(dataDir)
	if err != nil {
		return err
	}
	compose = strings.ReplaceAll(compose, "{MU_PLUGINS_DIR}", filepath.Dir(muDir))

	f := filepath.Join(dir, "docker-compose.yml")
	return os.WriteFile(f, []byte(compose), 0644)
}

func dockerComposeUp(dataDir, instanceID string) error {
	dir := instanceDir(dataDir, instanceID)
	cmd := exec.Command(getContainerEngine(), "compose", "-f", filepath.Join(dir, "docker-compose.yml"), "up", "-d")
	cmd.Stdout = os.Stdout
	cmd.Stderr = os.Stderr
	return cmd.Run()
}

func dockerComposeDown(dataDir, instanceID string) error {
	dir := instanceDir(dataDir, instanceID)
	cmd := exec.Command(getContainerEngine(), "compose", "-f", filepath.Join(dir, "docker-compose.yml"), "down")
	cmd.Stdout = os.Stdout
	cmd.Stderr = os.Stderr
	return cmd.Run()
}

func dockerComposeRm(dataDir, instanceID string) error {
	dir := instanceDir(dataDir, instanceID)
	cmd := exec.Command(getContainerEngine(), "compose", "-f", filepath.Join(dir, "docker-compose.yml"), "down", "-v")
	cmd.Stdout = os.Stdout
	cmd.Stderr = os.Stderr
	if err := cmd.Run(); err != nil {
		return err
	}
	return os.RemoveAll(dir)
}

// extractPublicURL tries to find the public URL from a WordPress compose config.
func extractPublicURL(composeConfig string) string {
	re := regexp.MustCompile(`define\('WP_HOME',\s*'([^']+)'\);`)
	m := re.FindStringSubmatch(composeConfig)
	if len(m) > 1 {
		return m[1]
	}
	return ""
}

// updateWordPressURLs patches wp-config.php inside the WordPress container
// so that WP_HOME and WP_SITEURL point to the public URL.
func updateWordPressURLs(dataDir, instanceID, publicURL string) error {
	if publicURL == "" {
		return nil
	}
	dir := instanceDir(dataDir, instanceID)
	composeFile := filepath.Join(dir, "docker-compose.yml")
	engine := getContainerEngine()

	script := fmt.Sprintf(`#!/bin/sh
CONFIG=/var/www/html/wp-config.php
if [ -f "$CONFIG" ]; then
  sed -i "s|define('WP_HOME',[^;]*);|define('WP_HOME', '%s');|" "$CONFIG"
  sed -i "s|define('WP_SITEURL',[^;]*);|define('WP_SITEURL', '%s');|" "$CONFIG"
  if ! grep -q "define('WP_HOME'" "$CONFIG"; then
    sed -i "/That's all, stop editing/i define('WP_HOME', '%s');\ndefine('WP_SITEURL', '%s');" "$CONFIG"
  fi
fi
`, publicURL, publicURL, publicURL, publicURL)

	scriptPath := filepath.Join(dir, "update-wp-urls.sh")
	if err := os.WriteFile(scriptPath, []byte(script), 0755); err != nil {
		return err
	}
	defer os.Remove(scriptPath)

	cpCmd := exec.Command(engine, "compose", "-f", composeFile, "cp", scriptPath, "app:/tmp/update-wp-urls.sh")
	cpCmd.Stdout = os.Stdout
	cpCmd.Stderr = os.Stderr
	if err := cpCmd.Run(); err != nil {
		return err
	}

	execCmd := exec.Command(engine, "compose", "-f", composeFile, "exec", "-T", "app", "sh", "/tmp/update-wp-urls.sh")
	execCmd.Stdout = os.Stdout
	execCmd.Stderr = os.Stderr
	return execCmd.Run()
}

// stripWordPressHardcodedURLs removes hardcoded WP_HOME/WP_SITEURL defines
// from wp-config.php so the EduBox mu-plugin can compute them from the Host
// header. This is useful when repairing older instances created before the
// mu-plugin existed.
func stripWordPressHardcodedURLs(dataDir, instanceID string) error {
	dir := instanceDir(dataDir, instanceID)
	composeFile := filepath.Join(dir, "docker-compose.yml")
	engine := getContainerEngine()

	script := `#!/bin/sh
CONFIG=/var/www/html/wp-config.php
if [ -f "$CONFIG" ]; then
  # Remove hardcoded WP_HOME / WP_SITEURL defines so the mu-plugin controls them
  sed -i "/define('WP_HOME',/d" "$CONFIG"
  sed -i "/define('WP_SITEURL',/d" "$CONFIG"
fi
`

	scriptPath := filepath.Join(dir, "strip-wp-urls.sh")
	if err := os.WriteFile(scriptPath, []byte(script), 0755); err != nil {
		return err
	}
	defer os.Remove(scriptPath)

	cpCmd := exec.Command(engine, "compose", "-f", composeFile, "cp", scriptPath, "app:/tmp/strip-wp-urls.sh")
	cpCmd.Stdout = os.Stdout
	cpCmd.Stderr = os.Stderr
	if err := cpCmd.Run(); err != nil {
		return err
	}

	execCmd := exec.Command(engine, "compose", "-f", composeFile, "exec", "-T", "app", "sh", "/tmp/strip-wp-urls.sh")
	execCmd.Stdout = os.Stdout
	execCmd.Stderr = os.Stderr
	return execCmd.Run()
}
