package main

import (
	"fmt"
	"log"
	"os"

	"gauth-central/api/middlewares"
	"gauth-central/api/routes"
	"gauth-central/config"
	"gauth-central/internal/database"
	"gauth-central/internal/models"
	"gauth-central/internal/services"
	"gauth-central/pkg/utils"

	"github.com/gin-gonic/gin"
	"github.com/gorilla/sessions"
	"github.com/markbates/goth"
	"github.com/markbates/goth/gothic"
	"github.com/markbates/goth/providers/github"
	"github.com/markbates/goth/providers/google"
)

// @title GAuth-Central API
// @version 1.0
// @description Centralized Authentication Service
// @BasePath /v1
// @securityDefinitions.apikey ApiKeyAuth
// @in header
// @name Authorization
func main() {
	// 1. Load Config
	config.LoadConfig()

	// 2. Setup Database
	database.ConnectDB()
	database.Migrate()

	// Check for seed-admin command
	if len(os.Args) > 1 && os.Args[1] == "seed-admin" {
		fmt.Println("Seeding default admin user...")
		database.SeedDefaultAdmin()
		fmt.Println("Admin seeding completed.")
		return
	}

	// Check for add-cors command
	if len(os.Args) > 2 && os.Args[1] == "add-cors" {
		origin := os.Args[2]
		fmt.Printf("Adding CORS origin: %s\n", origin)
		settingsService := services.NewSettingsService()
		err := settingsService.CreateCorsWhitelist(&models.CorsWhitelist{
			Origin:      origin,
			Description: "Added via CLI",
			IsActive:    true,
			CreatedBy:   "system",
		})
		if err != nil {
			if err == services.ErrCorsOriginExists {
				fmt.Printf("Origin already exists: %s\n", origin)
			} else {
				log.Fatalf("Failed to add CORS origin: %v", err)
			}
		} else {
			fmt.Println("Successfully added CORS origin.")
		}
		return
	}

	fmt.Println(`
   ___  __   __  ___   ___  _  __  ___  _  _  ___  
  | _ )| |  /  \|   \ | _ ) /   \| |/ / | __|| \| ||   \ 
  | _ \| |_| () | |) || _ \|  -  | ' <  | _| | .  || |) |
  |___/|____\__/|___/ |___/|_| |_|_|\_\ |___||_|\_||___/ 
                                                       
 `)
	fmt.Println("   Go Backend | v1.0.0 | " + utils.ColorGreen + "Running" + utils.ColorReset)
	fmt.Println()

	// 3. Setup Redis
	database.ConnectRedis()
	if err := database.FlushAll(); err != nil {
		log.Printf("Warning: Failed to flush Redis cache: %v", err)
	}

	// 4. Setup OAuth Providers
	setupProviders()

	// 5. Setup Services
	settingsService := services.NewSettingsService()

	// Display CORS configuration
	displayCorsConfiguration(settingsService)

	// 6. Setup Router
	r := gin.New()
	r.Use(gin.Recovery())
	r.Use(gin.Logger())

	// Dynamic CORS Middleware (uses database whitelist/blacklist)
	r.Use(middlewares.DynamicCorsMiddleware(settingsService))

	// Silence trusted proxy warning for dev
	r.SetTrustedProxies(nil)
	routes.SetupRoutes(r)

	// 6. Run Server
	log.Printf("Server running on port %s", config.AppConfig.Port)
	log.Printf("Swagger Documentation: http://localhost:%s/docs/index.html", config.AppConfig.Port)
	if err := r.Run(":" + config.AppConfig.Port); err != nil {
		log.Fatal("Failed to start server:", err)
	}
}

func setupProviders() {
	// Configure Gothic session store
	sessionSecret := os.Getenv("SESSION_SECRET")
	if sessionSecret == "" {
		log.Println("Warning: SESSION_SECRET not set, using default (not secure for production)")
		sessionSecret = "default-session-secret-change-in-production"
	}

	maxAge := 86400 * 30 // 30 days
	isProd := false      // Set to true in production

	store := sessions.NewCookieStore([]byte(sessionSecret))
	store.MaxAge(maxAge)
	store.Options.Path = "/"
	store.Options.HttpOnly = true // HttpOnly for security
	store.Options.Secure = isProd // Set true in production (HTTPS only)

	gothic.Store = store

	goth.UseProviders(
		google.New(
			config.AppConfig.GoogleClientID,
			config.AppConfig.GoogleClientSecret,
			config.AppConfig.ClientCallbackURL+"/google/callback", // e.g. http://localhost:8080/v1/auth/google/callback
		),
		github.New(
			config.AppConfig.GithubClientID,
			config.AppConfig.GithubClientSecret,
			config.AppConfig.ClientCallbackURL+"/github/callback",
		),
	)
}

// displayCorsConfiguration - Startup'ta CORS ayarlarını göster
func displayCorsConfiguration(settingsService *services.SettingsService) {
	fmt.Println(utils.ColorCyan + "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" + utils.ColorReset)
	fmt.Println(utils.ColorCyan + "  CORS Configuration (Database-Driven)" + utils.ColorReset)
	fmt.Println(utils.ColorCyan + "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" + utils.ColorReset)

	// Get Whitelist
	whitelists, err := settingsService.GetAllCorsWhitelist()
	if err != nil {
		fmt.Println(utils.ColorRed + "  ❌ Failed to load whitelist: " + err.Error() + utils.ColorReset)
	} else {
		fmt.Println(utils.ColorGreen + "  ✅ WHITELIST (Allowed Origins):" + utils.ColorReset)
		if len(whitelists) == 0 {
			fmt.Println(utils.ColorYellow + "     ⚠️  No origins whitelisted! Add origins via API." + utils.ColorReset)
		} else {
			for i, w := range whitelists {
				status := utils.ColorGreen + "●" + utils.ColorReset
				if !w.IsActive {
					status = utils.ColorRed + "○" + utils.ColorReset
				}
				fmt.Printf("     %s %d. %s\n", status, i+1, w.Origin)
				if w.Description != "" {
					fmt.Printf("        └─ %s\n", utils.ColorCyan+w.Description+utils.ColorReset)
				}
			}
		}
	}

	fmt.Println()

	// Get Blacklist
	blacklists, err := settingsService.GetAllCorsBlacklist()
	if err != nil {
		fmt.Println(utils.ColorRed + "  ❌ Failed to load blacklist: " + err.Error() + utils.ColorReset)
	} else {
		fmt.Println(utils.ColorRed + "  🚫 BLACKLIST (Blocked Origins):" + utils.ColorReset)
		if len(blacklists) == 0 {
			fmt.Println(utils.ColorGreen + "     ✅ No origins blacklisted." + utils.ColorReset)
		} else {
			for i, b := range blacklists {
				status := utils.ColorRed + "●" + utils.ColorReset
				if !b.IsActive {
					status = utils.ColorYellow + "○" + utils.ColorReset
				}
				fmt.Printf("     %s %d. %s\n", status, i+1, b.Origin)
				if b.Reason != "" {
					fmt.Printf("        └─ Reason: %s\n", utils.ColorYellow+b.Reason+utils.ColorReset)
				}
			}
		}
	}

	fmt.Println()
	fmt.Println(utils.ColorCyan + "  Legend: " + utils.ColorGreen + "● Active" + utils.ColorReset + " | " + utils.ColorRed + "○ Inactive" + utils.ColorReset)
	fmt.Println(utils.ColorCyan + "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" + utils.ColorReset)
	fmt.Println()
}
