// Package server — JS bundle builder.
//
// Reads original Odoo JS source files from the addon directories, transpiles
// ES modules to odoo.define() format using the Go transpiler, and
// concatenates everything into a single JS bundle served at startup.
//
// This replaces the separate `go run ./cmd/transpile` build step — no
// pre-transpiled build/js directory is needed.
package server

import (
	"log"
	"net/http"
	"os"
	"path/filepath"
	"strings"
	"time"

	"odoo-go/pkg/tools"
)

// buildJSBundle reads all JS files listed in assets_js.txt from the original
// Odoo source directories, transpiles ES modules on-the-fly, and returns the
// concatenated bundle as a single string.
//
// xmlTemplateBundle is the compiled XML templates JS (from compileXMLTemplates),
// injected where xml_templates_bundle.js appears in the asset list.
//
// The first entry (module_loader.js) is excluded from the bundle because it
// must load before the bundle via its own <script> tag.
//
// The bundle is built once at server startup and cached in memory.
func buildJSBundle(config *tools.Config, xmlTemplateBundle string) string {
	start := time.Now()
	var buf strings.Builder
	transpiled := 0
	copied := 0
	skipped := 0

	for _, src := range jsFiles {
		if strings.HasSuffix(src, ".scss") {
			continue
		}

		// module_loader.js is served via its own <script> tag before the
		// bundle (it defines odoo.define/odoo.loader). Skip it here.
		if src == "/web/static/src/module_loader.js" {
			continue
		}

		// The XML templates bundle is generated in-memory by
		// compileXMLTemplates. Inject it where the placeholder appears
		// in the asset list instead of reading a file from disk.
		if src == "/web/static/src/xml_templates_bundle.js" {
			if xmlTemplateBundle != "" {
				buf.WriteString(";\n")
				buf.WriteString(xmlTemplateBundle)
				buf.WriteString("\n")
			}
			continue
		}

		// Read source from frontend directory
		content := ""
		rel := strings.TrimPrefix(src, "/")
		if config.FrontendDir != "" {
			fullPath := filepath.Join(config.FrontendDir, rel)
			if data, err := os.ReadFile(fullPath); err == nil {
				content = string(data)
			}
		}

		// Also try build dir as fallback (for pre-compiled assets)
		if content == "" && config.BuildDir != "" {
			buildPath := filepath.Join(config.BuildDir, rel)
			if data, err := os.ReadFile(buildPath); err == nil {
				content = string(data)
			}
		}

		if content == "" {
			skipped++
			continue
		}

		// Transpile ES modules to odoo.define() format
		if IsOdooModule(src, content) {
			content = TranspileJS(src, content)
			transpiled++
		} else {
			copied++
		}

		buf.WriteString(";\n")
		buf.WriteString(content)
		buf.WriteString("\n")
	}

	log.Printf("bundle: %d transpiled + %d copied + %d skipped in %s (%d KB)",
		transpiled, copied, skipped, time.Since(start).Round(time.Millisecond), buf.Len()/1024)
	return buf.String()
}

// handleJSBundle serves the concatenated JS bundle from memory.
// The bundle is built once at startup and cached in s.jsBundle.
func (s *Server) handleJSBundle(w http.ResponseWriter, r *http.Request) {
	if r.Method != http.MethodGet && r.Method != http.MethodHead {
		http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
		return
	}
	w.Header().Set("Content-Type", "application/javascript; charset=utf-8")
	w.Header().Set("Cache-Control", "public, max-age=3600")
	w.Write([]byte(s.jsBundle))
}
