package main

import (
	"context"
	"log"
	"net/http"
	"os"
	"os/signal"
	"syscall"
	"time"

	"github.com/breakpilot/ai-compliance-sdk/internal/api"
	"github.com/breakpilot/ai-compliance-sdk/internal/db"
	"github.com/breakpilot/ai-compliance-sdk/internal/llm"
	"github.com/breakpilot/ai-compliance-sdk/internal/rag"
	"github.com/gin-gonic/gin"
	"github.com/joho/godotenv"
)

func main() {
	// Load environment variables
	if err := godotenv.Load(); err != nil {
		log.Println("No .env file found, using environment variables")
	}

	// Get configuration from environment
	port := getEnv("PORT", "8085")
	dbURL := getEnv("DATABASE_URL", "postgres://localhost:5432/sdk_states?sslmode=disable")
	qdrantURL := getEnv("QDRANT_URL", "http://localhost:6333")
	anthropicKey := getEnv("ANTHROPIC_API_KEY", "")

	// Initialize database connection
	dbPool, err := db.NewPostgresPool(dbURL)
	if err != nil {
		log.Printf("Warning: Database connection failed: %v", err)
		// Continue without database - use in-memory fallback
	}

	// Initialize RAG service
	ragService, err := rag.NewService(qdrantURL)
	if err != nil {
		log.Printf("Warning: RAG service initialization failed: %v", err)
		// Continue without RAG - will return empty results
	}

	// Initialize LLM service
	llmService := llm.NewService(anthropicKey)

	// Create Gin router
	gin.SetMode(gin.ReleaseMode)
	if os.Getenv("GIN_MODE") == "debug" {
		gin.SetMode(gin.DebugMode)
	}

	router := gin.Default()

	// CORS middleware
	router.Use(corsMiddleware())

	// Health check
	router.GET("/health", func(c *gin.Context) {
		c.JSON(http.StatusOK, gin.H{
			"status":    "healthy",
			"timestamp": time.Now().UTC().Format(time.RFC3339),
			"services": gin.H{
				"database": dbPool != nil,
				"rag":      ragService != nil,
				"llm":      anthropicKey != "",
			},
		})
	})

	// API routes
	v1 := router.Group("/sdk/v1")
	{
		// State Management
		stateHandler := api.NewStateHandler(dbPool)
		v1.GET("/state/:tenantId", stateHandler.GetState)
		v1.POST("/state", stateHandler.SaveState)
		v1.DELETE("/state/:tenantId", stateHandler.DeleteState)

		// RAG Search
		ragHandler := api.NewRAGHandler(ragService)
		v1.GET("/rag/search", ragHandler.Search)
		v1.GET("/rag/status", ragHandler.GetCorpusStatus)
		v1.POST("/rag/index", ragHandler.IndexDocument)

		// Document Generation
		generateHandler := api.NewGenerateHandler(llmService, ragService)
		v1.POST("/generate/dsfa", generateHandler.GenerateDSFA)
		v1.POST("/generate/tom", generateHandler.GenerateTOM)
		v1.POST("/generate/vvt", generateHandler.GenerateVVT)
		v1.POST("/generate/gutachten", generateHandler.GenerateGutachten)

		// Checkpoint Validation
		checkpointHandler := api.NewCheckpointHandler()
		v1.GET("/checkpoints", checkpointHandler.GetAll)
		v1.POST("/checkpoints/validate", checkpointHandler.Validate)
	}

	// Create server
	srv := &http.Server{
		Addr:    ":" + port,
		Handler: router,
	}

	// Graceful shutdown
	go func() {
		log.Printf("SDK Backend starting on port %s", port)
		if err := srv.ListenAndServe(); err != nil && err != http.ErrServerClosed {
			log.Fatalf("Failed to start server: %v", err)
		}
	}()

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

	log.Println("Shutting down server...")

	// Give outstanding requests 5 seconds to complete
	ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
	defer cancel()

	if err := srv.Shutdown(ctx); err != nil {
		log.Fatal("Server forced to shutdown:", err)
	}

	// Close database connection
	if dbPool != nil {
		dbPool.Close()
	}

	log.Println("Server exited")
}

func getEnv(key, defaultValue string) string {
	if value := os.Getenv(key); value != "" {
		return value
	}
	return defaultValue
}

func corsMiddleware() gin.HandlerFunc {
	return func(c *gin.Context) {
		c.Writer.Header().Set("Access-Control-Allow-Origin", "*")
		c.Writer.Header().Set("Access-Control-Allow-Credentials", "true")
		c.Writer.Header().Set("Access-Control-Allow-Headers", "Content-Type, Content-Length, Accept-Encoding, X-CSRF-Token, Authorization, accept, origin, Cache-Control, X-Requested-With, If-Match, If-None-Match")
		c.Writer.Header().Set("Access-Control-Allow-Methods", "POST, OPTIONS, GET, PUT, DELETE")
		c.Writer.Header().Set("Access-Control-Expose-Headers", "ETag, Last-Modified")

		if c.Request.Method == "OPTIONS" {
			c.AbortWithStatus(204)
			return
		}

		c.Next()
	}
}
