package registry

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

// emitModuleVersionHeader writes <dir_path>/version_generated.h for a module.
// The header exposes constants the C++ side can read:
//
//	FN_MODULE_<NAME>_VERSION       (const char*)
//	FN_MODULE_<NAME>_NAME          (const char*)
//	FN_MODULE_<NAME>_DESCRIPTION   (const char*)
//
// For C++ modules only (lang == "cpp"). For other langs, returns nil silently.
// Idempotent: only rewrites when content differs.
func emitModuleVersionHeader(m *Module, root string) error {
	if m.Lang != "cpp" {
		return nil
	}
	if m.DirPath == "" {
		return nil
	}

	upper := strings.ToUpper(m.Name)
	macroPrefix := "FN_MODULE_" + upper
	guard := macroPrefix + "_VERSION_GENERATED_H"

	body := fmt.Sprintf(`// Auto-generated by `+"`fn index`"+` — do not edit.
// Module: %s
// Source of truth: modules/%s/module.md
#ifndef %s
#define %s

#define %s_NAME        %q
#define %s_VERSION     %q
#define %s_DESCRIPTION %q

#endif // %s
`, m.Name, m.Name,
		guard, guard,
		macroPrefix, m.Name,
		macroPrefix, m.Version,
		macroPrefix, m.Description,
		guard)

	headerPath := filepath.Join(root, m.DirPath, "version_generated.h")

	// Idempotent: skip write when content already matches.
	if existing, err := os.ReadFile(headerPath); err == nil && string(existing) == body {
		return nil
	}

	if err := os.MkdirAll(filepath.Dir(headerPath), 0o755); err != nil {
		return fmt.Errorf("mkdir %s: %w", filepath.Dir(headerPath), err)
	}
	return os.WriteFile(headerPath, []byte(body), 0o644)
}
