package jsbundler

import "path/filepath"

// Config tells the bundler where the application tree and the shared kjol JS
// tree live. The bundler always runs from the app root, so relative paths are
// resolved against that working directory (absolute paths also work).
//
// When WebDir is empty the bundler runs in single-tree mode: the kit, vendored
// runtime, icons, and styles are expected under AppFrontend (the pre-extraction
// layout). When WebDir points at kjol/go/jsruntime, those come from the shared
// tree and the app supplies only its pages/routes/brand.
type Config struct {
	AppFrontend string // app frontend source root (default "frontend")
	WebDir      string // path to kjol/go/jsruntime; "" => single-tree under AppFrontend
	Output      string // build output dir (default "wwwroot")
	GenGoDir    string // dir for generated Go, e.g. public_pages.gen.go (default "internal/handlers")
	GenTSDir    string // dir for generated TS, e.g. faIcons.ts (default AppFrontend/src/ui/generated)
}

// Package-level resolved configuration. Set once by Configure (called from
// Build / StartDevHMR) and read by every stage. Defaults preserve the original
// single-tree behaviour so nothing breaks before an app opts into the kjol tree.
var (
	frontendDir = "frontend"
	outputDir   = "wwwroot"
	webDir      = "" // kjol/go/jsruntime; empty => single-tree
	genGoDir    = "internal/handlers"
	genTSDir    = filepath.Join("frontend", "src", "ui", "generated")
)

// Configure applies c, filling defaults for empty fields.
func Configure(c Config) {
	if c.AppFrontend != "" {
		frontendDir = c.AppFrontend
	}
	if c.Output != "" {
		outputDir = c.Output
	}
	if c.GenGoDir != "" {
		genGoDir = c.GenGoDir
	}
	webDir = c.WebDir
	if c.GenTSDir != "" {
		genTSDir = c.GenTSDir
	} else {
		genTSDir = filepath.Join(frontendDir, "src", "ui", "generated")
	}
}

// webRoot is the kjol JS tree (@kjol/* root), falling back to the app frontend
// in single-tree mode.
func webRoot() string {
	if webDir != "" {
		return webDir
	}
	return frontendDir
}

// uikitDir is where the shared Solid component kit lives (@ui/* root).
func uikitDir() string {
	if webDir != "" {
		return filepath.Join(webDir, "uikit")
	}
	return filepath.Join(frontendDir, "src", "ui")
}

// iconsDirs lists the FontAwesome SVG source roots in resolution precedence
// order: the app's own kit first, kjol's second.
//
// The app has to win. kjol ships a SUBSET — the icons its own kit and example
// reference — while an app carries the full FontAwesome kit it licensed. If kjol
// were searched first (or searched alone, as this used to be when WebDir was
// set), an app adopting the shared tree would silently regenerate its registry
// from kjol's few dozen icons and lose every other icon it uses, with no error:
// the registry would simply come back smaller and the icons would render blank.
//
// Searching both, app-first, means an app-side icon of the same name overrides
// kjol's, and an icon kjol has never heard of still resolves.
func iconsDirs() []string {
	if webDir != "" {
		return []string{filepath.Join(frontendDir, "icons"), filepath.Join(webDir, "icons")}
	}
	return []string{filepath.Join(frontendDir, "icons")}
}

// vendorDirs lists the vendored-runtime roots in resolution precedence order.
// The kjol runtime comes first so its solid-js wins (a split reactive instance
// silently breaks effect flushing).
func vendorDirs() []string {
	if webDir != "" {
		return []string{filepath.Join(webDir, "runtime"), filepath.Join(frontendDir, "vendor")}
	}
	return []string{filepath.Join(frontendDir, "vendor")}
}

// faOutPath is where the generated FA registry is written (app-owned).
func faOutPath() string { return filepath.Join(genTSDir, "faIcons.ts") }
