package settings

import (
	"fmt"
	"os"
	"path/filepath"
	"sync"

	"gopkg.in/yaml.v3"
)

type Store struct {
	mu   sync.RWMutex
	path string
}

type Settings struct {
	Theme                 string        `yaml:"theme" json:"theme"`
	RepoURL               string        `yaml:"repoUrl" json:"repoUrl"`
	TTLDays               int           `yaml:"ttlDays" json:"ttlDays"`
	MaxPayloadBytes       int           `yaml:"maxPayloadBytes" json:"maxPayloadBytes"`
	AutoPurgePayloads     bool          `yaml:"autoPurgePayloads" json:"autoPurgePayloads"`
	AutoPurgePayloadBytes int           `yaml:"autoPurgePayloadBytes" json:"autoPurgePayloadBytes"`
	AutoExpandDepth       int           `yaml:"autoExpandDepth" json:"autoExpandDepth"`
	ImageDetection        bool          `yaml:"imageDetectionEnabled" json:"imageDetectionEnabled"`
	HighlightMs           int           `yaml:"highlightMs" json:"highlightMs"`
	MQTTProfiles          []MQTTProfile `yaml:"mqttProfiles" json:"mqttProfiles"`
	ActiveProfileID       string        `yaml:"activeProfileId" json:"activeProfileId"`
	ApplyViewFilter       bool          `yaml:"applyViewFilter" json:"applyViewFilter"`
	ExpandTreeOnStart     bool          `yaml:"expandTreeOnStart" json:"expandTreeOnStart"`
	TopicFilters          []TopicFilter `yaml:"topicFilters" json:"topicFilters"`
	UIFontSize            int           `yaml:"uiFontSize" json:"uiFontSize"`
	TopicFontSize         int           `yaml:"topicFontSize" json:"topicFontSize"`
	PayloadFontSize       int           `yaml:"payloadFontSize" json:"payloadFontSize"`
	StatsRefreshMs        int           `yaml:"statsRefreshMs" json:"statsRefreshMs"`
	ResizeHandlePx        int           `yaml:"resizeHandlePx" json:"resizeHandlePx"`
}

type MQTTProfile struct {
	ID        string `yaml:"id" json:"id"`
	Name      string `yaml:"name" json:"name"`
	Host      string `yaml:"host" json:"host"`
	Port      int    `yaml:"port" json:"port"`
	Username  string `yaml:"username" json:"username"`
	Password  string `yaml:"password" json:"password"`
	IsDefault bool   `yaml:"isDefault" json:"isDefault"`
}

type TopicFilter struct {
	Topic string `yaml:"topic" json:"topic"`
	Save  bool   `yaml:"save" json:"save"`
	View  bool   `yaml:"view" json:"view"`
}

func NewStore(path string) *Store {
	return &Store{path: path}
}

func (s *Store) Load(defaults Settings) (Settings, error) {
	s.mu.RLock()
	defer s.mu.RUnlock()

	content, err := os.ReadFile(s.path)
	if err != nil {
		if os.IsNotExist(err) {
			return defaults, nil
		}
		return defaults, fmt.Errorf("lecture settings: %w", err)
	}

	var loaded Settings
	if err := yaml.Unmarshal(content, &loaded); err != nil {
		return defaults, fmt.Errorf("yaml settings: %w", err)
	}

	return merge(defaults, loaded), nil
}

func (s *Store) Save(next Settings) error {
	s.mu.Lock()
	defer s.mu.Unlock()

	dir := filepath.Dir(s.path)
	if err := os.MkdirAll(dir, 0o755); err != nil {
		return fmt.Errorf("mkdir settings: %w", err)
	}

	content, err := yaml.Marshal(next)
	if err != nil {
		return fmt.Errorf("marshal settings: %w", err)
	}

	return os.WriteFile(s.path, content, 0o644)
}

func merge(base, override Settings) Settings {
	merged := base
	if override.Theme != "" {
		merged.Theme = override.Theme
	}
	if override.RepoURL != "" {
		merged.RepoURL = override.RepoURL
	}
	if override.TTLDays != 0 {
		merged.TTLDays = override.TTLDays
	}
	if override.MaxPayloadBytes != 0 {
		merged.MaxPayloadBytes = override.MaxPayloadBytes
	}
	merged.AutoPurgePayloads = override.AutoPurgePayloads
	if override.AutoPurgePayloadBytes != 0 {
		merged.AutoPurgePayloadBytes = override.AutoPurgePayloadBytes
	}
	if override.AutoExpandDepth != 0 {
		merged.AutoExpandDepth = override.AutoExpandDepth
	}
	merged.ImageDetection = override.ImageDetection
	if override.HighlightMs != 0 {
		merged.HighlightMs = override.HighlightMs
	}
	if len(override.MQTTProfiles) > 0 {
		merged.MQTTProfiles = override.MQTTProfiles
	}
	if override.ActiveProfileID != "" {
		merged.ActiveProfileID = override.ActiveProfileID
	}
	merged.ApplyViewFilter = override.ApplyViewFilter
	merged.ExpandTreeOnStart = override.ExpandTreeOnStart
	if len(override.TopicFilters) > 0 {
		merged.TopicFilters = override.TopicFilters
	}
	if override.UIFontSize != 0 {
		merged.UIFontSize = override.UIFontSize
	}
	if override.TopicFontSize != 0 {
		merged.TopicFontSize = override.TopicFontSize
	}
	if override.PayloadFontSize != 0 {
		merged.PayloadFontSize = override.PayloadFontSize
	}
	if override.StatsRefreshMs != 0 {
		merged.StatsRefreshMs = override.StatsRefreshMs
	}
	if override.ResizeHandlePx != 0 {
		merged.ResizeHandlePx = override.ResizeHandlePx
	}
	return merged
}
