package config

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

type Config struct {
	Listen             string            `json:"listen"`
	DiscoveryPort      int               `json:"discovery_port"`
	DiscoveryTimeoutMs int               `json:"discovery_timeout_ms"`
	OfflineAfterMs     int               `json:"offline_after_ms"`
	AgentToken         string            `json:"agent_token"`
	Concurrency        int               `json:"concurrency"`
	DataDir            string            `json:"data_dir,omitempty"`
	DBPath             string            `json:"db_path,omitempty"`
	LogDir             string            `json:"log_dir,omitempty"`
	MediaRepoPath      string            `json:"media_repo_path,omitempty"` // explicit import-only source; not used for runtime rendering
	DeviceAliases      map[string]string `json:"device_aliases,omitempty"`
	path               string
}

func LoadConfig(path string) (*Config, error) {
	file, err := os.Open(path)
	if err != nil {
		return nil, err
	}
	defer file.Close()

	var cfg Config
	decoder := json.NewDecoder(file)
	if err := decoder.Decode(&cfg); err != nil {
		return nil, err
	}
	cfg.path = path

	return &cfg, nil
}

func (c *Config) Save() error {
	if c == nil || c.path == "" {
		return nil
	}
	body, err := json.MarshalIndent(c, "", "  ")
	if err != nil {
		return err
	}
	return os.WriteFile(c.path, append(body, '\n'), 0o644)
}

func (c *Config) DataDirOrDefault() string {
	if c != nil && strings.TrimSpace(c.DataDir) != "" {
		return filepath.Clean(strings.TrimSpace(c.DataDir))
	}
	return "data"
}

func (c *Config) DBPathOrDefault() string {
	if c != nil && strings.TrimSpace(c.DBPath) != "" {
		return filepath.Clean(strings.TrimSpace(c.DBPath))
	}
	return filepath.Join(c.DataDirOrDefault(), "app.db")
}

func (c *Config) LogDirOrDefault() string {
	if c != nil && strings.TrimSpace(c.LogDir) != "" {
		return filepath.Clean(strings.TrimSpace(c.LogDir))
	}
	return filepath.Join(c.DataDirOrDefault(), "logs")
}
