package cmd

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

	"github.com/spf13/cobra"
	"github.com/spf13/viper"
)

// ConfigDir returns the mosis config directory (~/.mosis)
func ConfigDir() string {
	home, err := os.UserHomeDir()
	if err != nil {
		return ".mosis"
	}
	return filepath.Join(home, ".mosis")
}

// InitConfig initializes viper configuration
func InitConfig() {
	configDir := ConfigDir()

	// Set defaults
	viper.SetDefault("portal_url", "http://localhost:8080")
	viper.SetDefault("designer_path", "mosis-designer")

	// Read config file if exists
	viper.SetConfigName("config")
	viper.SetConfigType("json")
	viper.AddConfigPath(configDir)
	viper.ReadInConfig() // Ignore error if no config file

	// Environment variables
	viper.SetEnvPrefix("MOSIS")
	viper.AutomaticEnv()
}

// EnsureConfigDir creates the config directory if it doesn't exist
func EnsureConfigDir() error {
	dir := ConfigDir()
	return os.MkdirAll(dir, 0700)
}

// SaveConfig saves the current config to file
func SaveConfig() error {
	if err := EnsureConfigDir(); err != nil {
		return err
	}

	configPath := filepath.Join(ConfigDir(), "config.json")

	data := map[string]interface{}{
		"portal_url":    viper.GetString("portal_url"),
		"designer_path": viper.GetString("designer_path"),
	}

	if name := viper.GetString("default_author_name"); name != "" {
		data["default_author"] = map[string]string{
			"name":  name,
			"email": viper.GetString("default_author_email"),
		}
	}

	content, err := json.MarshalIndent(data, "", "  ")
	if err != nil {
		return err
	}

	return os.WriteFile(configPath, content, 0600)
}

// ConfigCmd returns the config command
func ConfigCmd() *cobra.Command {
	cmd := &cobra.Command{
		Use:   "config",
		Short: "Manage CLI configuration",
	}

	cmd.AddCommand(configGetCmd())
	cmd.AddCommand(configSetCmd())
	cmd.AddCommand(configListCmd())

	return cmd
}

func configGetCmd() *cobra.Command {
	return &cobra.Command{
		Use:   "get <key>",
		Short: "Get a configuration value",
		Args:  cobra.ExactArgs(1),
		Run: func(cmd *cobra.Command, args []string) {
			key := args[0]
			value := viper.Get(key)
			if value == nil {
				fmt.Printf("%s: (not set)\n", key)
			} else {
				fmt.Printf("%s: %v\n", key, value)
			}
		},
	}
}

func configSetCmd() *cobra.Command {
	return &cobra.Command{
		Use:   "set <key> <value>",
		Short: "Set a configuration value",
		Args:  cobra.ExactArgs(2),
		RunE: func(cmd *cobra.Command, args []string) error {
			key := args[0]
			value := args[1]

			viper.Set(key, value)
			if err := SaveConfig(); err != nil {
				return fmt.Errorf("save config: %w", err)
			}

			fmt.Printf("Set %s = %s\n", key, value)
			return nil
		},
	}
}

func configListCmd() *cobra.Command {
	return &cobra.Command{
		Use:   "list",
		Short: "List all configuration values",
		Run: func(cmd *cobra.Command, args []string) {
			settings := viper.AllSettings()
			for key, value := range settings {
				fmt.Printf("%s: %v\n", key, value)
			}
		},
	}
}
