package provision

import (
	"fmt"
	"log"
	"strings"

	"zlh-agent/internal/provision/addons"
	"zlh-agent/internal/provision/devcontainer"
	"zlh-agent/internal/provision/minecraft"
	"zlh-agent/internal/provision/steam"
	"zlh-agent/internal/state"
)

/*
ProvisionAll — unified entrypoint for provisioning.
IMPORTANT:
- This function ONLY performs installation.
- Validation/verification happens in ensureProvisioned().
- state.Config is treated as immutable desired state.
*/
func ProvisionAll(cfg state.Config) error {
	normalizeMinecraftConfig(&cfg)

	/* ---------------------------------------------------------
	   BASE ROLE PROVISIONING
	--------------------------------------------------------- */
	if cfg.ContainerType == "dev" {

		if err := devcontainer.Provision(cfg); err != nil {
			return err
		}

	} else {

		// Legacy / default behavior assumes game containers
		game := strings.ToLower(cfg.Game)
		variant := strings.ToLower(cfg.Variant)
		runtime := strings.ToLower(cfg.Runtime)

		/* ---------------------------------------------------------
		   MINECRAFT
		--------------------------------------------------------- */
		if game == "minecraft" {

			// 1. Install Java (runtime)
			if err := InstallJava(cfg); err != nil {
				return fmt.Errorf("java install failed: %w", err)
			}

			// 2. Game variant install
			switch variant {
			case "vanilla":
				if runtime != "fabric" {
					return fmt.Errorf("unsupported runtime: %s", cfg.Runtime)
				}
				if err := minecraft.InstallFabric(cfg); err != nil {
					return err
				}
				if err := minecraft.InjectFabricProxyLite(cfg); err != nil {
					return fmt.Errorf("fabricproxy-lite injection failed: %w", err)
				}

			case "fabric":
				if err := minecraft.InstallFabric(cfg); err != nil {
					return err
				}

			case "paper", "purpur", "quilt":
				if err := minecraft.InstallMinecraftJar(cfg); err != nil {
					return fmt.Errorf("minecraft jar install failed: %w", err)
				}

			case "forge":
				if err := minecraft.InstallMinecraftForge(cfg); err != nil {
					return fmt.Errorf("forge install failed: %w", err)
				}

			case "neoforge":
				if err := minecraft.InstallMinecraftNeoForge(cfg); err != nil {
					return fmt.Errorf("neoforge install failed: %w", err)
				}

			default:
				return fmt.Errorf("unsupported minecraft variant: %s", variant)
			}

			// 3. Config files generated AFTER variant installer
			if err := WriteEula(cfg); err != nil {
				return err
			}
			if err := WriteServerProperties(cfg); err != nil {
				return err
			}
			if err := WriteStartScript(cfg); err != nil {
				return err
			}

		} else if IsSteamGame(game) {

			/* ---------------------------------------------------------
			   STEAM GAMES
			--------------------------------------------------------- */

			// 1. SteamCMD install
			if err := steam.EnsureSteamCMD(); err != nil {
				return fmt.Errorf("steamcmd install failed: %w", err)
			}

			// 2. Install game-specific content
			switch game {

			case "valheim":
				if err := steam.InstallValheim(cfg); err != nil {
					return err
				}

			case "rust":
				if err := steam.InstallRust(cfg); err != nil {
					return err
				}

			case "terraria":
				if err := steam.InstallTerraria(cfg); err != nil {
					return err
				}

			case "projectzomboid":
				if err := steam.InstallProjectZomboid(cfg); err != nil {
					return err
				}

			default:
				return fmt.Errorf("unsupported steam game: %s", game)
			}

			// 3. Start script
			if err := WriteStartScript(cfg); err != nil {
				return err
			}

		} else {
			return fmt.Errorf(
				"unsupported container identity (containerType=%q game=%q)",
				cfg.ContainerType,
				cfg.Game,
			)
		}
	}

	/* ---------------------------------------------------------
	   ADDONS (OPTIONAL, ROLE-AGNOSTIC)
	--------------------------------------------------------- */
	if strings.EqualFold(cfg.ContainerType, "dev") && codeServerRequested(cfg) {
		seen := false
		for _, addon := range cfg.Addons {
			if strings.EqualFold(addon, "codeserver") {
				seen = true
				break
			}
		}
		if !seen {
			cfg.Addons = append(cfg.Addons, "codeserver")
		}
	}

	if len(cfg.Addons) > 0 {
		if err := addons.Provision(cfg); err != nil {
			return err
		}
	}

	return nil
}

func codeServerRequested(cfg state.Config) bool {
	if cfg.EnableCodeServer {
		return true
	}
	for _, addon := range cfg.Addons {
		if strings.EqualFold(addon, "codeserver") {
			return true
		}
	}
	return false
}

func normalizeMinecraftConfig(cfg *state.Config) {
	if cfg == nil {
		return
	}
	if !strings.EqualFold(cfg.ContainerType, "game") {
		return
	}
	if !strings.EqualFold(cfg.Game, "minecraft") {
		return
	}
	if !strings.EqualFold(cfg.Variant, "vanilla") {
		return
	}

	cfg.Runtime = "fabric"
	cfg.InternalProfile = "vanilla-fabric"
	cfg.ArtifactPath = fmt.Sprintf("minecraft/fabric/%s/server.jar", strings.TrimSpace(cfg.Version))
	log.Printf("[provision] vmid=%d action=normalize original_variant=vanilla runtime=fabric profile=vanilla-fabric", cfg.VMID)
	log.Printf("[provision] vmid=%d variant=vanilla normalized_runtime=fabric", cfg.VMID)
	log.Printf("[provision] vmid=%d artifact_override=true source=fabric path=%s", cfg.VMID, cfg.ArtifactPath)
}
