package models

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

var (
	mu      sync.RWMutex
	cfg     *AppConfig
	cfgPath string
)

func init() {
	cfgPath = resolveCfgPath()
	hostname, _ := os.Hostname()
	cfg = &AppConfig{
		Node: NodeInfo{
			Hostname:      hostname,
			UpdateHistory: []UpdateRecord{},
			Backup: BackupConfig{
				Targets: []BackupTarget{},
				History: []BackupExecution{},
			},
		},
		Nodes:    []RemoteNode{},
		Services: []Service{},
	}
	if data, err := os.ReadFile(cfgPath); err == nil {
		_ = json.Unmarshal(data, cfg)
	}
	ensureSlices()
}

func ensureSlices() {
	if cfg.Node.UpdateHistory == nil {
		cfg.Node.UpdateHistory = []UpdateRecord{}
	}
	if cfg.Node.Backup.Targets == nil {
		cfg.Node.Backup.Targets = []BackupTarget{}
	}
	if cfg.Node.Backup.History == nil {
		cfg.Node.Backup.History = []BackupExecution{}
	}
	if cfg.Nodes == nil {
		cfg.Nodes = []RemoteNode{}
	}
	if cfg.Services == nil {
		cfg.Services = []Service{}
	}
}

func resolveCfgPath() string {
	const etcPath = "/etc/nodemaster/nodemaster.conf"
	if err := os.MkdirAll(filepath.Dir(etcPath), 0755); err == nil {
		if f, err := os.OpenFile(etcPath, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0600); err == nil {
			f.Close()
			return etcPath
		}
	}
	home, err := os.UserHomeDir()
	if err != nil {
		home = "."
	}
	return filepath.Join(home, ".nodemaster.conf")
}

func persist() error {
	data, err := json.MarshalIndent(cfg, "", "  ")
	if err != nil {
		return err
	}
	if err := os.MkdirAll(filepath.Dir(cfgPath), 0755); err != nil {
		return fmt.Errorf("mkdir: %w", err)
	}
	// 0600: the config now embeds the restic repository password, so it must
	// not be group/world-readable. Chmod covers pre-existing files that were
	// created before this field existed (WriteFile's mode only applies on
	// create, not to files that already exist with looser permissions).
	if err := os.WriteFile(cfgPath, data, 0600); err != nil {
		return err
	}
	_ = os.Chmod(cfgPath, 0600)
	return nil
}

// ConfigPath returns the resolved config file path.
func ConfigPath() string {
	return cfgPath
}
