package cmd

import (
	"bytes"
	"encoding/json"
	"fmt"
	"os"
	"os/exec"
	"path/filepath"
	"strings"

	"github.com/spf13/cobra"
)

// Config holds Gitea connection details stored in ~/.gtea.json
type Config struct {
	URL      string `json:"url"`
	Token    string `json:"token"`
	Username string `json:"username"`

	// Homelab / beepc
	SSHHost     string `json:"ssh_host"`
	SSHUser     string `json:"ssh_user"`
	ProjectsDir string `json:"projects_dir"`
	HomelabDir  string `json:"homelab_dir"`
	ProxyHost   string `json:"proxy_host"` // IP/hostname Caddy on VPS uses to reach beepc

	// Caddy reverse proxy
	CaddyConfDir   string `json:"caddy_conf_dir"`
	CaddyReloadCmd string `json:"caddy_reload_cmd"`

	// Project defaults
	Domain    string `json:"domain"`
	PortStart int    `json:"port_range_start"`
}

var rootCmd = &cobra.Command{
	Use:   "gtea",
	Short: "Gitea project and repo manager",
	Long:  "gtea — create Gitea repos, commit, push, and pull without leaving the terminal.",
}

func Execute() {
	if err := rootCmd.Execute(); err != nil {
		os.Exit(1)
	}
}

func init() {
	rootCmd.AddCommand(configCmd)
	rootCmd.AddCommand(initCmd)
	rootCmd.AddCommand(commitCmd)
	rootCmd.AddCommand(pushCmd)
	rootCmd.AddCommand(pullCmd)
	rootCmd.AddCommand(statusCmd)
}

func configPath() string {
	home, _ := os.UserHomeDir()
	return filepath.Join(home, ".gtea.json")
}

func loadConfig() (*Config, error) {
	data, err := os.ReadFile(configPath())
	if err != nil {
		return nil, fmt.Errorf("no config found — run 'gtea config' first")
	}
	var cfg Config
	if err := json.Unmarshal(data, &cfg); err != nil {
		return nil, fmt.Errorf("invalid config: %w", err)
	}
	if cfg.URL == "" || cfg.Token == "" || cfg.Username == "" {
		return nil, fmt.Errorf("incomplete config — run 'gtea config' to fill in missing fields")
	}
	return &cfg, nil
}

func saveConfig(cfg *Config) error {
	data, err := json.MarshalIndent(cfg, "", "  ")
	if err != nil {
		return err
	}
	return os.WriteFile(configPath(), data, 0600)
}

// runGit runs a git command in dir (use "." for current directory).
func runGit(dir string, args ...string) error {
	c := exec.Command("git", args...)
	c.Dir = dir
	c.Stdout = os.Stdout
	c.Stderr = os.Stderr
	if err := c.Run(); err != nil {
		return fmt.Errorf("git %s: %w", strings.Join(args, " "), err)
	}
	return nil
}

// currentBranch returns the name of the currently checked-out branch.
func currentBranch() (string, error) {
	out, err := exec.Command("git", "rev-parse", "--abbrev-ref", "HEAD").Output()
	if err != nil {
		return "", err
	}
	return string(bytes.TrimSpace(out)), nil
}

// authCloneURL injects token credentials into an HTTPS clone URL.
func authCloneURL(cfg *Config, cloneURL string) string {
	if strings.HasPrefix(cloneURL, "https://") {
		return strings.Replace(
			cloneURL,
			"https://",
			fmt.Sprintf("https://%s:%s@", cfg.Username, cfg.Token),
			1,
		)
	}
	return cloneURL
}
