package executor

import (
	"os"
	"path/filepath"
	"regexp"

	"webby-builder/internal/models"
)

// accentNameRe matches safe accent names (all-lowercase letters, digits, hyphens).
// Accent names are used directly as filenames — reject anything that doesn't
// match to prevent path traversal (e.g. "../evil").
var accentNameRe = regexp.MustCompile(`^[a-z0-9-]+$`)

// writeStyleVariations emits styles/*.json Site Editor style variations from
// the design system: a Dark variation (tokens .dark + the chosen accent's dark
// map) plus one per non-chosen accent in the catalog. Because the base
// theme.json styles reference var:preset|color|base / contrast, a palette-only
// variation restyles the whole site. Existing files win (template/AI-authored).
// Best-effort: write failures are ignored (the theme works without variations).
func writeStyleVariations(workspacePath string, ds *models.DesignSystem) {
	if ds == nil {
		return
	}
	base := parseCSSVars(ds.Tokens, ":root")
	dark := parseCSSVars(ds.Tokens, ".dark")
	stylesDir := filepath.Join(workspacePath, "styles")

	write := func(name, title string, palette []map[string]string) {
		if len(palette) == 0 {
			return
		}
		path := filepath.Join(stylesDir, name+".json")
		if _, err := os.Stat(path); err == nil {
			return
		}
		if err := os.MkdirAll(stylesDir, 0o755); err != nil {
			return
		}
		_ = WriteJSONFileAtomic(path, map[string]interface{}{
			"$schema": wpSchemaURL(),
			"version": 3,
			"title":   title,
			"settings": map[string]interface{}{
				"color": map[string]interface{}{"palette": palette},
			},
		})
	}

	write("dark", "Dark", buildWPPalette(dark, ds.AccentDark))
	for name, pair := range ds.Accents {
		if name == ds.Accent {
			continue
		}
		if !accentNameRe.MatchString(name) {
			continue
		}
		write(name, capitalize(name), buildWPPalette(base, pair.Light))
	}
}
