// BreakPilot Compliance SDK - API Gateway
//
// Main entry point for the API Gateway service.
// Handles authentication, rate limiting, and request routing.

package main

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

	"github.com/breakpilot/compliance-sdk/services/api-gateway/internal/api"
	"github.com/breakpilot/compliance-sdk/services/api-gateway/internal/config"
	"github.com/breakpilot/compliance-sdk/services/api-gateway/internal/middleware"
	"github.com/gin-gonic/gin"
	"go.uber.org/zap"
)

func main() {
	// Initialize logger
	logger, _ := zap.NewProduction()
	defer logger.Sync()

	// Load configuration
	cfg, err := config.Load()
	if err != nil {
		logger.Fatal("Failed to load configuration", zap.Error(err))
	}

	// Set Gin mode
	if cfg.Environment == "production" {
		gin.SetMode(gin.ReleaseMode)
	}

	// Initialize router
	router := gin.New()

	// Global middleware
	router.Use(gin.Recovery())
	router.Use(middleware.Logger(logger))
	router.Use(middleware.CORS())
	router.Use(middleware.RequestID())

	// Health check (no auth required)
	router.GET("/health", func(c *gin.Context) {
		c.JSON(http.StatusOK, gin.H{
			"status":  "healthy",
			"service": "api-gateway",
			"version": cfg.Version,
		})
	})

	// API v1 routes
	v1 := router.Group("/api/v1")
	{
		// Public routes (rate limited)
		v1.Use(middleware.RateLimiter(cfg.RateLimit))

		// Auth routes
		auth := v1.Group("/auth")
		{
			auth.POST("/token", api.GetToken)
			auth.POST("/refresh", api.RefreshToken)
		}

		// Protected routes
		protected := v1.Group("")
		protected.Use(middleware.Auth(cfg.JWTSecret))
		protected.Use(middleware.TenantIsolation())
		{
			// State management
			protected.GET("/state/:tenantId", api.GetState)
			protected.POST("/state/save", api.SaveState)
			protected.POST("/state/reset", api.ResetState)

			// DSGVO
			dsgvo := protected.Group("/dsgvo")
			{
				dsgvo.POST("/consent", api.RecordConsent)
				dsgvo.GET("/consent/:userId", api.GetConsents)
				dsgvo.DELETE("/consent/:consentId", api.RevokeConsent)

				dsgvo.POST("/dsr", api.SubmitDSR)
				dsgvo.GET("/dsr", api.ListDSRRequests)
				dsgvo.PUT("/dsr/:requestId", api.UpdateDSRStatus)

				dsgvo.GET("/vvt", api.GetProcessingActivities)
				dsgvo.POST("/vvt", api.CreateProcessingActivity)
				dsgvo.PUT("/vvt/:activityId", api.UpdateProcessingActivity)
				dsgvo.DELETE("/vvt/:activityId", api.DeleteProcessingActivity)

				dsgvo.GET("/tom", api.GetTOMs)
				dsgvo.POST("/tom", api.CreateTOM)
				dsgvo.PUT("/tom/:tomId", api.UpdateTOM)
				dsgvo.DELETE("/tom/:tomId", api.DeleteTOM)

				dsgvo.GET("/dsfa", api.GetDSFAs)
				dsgvo.POST("/dsfa", api.CreateDSFA)
				dsgvo.PUT("/dsfa/:dsfaId", api.UpdateDSFA)

				dsgvo.GET("/retention", api.GetRetentionPolicies)
				dsgvo.POST("/retention", api.CreateRetentionPolicy)
				dsgvo.PUT("/retention/:policyId", api.UpdateRetentionPolicy)
				dsgvo.DELETE("/retention/:policyId", api.DeleteRetentionPolicy)
			}

			// Compliance
			compliance := protected.Group("/compliance")
			{
				compliance.GET("/controls", api.GetControls)
				compliance.POST("/controls", api.CreateControl)
				compliance.PUT("/controls/:controlId", api.UpdateControl)
				compliance.DELETE("/controls/:controlId", api.DeleteControl)

				compliance.GET("/evidence", api.GetEvidence)
				compliance.POST("/evidence", api.UploadEvidence)
				compliance.PUT("/evidence/:evidenceId", api.UpdateEvidence)
				compliance.DELETE("/evidence/:evidenceId", api.DeleteEvidence)

				compliance.GET("/obligations", api.GetObligations)
				compliance.POST("/assessment", api.RunAssessment)

				compliance.GET("/export/pdf", api.ExportPDF)
				compliance.GET("/export/docx", api.ExportDOCX)
			}

			// RAG
			rag := protected.Group("/rag")
			{
				rag.POST("/search", api.SearchRAG)
				rag.POST("/ask", api.AskRAG)
				rag.GET("/regulations", api.GetRegulations)
				rag.POST("/documents", api.UploadDocument)
			}

			// SBOM & Security
			security := protected.Group("/security")
			{
				security.POST("/sbom/generate", api.GenerateSBOM)
				security.GET("/sbom/components", api.GetSBOMComponents)
				security.GET("/sbom/export/:format", api.ExportSBOM)

				security.POST("/scan", api.StartSecurityScan)
				security.GET("/findings", api.GetSecurityFindings)
				security.GET("/recommendations", api.GetRecommendations)
				security.GET("/reports", api.GetSecurityReports)
			}
		}
	}

	// Create HTTP server
	srv := &http.Server{
		Addr:         ":" + cfg.Port,
		Handler:      router,
		ReadTimeout:  15 * time.Second,
		WriteTimeout: 15 * time.Second,
		IdleTimeout:  60 * time.Second,
	}

	// Start server in goroutine
	go func() {
		logger.Info("Starting API Gateway", zap.String("port", cfg.Port))
		if err := srv.ListenAndServe(); err != nil && err != http.ErrServerClosed {
			logger.Fatal("Failed to start server", zap.Error(err))
		}
	}()

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

	logger.Info("Shutting down server...")

	ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
	defer cancel()

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

	logger.Info("Server exited")
}
