package config

import (
	"encoding/json"
	"os"
	"path/filepath"
)

// Config mirrors config.json structure.
type Config struct {
	Deployment    Deployment             `json:"deployment"`
	AdminAccount  AdminAccount           `json:"adminAccount"`
	Activation    Activation             `json:"activation"`
	Software      Software               `json:"software"`
	Steps         map[string]bool        `json:"steps"`
	Features      Features               `json:"features"`
	Bloatware     Bloatware              `json:"bloatware"`
}

type Deployment struct {
	PCName        string `json:"pcName"`
	PCDescription string `json:"pcDescription"`
	Timezone      string `json:"timezone"`
	ProfileType   string `json:"profileType"` // default | admin | user
}

type AdminAccount struct {
	Username string `json:"username"`
}

type Activation struct {
	ProductKey string `json:"productKey"`
	KMSServer  string `json:"kmsServer"`
}

type SoftwareItem struct {
	Name     string `json:"name"`
	WingetID string `json:"wingetId"`
}

type Software struct {
	Install []SoftwareItem `json:"install"`
}

// Bloatware holds bloatware-removal config. KeepPackages lists AppX package
// names that must never be removed, on top of the always-kept defaults.
type Bloatware struct {
	KeepPackages []string `json:"keepPackages"`
}

// Features holds per-step, per-feature toggle flags.
// Keys: stepID -> featureID -> enabled.
// A missing key defaults to true (feature enabled).
type Features map[string]map[string]bool

// DefaultConfig returns a config with sensible defaults.
func DefaultConfig() Config {
	return Config{
		Deployment: Deployment{
			Timezone:    "Central Europe Standard Time",
			ProfileType: "default",
		},
		AdminAccount: AdminAccount{
			Username: "adminx9",
		},
		Activation: Activation{
			ProductKey: "",
		},
		Software: Software{
			Install: []SoftwareItem{
				{Name: "7-Zip", WingetID: "7zip.7zip"},
				{Name: "Adobe Acrobat Reader 64-bit", WingetID: "Adobe.Acrobat.Reader.64-bit"},
				{Name: "OpenVPN Connect", WingetID: "OpenVPNTechnologies.OpenVPNConnect"},
			},
		},
		Steps: map[string]bool{
			"adminAccount":   true,
			"activation":     true,
			"bloatware":      true,
			"software":       true,
			"systemRegistry": true,
			"defaultProfile": true,
			"backinfo":       true,
			"network":        true,
			"dellUpdate":     true,
			"pcIdentity":     true,
			"windowsUpdate":  true,
		},
		Features: Features{
			"bloatware": {
				"standardBloatware":  true,
				"removeNewOutlook":   true,
				"removeSnippingTool": false,
			},
			"software": {
				"wingetInstalls": true,
				"pdfDefault":     true,
				"ateraAgent":     true,
			},
			"systemRegistry": {
				"systemTweaks":      true,
				"edgePolicies":      true,
				"oneDriveUninstall": true,
				"powercfg":          true,
				"proxyDisable":      true,
			},
			"defaultProfile": {
				"taskbarTweaks":   true,
				"startMenuTweaks": true,
				"explorerTweaks":  true,
			},
			"dellUpdate": {
				"drivers": true,
				"bios":    true,
			},
		},
		Bloatware: Bloatware{
			KeepPackages: []string{"Microsoft.WindowsCalculator"},
		},
	}
}

// Load reads config.json from the given path.
// If the file does not exist, returns DefaultConfig without error.
func Load(path string) (Config, error) {
	cfg := DefaultConfig()
	data, err := os.ReadFile(path)
	if os.IsNotExist(err) {
		return cfg, nil
	}
	if err != nil {
		return cfg, err
	}
	if err := json.Unmarshal(data, &cfg); err != nil {
		return cfg, err
	}
	return cfg, nil
}

// Save writes config to the given path (creates directories if needed).
func Save(cfg Config, path string) error {
	if err := os.MkdirAll(filepath.Dir(path), 0755); err != nil {
		return err
	}
	data, err := json.MarshalIndent(cfg, "", "  ")
	if err != nil {
		return err
	}
	return os.WriteFile(path, data, 0644)
}

// ConfigPath returns the default config.json path (next to the executable).
func ConfigPath() string {
	exe, err := os.Executable()
	if err != nil {
		return "config.json"
	}
	return filepath.Join(filepath.Dir(exe), "config.json")
}
