package bundler

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

	esbuild "github.com/evanw/esbuild/pkg/api"
)

// aliasRoots maps the framework import prefixes to absolute filesystem roots:
//
//	@ui/*     -> kjol web kit (shared Solid components)
//	@kjol/*   -> kjol web root (auth, utils, hooks, ssr, env.ts, ...)
//	@appgen/* -> the app's generated dir (faIcons registry etc. — app-owned)
//
// In single-tree mode @ui/@kjol resolve back under the app frontend.
func aliasRoots() map[string]string {
	abs := func(p string) string { a, _ := filepath.Abs(p); return a }
	return map[string]string{
		"@ui":     abs(kitSrcDir()),
		"@kjol":   abs(webRoot()),
		"@appgen": abs(genTSDir),
	}
}

// resolveAlias turns "<root>/<rest>" into a concrete file, probing the usual
// TS/JS extensions and index files when the specifier is extensionless.
func resolveAlias(root, rest string) (string, bool) {
	base := filepath.Join(root, filepath.FromSlash(rest))
	var cands []string
	if filepath.Ext(base) != "" {
		cands = append(cands, base)
	} else {
		for _, e := range []string{".tsx", ".ts", ".jsx", ".js"} {
			cands = append(cands, base+e)
		}
		for _, e := range []string{".tsx", ".ts", ".jsx", ".js"} {
			cands = append(cands, filepath.Join(base, "index"+e))
		}
	}
	for _, c := range cands {
		if fi, err := os.Stat(c); err == nil && !fi.IsDir() {
			return c, true
		}
	}
	return "", false
}

// aliasPlugin resolves @ui / @kjol / @appgen imports to absolute paths across the
// app and kjol web trees. It sits before the vendor resolvers; the Solid
// compiler's OnLoad then compiles any .tsx/.jsx it points at.
func aliasPlugin() esbuild.Plugin {
	roots := aliasRoots()
	return esbuild.Plugin{
		Name: "kjol-alias",
		Setup: func(b esbuild.PluginBuild) {
			b.OnResolve(esbuild.OnResolveOptions{Filter: `^@(ui|kjol|appgen)/`}, func(a esbuild.OnResolveArgs) (esbuild.OnResolveResult, error) {
				slash := strings.IndexByte(a.Path, '/')
				if slash < 0 {
					return esbuild.OnResolveResult{}, nil
				}
				prefix, rest := a.Path[:slash], a.Path[slash+1:]
				root, ok := roots[prefix]
				if !ok {
					return esbuild.OnResolveResult{}, nil
				}
				if p, ok := resolveAlias(root, rest); ok {
					return esbuild.OnResolveResult{Path: p}, nil
				}
				return esbuild.OnResolveResult{}, fmt.Errorf("kjol-alias: cannot resolve %q under %s", a.Path, root)
			})
		},
	}
}
