package esr

import (
	"esr/internal/config"
	"esr/internal/esr/plugins"
	"fmt"

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

type ModeType int

const (
	ModeBuilder ModeType = iota
	ModeServer
	ModeRunner
)

func ModeOptions(config *config.Config, mode ModeType, entryPoint, tempFilePath string) *api.BuildOptions {
	buildOptions := api.BuildOptions{
		EntryPoints: []string{entryPoint},
		Plugins:     []api.Plugin{plugins.EnvPlugin},
	}

	// Apply common settings based on the mode
	getSourceMap := func(sourcemap bool) api.SourceMap {
		if sourcemap {
			return api.SourceMapLinked
		}
		return api.SourceMapNone
	}

	switch mode {
	case ModeBuilder:
		buildOptions.Bundle = config.Build.Bundle
		buildOptions.Outdir = config.Build.Outdir
		buildOptions.MinifySyntax = config.Build.Minify
		buildOptions.MinifyWhitespace = config.Build.MinifyWhitespace
		buildOptions.MinifyIdentifiers = config.Build.MinifyIdentifiers
		buildOptions.JSXFactory = config.Build.JSXFactory
		buildOptions.JSXImportSource = config.Build.JSXImportSource
		buildOptions.Sourcemap = getSourceMap(config.Build.Sourcemap)
		buildOptions.External = config.Build.External
	case ModeServer:
		buildOptions.Bundle = config.Serve.Bundle
		buildOptions.Outdir = config.Serve.Outdir
		buildOptions.MinifySyntax = config.Serve.Minify
		buildOptions.MinifyWhitespace = config.Serve.MinifyWhitespace
		buildOptions.MinifyIdentifiers = config.Serve.MinifyIdentifiers
		buildOptions.JSXFactory = config.Serve.JSXFactory
		buildOptions.JSXImportSource = config.Serve.JSXImportSource
		buildOptions.Sourcemap = getSourceMap(config.Serve.Sourcemap)
		buildOptions.External = config.Serve.External
	case ModeRunner:
		buildOptions.Bundle = true
		buildOptions.Format = api.FormatESModule
		buildOptions.Platform = api.PlatformNode
		buildOptions.Outfile = tempFilePath
		buildOptions.Outdir = ""
		buildOptions.Sourcemap = getSourceMap(config.Run.Sourcemap)
		buildOptions.External = config.Run.External
	}

	// Apply format
	switch config.Format {
	case "esm":
		buildOptions.Format = api.FormatESModule
	case "cjs":
		buildOptions.Format = api.FormatCommonJS
	case "iife":
		buildOptions.Format = api.FormatIIFE
	default:
		buildOptions.Format = api.FormatDefault
		fmt.Printf("Unknown format: %s, using default\n", config.Format)
	}

	// Apply platform
	switch config.Platform {
	case "browser":
		buildOptions.Platform = api.PlatformBrowser
	case "node":
		buildOptions.Platform = api.PlatformNode
	case "neutral":
		buildOptions.Platform = api.PlatformNeutral
	default:
		buildOptions.Platform = api.PlatformDefault
		fmt.Printf("Unknown platform: %s, using default\n", config.Platform)
	}

	switch config.JSX {
	case "preserve":
		buildOptions.JSX = api.JSXPreserve
	case "transform":
		buildOptions.JSX = api.JSXTransform
	case "automatic":
		buildOptions.JSX = api.JSXAutomatic
	default:
		buildOptions.JSX = api.JSXPreserve
		fmt.Printf("Unknown JSX: %s, using default\n", config.JSX)
	}

	// Default loaders
	var loaders = map[string]api.Loader{
		".js":    api.LoaderJS,
		".mjs":   api.LoaderJS,
		".cjs":   api.LoaderJS,
		".jsx":   api.LoaderJSX,
		".ts":    api.LoaderTS,
		".tsx":   api.LoaderTSX,
		".mts":   api.LoaderTS,
		".css":   api.LoaderCSS,
		".json":  api.LoaderJSON,
		".txt":   api.LoaderText,
		".html":  api.LoaderText,
		".md":    api.LoaderText,
		".svg":   api.LoaderDataURL,
		".png":   api.LoaderDataURL,
		".webp":  api.LoaderDataURL,
		".gif":   api.LoaderDataURL,
		".ttf":   api.LoaderDataURL,
		".eot":   api.LoaderDataURL,
		".woff":  api.LoaderDataURL,
		".woff2": api.LoaderDataURL,
	}

	// Overwrite sane default loaders with ones from config
	for ext, loader := range config.Loader {
		switch loader {
		case "file":
			loaders[ext] = api.LoaderFile
		case "dataurl":
			loaders[ext] = api.LoaderDataURL
		case "binary":
			loaders[ext] = api.LoaderBinary
		case "text":
			loaders[ext] = api.LoaderText
		case "js":
			loaders[ext] = api.LoaderJS
		case "jsx":
			loaders[ext] = api.LoaderJSX
		case "tsx":
			loaders[ext] = api.LoaderTSX
		case "ts":
			loaders[ext] = api.LoaderTS
		case "json":
			loaders[ext] = api.LoaderJSON
		case "css":
			loaders[ext] = api.LoaderCSS
		case "default":
			loaders[ext] = api.LoaderDefault
		// Add additional cases if necessary for other loaders
		default:
			fmt.Printf("Unknown loader: %s for extension %s, using none\n", loader, ext)
			loaders[ext] = api.LoaderNone
		}
	}

	buildOptions.Loader = loaders

	return &buildOptions
}
