package config

import (
	"encoding/json"
	"fmt"

	"github.com/alexei/docker-watcher/internal/store"
	"gopkg.in/yaml.v3"
)

// ExportConfig reads the current database state and produces a SeedConfig YAML
// representation. Credential fields (tokens, passwords) are exported as placeholder
// strings since they are encrypted in the database.
func ExportConfig(db *store.Store) ([]byte, error) {
	cfg, err := buildSeedConfig(db)
	if err != nil {
		return nil, fmt.Errorf("build seed config: %w", err)
	}

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

	return data, nil
}

// buildSeedConfig constructs a SeedConfig from the current database state.
func buildSeedConfig(db *store.Store) (SeedConfig, error) {
	settings, err := db.GetSettings()
	if err != nil {
		return SeedConfig{}, fmt.Errorf("get settings: %w", err)
	}

	registries, err := db.GetAllRegistries()
	if err != nil {
		return SeedConfig{}, fmt.Errorf("get registries: %w", err)
	}

	projects, err := db.GetAllProjects()
	if err != nil {
		return SeedConfig{}, fmt.Errorf("get projects: %w", err)
	}

	cfg := SeedConfig{
		Global: GlobalConfig{
			Domain:           settings.Domain,
			ServerIP:         settings.ServerIP,
			Network:          settings.Network,
			SubdomainPattern: settings.SubdomainPattern,
			NotificationURL:  settings.NotificationURL,
			Npm: NpmConfig{
				URL:      settings.NpmURL,
				Email:    settings.NpmEmail,
				Password: "CHANGE_ME", // Encrypted value, export placeholder.
			},
		},
		Registries: make(map[string]RegistryDef),
		Projects:   make(map[string]ProjectDef),
	}

	for _, reg := range registries {
		cfg.Registries[reg.Name] = RegistryDef{
			URL:   reg.URL,
			Type:  reg.Type,
			Token: "CHANGE_ME", // Encrypted value, export placeholder.
		}
	}

	for _, proj := range projects {
		stages, err := db.GetStagesByProjectID(proj.ID)
		if err != nil {
			return SeedConfig{}, fmt.Errorf("get stages for project %s: %w", proj.Name, err)
		}

		stageDefs := make(map[string]StageDef)
		for _, st := range stages {
			stageDefs[st.Name] = StageDef{
				TagPattern:   st.TagPattern,
				AutoDeploy:   st.AutoDeploy,
				MaxInstances: st.MaxInstances,
				Confirm:      st.Confirm,
				PromoteFrom:  st.PromoteFrom,
				Subdomain:    st.Subdomain,
			}
		}

		envMap := parseJSONMap(proj.Env)
		volMap := parseJSONMap(proj.Volumes)

		cfg.Projects[proj.Name] = ProjectDef{
			Registry:    proj.Registry,
			Image:       proj.Image,
			Port:        proj.Port,
			Healthcheck: proj.Healthcheck,
			Env:         envMap,
			Volumes:     volMap,
			Stages:      stageDefs,
		}
	}

	return cfg, nil
}

// parseJSONMap safely parses a JSON-encoded map string. Returns nil on failure.
func parseJSONMap(jsonStr string) map[string]string {
	if jsonStr == "" || jsonStr == "{}" {
		return nil
	}
	var m map[string]string
	if err := json.Unmarshal([]byte(jsonStr), &m); err != nil {
		return nil
	}
	if len(m) == 0 {
		return nil
	}
	return m
}
