package config

import (
	"encoding/json"
	"fmt"
	"os"
)

type InstallConfig struct {
	Disk           string
	EnableLUKS     bool
	Hostname       string
	Username       string
	RootPassword   string
	UserPassword   string
	Timezone       string
	Locale         string
}

type ArchInstallConfig struct {
	Version             string              `json:"version"`
	Script              string              `json:"script"`
	ArchinstallLanguage string              `json:"archinstall-language"`
	Bootloader          string              `json:"bootloader"`
	Kernels             []string            `json:"kernels"`
	Hostname            string              `json:"hostname"`
	Timezone            string              `json:"timezone"`
	LocaleConfig        LocaleConfig        `json:"locale_config"`
	DiskConfig          DiskConfig          `json:"disk_config"`
	ProfileConfig       ProfileConfig       `json:"profile_config"`
	AuthConfig          AuthConfig          `json:"auth_config"`
	Packages            []string            `json:"packages"`
	Services            []string            `json:"services"`
}

type LocaleConfig struct {
	KbLayout string `json:"kb_layout"`
	SysEnc   string `json:"sys_enc"`
	SysLang  string `json:"sys_lang"`
}

type DiskConfig struct {
	ConfigType          string              `json:"config_type"`
	DeviceModifications []DeviceModification `json:"device_modifications"`
}

type DeviceModification struct {
	Device      string      `json:"device"`
	Partitions  []Partition `json:"partitions"`
	Wipe        bool        `json:"wipe"`
}

type Partition struct {
	Btrfs        []interface{} `json:"btrfs"`
	Flags        []string      `json:"flags,omitempty"`
	FsType       string        `json:"fs_type"`
	Size         Size          `json:"size"`
	MountOptions []string      `json:"mount_options"`
	Mountpoint   string        `json:"mountpoint,omitempty"`
	ObjId        string        `json:"obj_id"`
	Start        Size          `json:"start"`
	Status       string        `json:"status"`
	Type         string        `json:"type"`
}

type Size struct {
	SectorSize *int    `json:"sector_size"`
	Unit       string  `json:"unit"`
	Value      float64 `json:"value"`
}

type ProfileConfig struct {
	Profile Profile `json:"profile"`
}

type Profile struct {
	Main    string   `json:"main"`
	Details []string `json:"details,omitempty"`
}

type AuthConfig struct {
	Users []User `json:"users"`
}

type User struct {
	Username string `json:"username"`
	Password string `json:"password"`
	Sudo     bool   `json:"sudo"`
}

func (c *InstallConfig) ToArchInstall() *ArchInstallConfig {
	// Create partitions for EFI and root
	partitions := []Partition{
		{
			Btrfs:        []interface{}{},
			Flags:        []string{"boot"},
			FsType:       "fat32",
			Size:         Size{SectorSize: nil, Unit: "MiB", Value: 512},
			MountOptions: []string{},
			Mountpoint:   "/boot",
			ObjId:        "efi-partition-id",
			Start:        Size{SectorSize: nil, Unit: "MiB", Value: 1},
			Status:       "create",
			Type:         "primary",
		},
		{
			Btrfs:        []interface{}{},
			Flags:        []string{},
			FsType:       "btrfs",
			Size:         Size{SectorSize: nil, Unit: "Percent", Value: 100},
			MountOptions: []string{},
			Mountpoint:   "/",
			ObjId:        "root-partition-id",
			Start:        Size{SectorSize: nil, Unit: "MiB", Value: 513},
			Status:       "create",
			Type:         "primary",
		},
	}

	// Miasma OS specific packages based on ProductDescription.md
	miasmaPackages := []string{
		// Base system
		"base",
		"base-devel",
		"linux-hardened",
		"linux-firmware",
		"btrfs-progs",
		
		// Text editors
		"neovim",
		
		// Shell
		"zsh",
		
		// Terminal
		"alacritty",
		
		// System tools
		"tmux",
		"git",
		"networkmanager",
		
		// Security tools
		"opendoas",
		"firejail",
		"apparmor",
		"nftables", // Using nftables instead of ufw as requested
		"hardened-malloc",
		
		// Browsers
		"chromium", // Using regular chromium instead of ungoogled-chromium as requested
		
		// Wayland support
		"xwayland-satellite",
		
		// Cosmic Desktop
		"cosmic-session",
		"cosmic-greeter",
		"cosmic-files",
		"cosmic-edit",
		"cosmic-term",
		"cosmic-store",
		"cosmic-settings",
	}

	ac := &ArchInstallConfig{
		Version:             "2.8.6", // Match archinstall version
		Script:              "guided",
		ArchinstallLanguage: "English",
		Bootloader:          "Systemd-boot",
		Kernels:             []string{"linux-hardened"},
		Hostname:            c.Hostname,
		Timezone:            c.Timezone,
		LocaleConfig: LocaleConfig{
			KbLayout: "us",
			SysEnc:   "UTF-8",
			SysLang:  "en_US",
		},
		DiskConfig: DiskConfig{
			ConfigType: "default_layout",
			DeviceModifications: []DeviceModification{
				{
					Device:     c.Disk,
					Partitions: partitions,
					Wipe:       true,
				},
			},
		},
		ProfileConfig: ProfileConfig{
			Profile: Profile{
				Main:    "Desktop",
				Details: []string{"Cosmic"},
			},
		},
		AuthConfig: AuthConfig{
			Users: []User{
				{
					Username: c.Username,
					Password: c.UserPassword,
					Sudo:     true,
				},
			},
		},
		Packages: miasmaPackages,
		Services: []string{
			"NetworkManager",
			"nftables",
			"apparmor",
			"cosmic-greeter",
		},
	}

	return ac
}

func (c *InstallConfig) SaveArchInstallConfig(filepath string) error {
	archConfig := c.ToArchInstall()
	data, err := json.MarshalIndent(archConfig, "", "  ")
	if err != nil {
		return fmt.Errorf("failed to marshal config: %w", err)
	}

	return os.WriteFile(filepath, data, 0644)
}

func (c *InstallConfig) SaveUserCredentials(filepath string) error {
	// For credentials, we only save the sensitive information
	creds := map[string]interface{}{}
	
	if c.EnableLUKS && c.RootPassword != "" {
		creds["encryption_password"] = c.RootPassword
	}
	
	creds["users"] = []map[string]string{
		{
			"username": c.Username,
			"password": c.UserPassword,
		},
	}
	
	if c.RootPassword != "" {
		creds["root_enc_password"] = c.RootPassword
	}

	data, err := json.MarshalIndent(creds, "", "  ")
	if err != nil {
		return fmt.Errorf("failed to marshal credentials: %w", err)
	}

	return os.WriteFile(filepath, data, 0600)
}
