package main

import (
	"context"
	"flag"
	"log"
	"os"
	"os/signal"
	"sync"
	"syscall"

	"go.temporal.io/sdk/client"
	"go.temporal.io/sdk/worker"

	"github.com/rockliang/poimen/workflows/action"
	"github.com/rockliang/poimen/workflows/internal/api"
	"github.com/rockliang/poimen/workflows/internal/config"
	"github.com/rockliang/poimen/workflows/pkg/db"
	"github.com/rockliang/poimen/workflows/statemachine"
)

func main() {
	var (
		apiPort = flag.Int("port", 8080, "HTTP API port")
		verbose = flag.Bool("verbose", false, "verbose logging")
	)
	flag.Parse()

	logger := log.New(os.Stdout, "[poimen-server] ", log.LstdFlags|log.Lshortfile)

	// Load configuration
	cfg, err := config.LoadConfig()
	if err != nil {
		logger.Fatalf("failed to load config: %v", err)
	}

	// Connect to database (memory-db via K8s CNPG)
	logger.Println("connecting to database...")
	database, err := db.New(os.Getenv("DATABASE_URL"))
	if err != nil {
		logger.Fatalf("failed to connect to database: %v", err)
	}
	defer database.Close()
	logger.Println("✓ Connected to database")

	// Connect to Temporal
	logger.Printf("connecting to Temporal at %s", cfg.Temporal.HostPort)
	c, err := client.Dial(client.Options{
		HostPort:  cfg.Temporal.HostPort,
		Namespace: cfg.Temporal.Namespace,
	})
	if err != nil {
		logger.Fatalf("failed to connect to temporal: %v", err)
	}
	defer c.Close()

	logger.Println("✓ Connected to Temporal")

	// Create and start Temporal worker
	w := worker.New(c, "default", worker.Options{})

	// Register RoutingWorkflow
	w.RegisterWorkflow(statemachine.RoutingWorkflow)

	// Register activities
	w.RegisterActivity(action.CloneRepoActivity)
	w.RegisterActivity(action.AnalyzeCodeActivity)
	w.RegisterActivity(action.SecurityScanActivity)
	w.RegisterActivity(action.GenerateReportActivity)
	w.RegisterActivity(action.DeploymentPreCheckActivity)
	w.RegisterActivity(action.NotifyStatusActivity)
	w.RegisterActivity(action.ApproveWorkflowActivity)
	w.RegisterActivity(action.ArchiveResultsActivity)
	w.RegisterActivity(action.RetrieveMemoryActivity)
	w.RegisterActivity(action.AssumeRoleActivity)
	w.RegisterActivity(action.LLMInferenceActivity)
	w.RegisterActivity(action.LLMBatchInferenceActivity)
	w.RegisterActivity(action.CanvasReasonerActivity)

	var wg sync.WaitGroup
	errChan := make(chan error, 2)

	// Start Temporal worker
	wg.Add(1)
	go func() {
		defer wg.Done()
		logger.Println("starting Temporal worker...")
		if err := w.Run(worker.InterruptCh()); err != nil {
			errChan <- err
		}
	}()

	// Start HTTP API server
	wg.Add(1)
	go func() {
		defer wg.Done()
		server := api.NewServer(database, c, logger)
		logger.Printf("starting API server on port %d", *apiPort)
		if err := server.Start(*apiPort); err != nil {
			errChan <- err
		}
	}()

	// Wait for interrupt signal
	sigChan := make(chan os.Signal, 1)
	signal.Notify(sigChan, syscall.SIGINT, syscall.SIGTERM)

	go func() {
		sig := <-sigChan
		logger.Printf("received signal: %v", sig)
		w.Stop()
	}()

	// Monitor for errors
	go func() {
		err := <-errChan
		if err != nil {
			logger.Printf("error: %v", err)
			w.Stop()
		}
	}()

	wg.Wait()
	logger.Println("✓ Server stopped gracefully")
}
