package cmd

import (
	"fmt"
	"log"
	"net/http"
	"os"
	"os/signal"
	"strings"
	"syscall"

	"github.com/go-chi/chi/v5"
	"github.com/go-chi/chi/v5/middleware"
	"github.com/go-chi/cors"
	"github.com/spf13/cobra"
	"github.com/spf13/viper"

	"github.com/insertr/insertr/internal/api"
	"github.com/insertr/insertr/internal/auth"
	"github.com/insertr/insertr/internal/content"
	"github.com/insertr/insertr/internal/db"
)

var serveCmd = &cobra.Command{
	Use:   "serve",
	Short: "Start the content API server",
	Long: `Start the HTTP API server that provides content storage and retrieval.
Supports both development and production modes with SQLite or PostgreSQL databases.`,
	Run: runServe,
}

var (
	port    int
	devMode bool
)

func init() {
	serveCmd.Flags().IntVarP(&port, "port", "p", 8080, "Server port")
	serveCmd.Flags().BoolVar(&devMode, "dev-mode", false, "Enable development mode features")

	// Bind flags to viper
	viper.BindPFlag("server.port", serveCmd.Flags().Lookup("port"))
	viper.BindPFlag("dev_mode", serveCmd.Flags().Lookup("dev-mode"))
}

func runServe(cmd *cobra.Command, args []string) {
	// Get configuration values
	port := viper.GetInt("server.port")
	dbPath := viper.GetString("database.path")
	devMode := viper.GetBool("dev_mode")

	// Initialize database
	database, err := db.NewDatabase(dbPath)
	if err != nil {
		log.Fatalf("Failed to initialize database: %v", err)
	}
	defer database.Close()

	// Initialize authentication service
	authConfig := &auth.AuthConfig{
		DevMode:   viper.GetBool("dev_mode"),
		JWTSecret: viper.GetString("jwt_secret"),
	}

	// Set default JWT secret if not configured
	if authConfig.JWTSecret == "" {
		authConfig.JWTSecret = "dev-secret-change-in-production"
		if authConfig.DevMode {
			log.Printf("🔑 Using default JWT secret for development")
		}
	}

	authService := auth.NewAuthService(authConfig)

	// Initialize content client for site manager
	contentClient := content.NewDatabaseClient(database)

	// Initialize site manager
	siteManager := content.NewSiteManager(contentClient, devMode)

	// Load sites from configuration
	if siteConfigs := viper.Get("server.sites"); siteConfigs != nil {
		if configs, ok := siteConfigs.([]interface{}); ok {
			var sites []*content.SiteConfig
			for _, configInterface := range configs {
				if configMap, ok := configInterface.(map[string]interface{}); ok {
					site := &content.SiteConfig{}
					if siteID, ok := configMap["site_id"].(string); ok {
						site.SiteID = siteID
					}
					if path, ok := configMap["path"].(string); ok {
						site.Path = path
					}
					if sourcePath, ok := configMap["source_path"].(string); ok {
						site.SourcePath = sourcePath
					}
					if domain, ok := configMap["domain"].(string); ok {
						site.Domain = domain
					}
					if autoEnhance, ok := configMap["auto_enhance"].(bool); ok {
						site.AutoEnhance = autoEnhance
					}
					if site.SiteID != "" && site.Path != "" {
						sites = append(sites, site)
					}
				}
			}
			if err := siteManager.RegisterSites(sites); err != nil {
				log.Printf("⚠️ Failed to register some sites: %v", err)
			}
		}
	}

	// Auto-enhance sites if enabled
	if devMode {
		log.Printf("🔄 Auto-enhancing sites in development mode...")
		if err := siteManager.EnhanceAllSites(); err != nil {
			log.Printf("⚠️ Some sites failed to enhance: %v", err)
		}
	}

	// Initialize handlers
	contentHandler := api.NewContentHandler(database, authService)
	contentHandler.SetSiteManager(siteManager)

	// Setup Chi router
	router := chi.NewRouter()

	// Add Chi middleware
	router.Use(middleware.Logger)
	router.Use(middleware.Recoverer)
	router.Use(cors.Handler(cors.Options{
		AllowedOrigins:   []string{"*"}, // In dev mode, allow all origins
		AllowedMethods:   []string{"GET", "POST", "PUT", "DELETE", "OPTIONS"},
		AllowedHeaders:   []string{"*"},
		ExposedHeaders:   []string{"Link"},
		AllowCredentials: true,
		MaxAge:           300, // Maximum value not ignored by any of major browsers
	}))
	router.Use(api.ContentTypeMiddleware)

	// Health check endpoint
	router.Get("/health", api.HealthMiddleware())

	// Static library serving (for demo sites)
	router.Get("/insertr.js", contentHandler.ServeInsertrJS)
	router.Get("/insertr.css", contentHandler.ServeInsertrCSS)

	// API routes
	router.Route("/api", func(apiRouter chi.Router) {
		// Site enhancement endpoint
		apiRouter.Post("/enhance", contentHandler.EnhanceSite)

		// Content endpoints
		apiRouter.Route("/content", func(contentRouter chi.Router) {
			contentRouter.Get("/bulk", contentHandler.GetBulkContent)
			contentRouter.Get("/{id}", contentHandler.GetContent)
			contentRouter.Get("/", contentHandler.GetAllContent)
			contentRouter.Post("/", contentHandler.CreateContent)

			// Version control endpoints
			contentRouter.Get("/{id}/versions", contentHandler.GetContentVersions)
			contentRouter.Post("/{id}/rollback", contentHandler.RollbackContent)
		})
	})

	// Static site serving - serve registered sites at /sites/{site_id}
	// Custom file server that fixes CSS MIME types
	for siteID, siteConfig := range siteManager.GetAllSites() {
		log.Printf("📁 Serving site %s from %s at /sites/%s/", siteID, siteConfig.Path, siteID)

		// Create custom file server with MIME type fixing
		fileServer := http.FileServer(http.Dir(siteConfig.Path))
		customHandler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
			// Fix MIME type for CSS files (including extensionless ones in css/ directory)
			if strings.Contains(r.URL.Path, "/css/") {
				w.Header().Set("Content-Type", "text/css; charset=utf-8")
			}
			fileServer.ServeHTTP(w, r)
		})

		router.Handle("/sites/"+siteID+"/*", http.StripPrefix("/sites/"+siteID+"/", customHandler))
	}

	// Start server
	addr := fmt.Sprintf(":%d", port)
	mode := "production"
	if devMode {
		mode = "development"
	}

	fmt.Printf("🚀 Insertr Content Server starting (%s mode)...\n", mode)
	fmt.Printf("📁 Database: %s\n", dbPath)
	fmt.Printf("🌐 Server running at: http://localhost%s\n", addr)
	fmt.Printf("💚 Health check: http://localhost%s/health\n", addr)
	fmt.Printf("📊 API endpoints:\n")
	fmt.Printf("   GET    /api/content?site_id={site}\n")
	fmt.Printf("   GET    /api/content/{id}?site_id={site}\n")
	fmt.Printf("   GET    /api/content/bulk?site_id={site}&ids[]={id1}&ids[]={id2}\n")
	fmt.Printf("   POST   /api/content\n")
	fmt.Printf("   PUT    /api/content/{id}\n")
	fmt.Printf("   GET    /api/content/{id}/versions?site_id={site}\n")
	fmt.Printf("   POST   /api/content/{id}/rollback\n")
	fmt.Printf("🌐 Static sites:\n")
	for siteID, _ := range siteManager.GetAllSites() {
		fmt.Printf("   %s: http://localhost%s/sites/%s/\n", siteID, addr, siteID)
	}
	fmt.Printf("\n🔄 Press Ctrl+C to shutdown gracefully\n\n")

	// Setup graceful shutdown
	server := &http.Server{
		Addr:    addr,
		Handler: router,
	}

	// Start server in a goroutine
	go func() {
		if err := server.ListenAndServe(); err != nil && err != http.ErrServerClosed {
			log.Fatalf("Server failed to start: %v", err)
		}
	}()

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

	fmt.Println("\n🛑 Shutting down server...")
	if err := server.Close(); err != nil {
		log.Fatalf("Server forced to shutdown: %v", err)
	}

	fmt.Println("✅ Server shutdown complete")
}
