// Odoo Go Server — Main entrypoint
// Mirrors: odoo-bin
//
// Usage:
//
//	go run ./cmd/odoo-server
//	ODOO_DB_HOST=localhost ODOO_DB_PORT=5432 go run ./cmd/odoo-server
package main

import (
	"context"
	"log"
	"os"
	"os/signal"
	"path/filepath"
	"syscall"

	"github.com/jackc/pgx/v5/pgxpool"

	// Import all modules (register models via init())
	_ "odoo-go/addons/base"
	_ "odoo-go/addons/account"
	_ "odoo-go/addons/product"
	_ "odoo-go/addons/sale"
	_ "odoo-go/addons/stock"
	_ "odoo-go/addons/purchase"
	_ "odoo-go/addons/hr"
	_ "odoo-go/addons/project"
	_ "odoo-go/addons/crm"
	_ "odoo-go/addons/fleet"
	_ "odoo-go/addons/l10n_de"

	// Google integrations (opt-in, only active with API keys)
	_ "odoo-go/addons/google_address"
	_ "odoo-go/addons/google_translate"
	_ "odoo-go/addons/google_calendar"

	"odoo-go/pkg/modules"
	"odoo-go/pkg/server"
	"odoo-go/pkg/service"
	"odoo-go/pkg/tools"
)

func main() {
	log.SetFlags(log.Ltime | log.Lshortfile)

	// Load configuration
	cfg := tools.DefaultConfig()
	cfg.LoadFromEnv()

	// Auto-detect frontend/ directory relative to the binary if not set
	if cfg.FrontendDir == "" {
		exe, _ := os.Executable()
		candidate := filepath.Join(filepath.Dir(exe), "frontend")
		if _, err := os.Stat(candidate); err != nil {
			// Try relative to working directory
			candidate = "frontend"
		}
		cfg.FrontendDir = candidate
	}
	// Auto-detect build/ directory
	if cfg.BuildDir == "" {
		exe, _ := os.Executable()
		candidate := filepath.Join(filepath.Dir(exe), "build")
		if _, err := os.Stat(candidate); err != nil {
			candidate = "build"
		}
		cfg.BuildDir = candidate
	}

	log.Printf("odoo: Odoo Go Server 19.0")
	log.Printf("odoo: database: %s@%s:%d/%s", cfg.DBUser, cfg.DBHost, cfg.DBPort, cfg.DBName)

	ctx, cancel := context.WithCancel(context.Background())
	defer cancel()

	// Handle shutdown signals
	sigCh := make(chan os.Signal, 1)
	signal.Notify(sigCh, syscall.SIGINT, syscall.SIGTERM)
	go func() {
		sig := <-sigCh
		log.Printf("odoo: received signal %s, shutting down...", sig)
		cancel()
	}()

	// Connect to database
	pool, err := pgxpool.New(ctx, cfg.DSN())
	if err != nil {
		log.Fatalf("odoo: database connection failed: %v", err)
	}
	defer pool.Close()

	if err := pool.Ping(ctx); err != nil {
		log.Fatalf("odoo: database ping failed: %v", err)
	}
	log.Println("odoo: database connected")

	// Load modules (base is auto-registered via init())
	log.Println("odoo: loading modules...")
	if err := modules.LoadModules(modules.All()); err != nil {
		log.Fatalf("odoo: module loading failed: %v", err)
	}
	log.Printf("odoo: %d modules loaded", len(modules.All()))

	// Initialize database schema
	log.Println("odoo: initializing database schema...")
	if err := service.InitDatabase(ctx, pool); err != nil {
		log.Fatalf("odoo: schema init failed: %v", err)
	}

	// Migrate schema: add any missing columns for newly registered fields
	log.Println("odoo: running schema migration...")
	if err := service.MigrateSchema(ctx, pool); err != nil {
		log.Printf("odoo: schema migration warning: %v", err)
	}

	// Check if database needs setup
	if service.NeedsSetup(ctx, pool) {
		log.Println("odoo: database is empty — database manager will be shown at /web/database/manager")
	} else {
		log.Println("odoo: database already initialized")
	}

	// Initialize session table
	if err := server.InitSessionTable(ctx, pool); err != nil {
		log.Printf("odoo: session table init warning: %v", err)
	}

	// Start HTTP server
	srv := server.New(cfg, pool)
	log.Printf("odoo: starting HTTP service on %s:%d", cfg.HTTPInterface, cfg.HTTPPort)

	if err := srv.Start(); err != nil {
		log.Fatalf("odoo: server error: %v", err)
	}
}
