// Package main provides a code generator that reads system_tables.json
// and generates Go constants, structs, and TypeScript types.
//
// This ensures a single source of truth for schema definitions.
// If system_tables.json changes, regenerate to get compile-time errors
// for any code using removed/renamed fields.
//
// Usage: go run ./cmd/codegen
package main

import (
	"encoding/json"
	"fmt"
	"log"
	"os"
	"path/filepath"
	"sort"
)

func main() {
	// Find project root by looking for system_tables.json
	jsonPath := findSystemTablesJSON()
	if jsonPath == "" {
		log.Fatal("❌ Could not find backend/internal/bootstrap/system_tables.json")
	}
	fmt.Printf("📖 Reading: %s\n", jsonPath)

	// Determine project root from json path
	// jsonPath is like: .../backend/internal/bootstrap/system_tables.json
	projectRoot := filepath.Dir(filepath.Dir(filepath.Dir(filepath.Dir(jsonPath))))

	// Read and parse JSON
	content, err := os.ReadFile(jsonPath)
	if err != nil {
		log.Fatalf("❌ Failed to read file: %v", err)
	}

	var tables []TableDefinition
	if err := json.Unmarshal(content, &tables); err != nil {
		log.Fatalf("❌ Failed to parse JSON: %v", err)
	}

	// Sort definitions for deterministic output
	sort.Strings(commonFieldNames)

	sort.Slice(tables, func(i, j int) bool {
		return tables[i].TableName < tables[j].TableName
	})

	fmt.Printf("📊 Total Definitions: %d\n", len(tables))

	ctx := &genContext{
		tables:    tables,
		timestamp: "2026-01-01T00:00:00Z", // Fixed timestamp for deterministic generation
	}

	// Generate all outputs
	if err := generateGoTableConstants(ctx, projectRoot); err != nil {
		log.Fatalf("❌ Failed to generate table constants: %v", err)
	}

	if err := generateGoFieldConstants(ctx, projectRoot); err != nil {
		log.Fatalf("❌ Failed to generate field constants: %v", err)
	}

	if err := generateGoStructs(ctx, projectRoot); err != nil {
		log.Fatalf("❌ Failed to generate structs: %v", err)
	}

	if err := generateTypeScript(ctx, projectRoot); err != nil {
		log.Fatalf("❌ Failed to generate TypeScript: %v", err)
	}

	if err := generateSchemaDefinitions(ctx, projectRoot); err != nil {
		log.Fatalf("❌ Failed to generate SchemaDefinitions: %v", err)
	}

	if err := generateGoColumnLists(ctx, projectRoot); err != nil {
		log.Fatalf("❌ Failed to generate column lists: %v", err)
	}

	if err := generateProtectedRecords(ctx, projectRoot); err != nil {
		log.Fatalf("❌ Failed to generate protected records map: %v", err)
	}

	if err := generateErrorCodes(ctx, projectRoot); err != nil {
		log.Fatalf("❌ Failed to generate Error Codes: %v", err)
	}

	if err := generateAPIDTOs(projectRoot); err != nil {
		log.Fatalf("❌ Failed to generate API DTOs: %v", err)
	}

	if err := generateOpenAPI(projectRoot); err != nil {
		log.Fatalf("❌ Failed to generate OpenAPI spec: %v", err)
	}

	// Sync fieldTypes.json from shared to backend/pkg/fieldtypes (Go embed can't follow symlinks)
	if err := syncFieldTypesJSON(projectRoot); err != nil {
		log.Fatalf("❌ Failed to sync fieldTypes.json: %v", err)
	}

	fmt.Println("\n🎉 Code generation complete!")
}

func findSystemTablesJSON() string {
	paths := []string{
		"backend/internal/bootstrap/system_tables.json",
		"internal/bootstrap/system_tables.json",
		"../internal/bootstrap/system_tables.json",
	}

	for _, p := range paths {
		if _, err := os.Stat(p); err == nil {
			abs, _ := filepath.Abs(p)
			return abs
		}
	}
	return ""
}
