package compliance

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

	"github.com/gitlink-org/gitlink-cli/shortcuts/common"
)

func Shortcuts() []*common.Shortcut {
	return []*common.Shortcut{
		{
			Name:        "scan",
			Description: "Full compliance scan (all five modules)",
			Flags: []common.Flag{
				{Name: "module", Short: "m", Usage: "Comma-separated modules: license,deps,secrets,exposure,vocab"},
			},
			Run: runScan,
		},
		{Name: "license", Description: "License compliance check", Run: runLicense},
		{Name: "deps", Description: "Dependency license check", Run: runDeps},
		{Name: "secrets", Description: "Hardcoded secrets scan", Run: runSecrets},
		{Name: "exposure", Description: "PII and network exposure scan", Run: runExposure},
		{Name: "vocab", Description: "Sensitive vocabulary scan", Run: runVocab},
	}
}

func repoRoot() (string, error) {
	dir, err := os.Getwd()
	if err != nil {
		return "", fmt.Errorf("get working directory: %w", err)
	}
	// find git root
	for {
		if _, err := os.Stat(filepath.Join(dir, ".git")); err == nil {
			return dir, nil
		}
		parent := filepath.Dir(dir)
		if parent == dir {
			return dir, nil // fallback to cwd
		}
		dir = parent
	}
}

// runScan is the full scan (all modules).
func runScan(ctx *common.RuntimeContext) error {
	root, err := repoRoot()
	if err != nil {
		return err
	}

	selected := ctx.Arg("module")
	var modules []string
	if selected != "" {
		modules = parseModules(selected)
	} else {
		modules = []string{"secrets", "exposure", "vocab"}
	}

	// license and deps checks
	var allFindings []Finding
	for _, m := range modules {
		switch m {
		case "license":
			allFindings = append(allFindings, checkLicense(root)...)
		case "deps":
			allFindings = append(allFindings, checkDeps(root)...)
		case "secrets", "exposure", "vocab":
			rules := allRules()[m]
			allFindings = append(allFindings, scanFiles(root, rules)...)
		}
	}

	return outputReport(ctx, allFindings, modules)
}

func runLicense(ctx *common.RuntimeContext) error {
	root, _ := repoRoot()
	findings := checkLicense(root)
	return outputReport(ctx, findings, []string{"license"})
}

func runDeps(ctx *common.RuntimeContext) error {
	root, _ := repoRoot()
	findings := checkDeps(root)
	return outputReport(ctx, findings, []string{"deps"})
}

func runSecrets(ctx *common.RuntimeContext) error {
	root, _ := repoRoot()
	findings := scanFiles(root, allRules()["secrets"])
	return outputReport(ctx, findings, []string{"secrets"})
}

func runExposure(ctx *common.RuntimeContext) error {
	root, _ := repoRoot()
	findings := scanFiles(root, allRules()["exposure"])
	return outputReport(ctx, findings, []string{"exposure"})
}

func runVocab(ctx *common.RuntimeContext) error {
	root, _ := repoRoot()
	findings := scanFiles(root, allRules()["vocab"])
	return outputReport(ctx, findings, []string{"vocab"})
}

func parseModules(s string) []string {
	var result []string
	seen := map[string]bool{}
	for _, m := range strings.Split(s, ",") {
		m = strings.TrimSpace(m)
		valid := map[string]bool{"license": true, "deps": true, "secrets": true, "exposure": true, "vocab": true}
		if valid[m] && !seen[m] {
			result = append(result, m)
			seen[m] = true
		}
	}
	return result
}
