// @title OCDP Backend API
// @version 1.0
// @description OCDP (Open Cloud Development Platform) Backend API
// @description
// @description RESTful API for managing Kubernetes clusters, OCI registries, and Helm deployments.
//
// @contact.name API Support
// @contact.email support@ocdp.io
//
// @license.name Apache 2.0
// @license.url http://www.apache.org/licenses/LICENSE-2.0.html
//
// @host localhost:8080
// @BasePath /api/v1
//
// @schemes http https
//
// @securityDefinitions.apikey BearerAuth
// @in header
// @name Authorization
// @description Type "Bearer" followed by a space and JWT token.
package main

import (
	"context"
	"fmt"
	"log"
	"net/http"
	"os"
	"strings"
	"time"

	"github.com/gorilla/mux"

	"github.com/ocdp/cluster-service/internal/adapter/input/http/rest"
	"github.com/ocdp/cluster-service/internal/adapter/output"
	"github.com/ocdp/cluster-service/internal/adapter/output/k8s"
	"github.com/ocdp/cluster-service/internal/bootstrap"
	"github.com/ocdp/cluster-service/internal/domain/service"
	"github.com/ocdp/cluster-service/internal/pkg/authz"
	"github.com/ocdp/cluster-service/internal/pkg/crypto"
	"github.com/ocdp/cluster-service/internal/pkg/jwt"
	"github.com/ocdp/cluster-service/internal/pkg/password"
)

func main() {
	log.Println("🚀 Starting OCDP Backend (Hexagonal Architecture)")

	// ===== 1. 读取配置 =====
	config := loadConfig()
	log.Printf("📝 Configuration: mode=%s, port=%s", config.AdapterMode, config.Port)

	// ===== 2. 创建加密器（用于敏感数据加密存储） =====
	encryptor := crypto.NewAESEncryptor(config.EncryptionKey)
	log.Println("✅ Encryption enabled for sensitive data")

	// ===== 3. 创建 Output Adapters（通过工厂） =====
	factory := output.NewAdapterFactory(
		output.AdapterMode(config.AdapterMode),
		encryptor,
		config.DatabaseURL,
	)

	repos, err := factory.CreateAllRepositories()
	if err != nil {
		log.Fatalf("❌ Failed to create adapters: %v", err)
	}
	log.Printf("✅ Output Adapters initialized (mode: %s)", config.AdapterMode)

	// ===== 4. 创建工具包实例 =====
	passwordHasher := password.NewHasher()
	tokenGenerator := jwt.NewJWTManager(config.JWTSecret)
	log.Println("✅ Utilities initialized")

	// ===== 5. 创建 Domain Services =====
	authService := service.NewAuthService(
		repos.UserRepo,
		repos.WorkspaceRepo,
		passwordHasher,
		tokenGenerator,
	)
	authService.SetUserLifecycleCleanup(
		repos.InstanceRepo,
		repos.ClusterRepo,
		repos.BindingRepo,
		repos.TenantKubeClient,
	)

	clusterService := service.NewClusterService(
		repos.ClusterRepo,
	)

	registryService := service.NewRegistryService(
		repos.RegistryRepo,
		repos.OCIClient,
	)

	artifactService := service.NewArtifactService(
		repos.RegistryRepo,
		repos.OCIClient,
	)

	instanceService := service.NewInstanceService(
		repos.InstanceRepo,
		repos.ClusterRepo,
		repos.RegistryRepo,
		repos.HelmClient,
		repos.OCIClient,
		repos.EntryClient,
		repos.BindingRepo,
	)
	instanceService.SetDiagnosticsClient(repos.DiagnosticsClient)
	instanceService.SetTenantProvisioning(repos.WorkspaceRepo, repos.TenantKubeClient)
	instanceService.SetScaleClient(k8s.NewScaleClient())
	instanceService.SetUserRepository(repos.UserRepo)

	monitoringService := service.NewMonitoringService(
		repos.ClusterRepo,
		repos.MetricsClient,
		repos.InstanceRepo,
		repos.UserRepo,
	)

	workspaceService := service.NewWorkspaceService(
		repos.WorkspaceRepo,
		repos.BindingRepo,
		repos.ClusterRepo,
		repos.TenantKubeClient,
		repos.AuditRepo,
	)

	log.Println("✅ Domain Services initialized")

	// ===== 6. 加载并执行 Bootstrap 预注入 =====
	bootstrapConfig, err := bootstrap.LoadBootstrapConfig()
	if err != nil {
		log.Printf("⚠️  Warning: Failed to load bootstrap config: %v", err)
		// 使用安全的空配置，避免在配置错误时写入任何预置账号或集群凭据。
		bootstrapConfig = bootstrap.GetDefaultBootstrapConfig()
	}

	seeder := bootstrap.NewSeeder(repos, passwordHasher, bootstrapConfig)
	if err := seeder.SeedAll(context.Background()); err != nil {
		log.Printf("⚠️  Warning: Failed to seed data: %v", err)
	}

	// ===== 7. 创建 Input Adapters (REST Handlers) =====
	authHandler := rest.NewAuthHandler(authService)
	clusterHandler := rest.NewClusterHandler(clusterService)
	registryHandler := rest.NewRegistryHandler(registryService)
	artifactHandler := rest.NewArtifactHandler(artifactService)
	instanceHandler := rest.NewInstanceHandler(instanceService)
	monitoringHandler := rest.NewMonitoringHandler(monitoringService)
	workspaceHandler := rest.NewWorkspaceHandler(workspaceService)
	swaggerHandler := rest.NewSwaggerHandler()

	log.Println("✅ Input Adapters (REST handlers) initialized")

	// ===== 8. 设置路由 =====
	router := setupRouter(
		authHandler,
		authService,
		clusterHandler,
		registryHandler,
		artifactHandler,
		instanceHandler,
		monitoringHandler,
		workspaceHandler,
		swaggerHandler,
	)

	// ===== 9. 启动服务器 =====
	addr := fmt.Sprintf(":%s", config.Port)
	log.Printf("🌐 Server starting on %s", addr)
	log.Println("")
	log.Println("📍 Available endpoints:")
	log.Printf("   - REST API:     http://localhost:%s/api/v1", config.Port)
	log.Printf("   - Swagger UI:   http://localhost:%s/api/docs", config.Port)
	log.Printf("   - OpenAPI Spec: http://localhost:%s/api/docs/openapi.yaml", config.Port)
	log.Printf("   - Health:       http://localhost:%s/health", config.Port)
	log.Println("")
	log.Println("✨ Press Ctrl+C to stop")
	log.Println("")

	if err := http.ListenAndServe(addr, router); err != nil {
		log.Fatalf("❌ Server failed: %v", err)
	}
}

// Config 应用配置
type Config struct {
	AdapterMode   string
	Port          string
	JWTSecret     string
	EncryptionKey string
	DatabaseURL   string
}

// loadConfig 加载配置
func loadConfig() *Config {
	return &Config{
		AdapterMode:   getEnv("ADAPTER_MODE", ""), // 默认为空字符串（真实模式）
		Port:          getEnv("PORT", "8080"),
		JWTSecret:     getEnv("JWT_SECRET", "your-secret-key-change-in-production"),
		EncryptionKey: getEnv("ENCRYPTION_KEY", "default-encryption-key-change-in-production"),
		DatabaseURL:   getEnv("DATABASE_URL", ""),
	}
}

// getEnv 获取环境变量，如果不存在则返回默认值
func getEnv(key, defaultValue string) string {
	value := os.Getenv(key)
	if value == "" {
		return defaultValue
	}
	return value
}

// setupRouter 设置路由
func setupRouter(
	authHandler *rest.AuthHandler,
	authService *service.AuthService,
	clusterHandler *rest.ClusterHandler,
	registryHandler *rest.RegistryHandler,
	artifactHandler *rest.ArtifactHandler,
	instanceHandler *rest.InstanceHandler,
	monitoringHandler *rest.MonitoringHandler,
	workspaceHandler *rest.WorkspaceHandler,
	swaggerHandler *rest.SwaggerHandler,
) *mux.Router {
	router := mux.NewRouter().StrictSlash(true)

	// 全局中间件
	router.Use(loggingMiddleware)
	router.Use(corsMiddleware)

	// 健康检查
	router.HandleFunc("/health", func(w http.ResponseWriter, r *http.Request) {
		w.Header().Set("Content-Type", "application/json")
		w.WriteHeader(http.StatusOK)
		w.Write([]byte(`{"status":"healthy"}`))
	})

	// ===== Swagger UI =====
	router.HandleFunc("/api/docs", swaggerHandler.ServeSwaggerUI).Methods(http.MethodGet)
	router.HandleFunc("/api/docs/assets/swagger-ui.css", swaggerHandler.ServeSwaggerCSS).Methods(http.MethodGet)
	router.HandleFunc("/api/docs/assets/swagger-ui-bundle.js", swaggerHandler.ServeSwaggerBundle).Methods(http.MethodGet)
	router.HandleFunc("/api/docs/assets/swagger-ui-standalone-preset.js", swaggerHandler.ServeSwaggerStandalonePreset).Methods(http.MethodGet)
	router.HandleFunc("/api/docs/openapi.yaml", swaggerHandler.ServeOpenAPISpec).Methods(http.MethodGet)

	// API v1
	api := router.PathPrefix("/api/v1").Subrouter()

	// ===== 认证路由 =====
	api.HandleFunc("/auth/login", authHandler.Login).Methods(http.MethodPost)
	api.HandleFunc("/auth/refresh", authHandler.RefreshToken).Methods(http.MethodPost)
	api.HandleFunc("/auth/status", authHandler.AuthStatus).Methods(http.MethodGet)
	api.HandleFunc("/auth/setup", authHandler.Setup).Methods(http.MethodPost)

	protected := api.PathPrefix("").Subrouter()
	protected.Use(authMiddleware(authService))
	protected.HandleFunc("/auth/me", authHandler.Me).Methods(http.MethodGet)
	protected.HandleFunc("/auth/register", authHandler.Register).Methods(http.MethodPost)
	protected.HandleFunc("/users", authHandler.ListUsers).Methods(http.MethodGet)
	protected.HandleFunc("/users", authHandler.Register).Methods(http.MethodPost)
	protected.HandleFunc("/users/{user_id}", authHandler.UpdateUser).Methods(http.MethodPut)
	protected.HandleFunc("/users/{user_id}", authHandler.DeleteUser).Methods(http.MethodDelete)

	// ===== 集群路由 =====
	protected.HandleFunc("/clusters", clusterHandler.CreateCluster).Methods(http.MethodPost)
	protected.HandleFunc("/clusters", clusterHandler.GetAllClusters).Methods(http.MethodGet)
	protected.HandleFunc("/clusters/{cluster_id}", clusterHandler.GetCluster).Methods(http.MethodGet)
	protected.HandleFunc("/clusters/{cluster_id}", clusterHandler.UpdateCluster).Methods(http.MethodPut)
	protected.HandleFunc("/clusters/{cluster_id}", clusterHandler.DeleteCluster).Methods(http.MethodDelete)
	protected.HandleFunc("/clusters/{cluster_id}/health", clusterHandler.GetClusterHealth).Methods(http.MethodGet)
	protected.HandleFunc("/clusters/{cluster_id}/stats", monitoringHandler.GetClusterStats).Methods(http.MethodGet)
	protected.HandleFunc("/clusters/{cluster_id}/kubeconfig", workspaceHandler.IssueClusterKubeconfig).Methods(http.MethodGet)

	// ===== Registry 路由 =====
	protected.HandleFunc("/registries", registryHandler.CreateRegistry).Methods(http.MethodPost)
	protected.HandleFunc("/registries", registryHandler.GetAllRegistries).Methods(http.MethodGet)
	protected.HandleFunc("/registries/{registry_id}", registryHandler.GetRegistry).Methods(http.MethodGet)
	protected.HandleFunc("/registries/{registry_id}", registryHandler.UpdateRegistry).Methods(http.MethodPut)
	protected.HandleFunc("/registries/{registry_id}", registryHandler.DeleteRegistry).Methods(http.MethodDelete)
	protected.HandleFunc("/registries/{registry_id}/health", registryHandler.GetRegistryHealth).Methods(http.MethodGet)

	// ===== Artifact 路由 =====
	protected.HandleFunc("/registries/{registry_id}/repositories", artifactHandler.ListRepositories).Methods(http.MethodGet)
	protected.HandleFunc("/repositories/{repository_name:.+}/tags", artifactHandler.ListRepositoryTags).Methods(http.MethodGet)
	protected.HandleFunc("/registries/{registry_id}/repositories/{repository_name:.+}/artifacts", artifactHandler.ListArtifacts).Methods(http.MethodGet)
	protected.HandleFunc("/registries/{registry_id}/repositories/{repository_name:.+}/tags", artifactHandler.ListRepositoryTags).Methods(http.MethodGet)
	protected.HandleFunc("/registries/{registry_id}/repositories/{repository_name:.+}/artifacts/{reference}", artifactHandler.GetArtifact).Methods(http.MethodGet)
	protected.HandleFunc("/registries/{registry_id}/repositories/{repository_name:.+}/artifacts/{reference}/values-schema", artifactHandler.GetArtifactValuesSchema).Methods(http.MethodGet)
	protected.HandleFunc("/registries/{registry_id}/repositories/{repository_name:.+}/artifacts/{reference}/values-yaml", artifactHandler.GetArtifactValuesYAML).Methods(http.MethodGet)

	// ===== Instance 路由 =====
	protected.HandleFunc("/clusters/{cluster_id}/instances", instanceHandler.CreateInstance).Methods(http.MethodPost)
	protected.HandleFunc("/clusters/{cluster_id}/instances", instanceHandler.ListInstances).Methods(http.MethodGet)
	protected.HandleFunc("/clusters/{cluster_id}/instances/{instance_id}", instanceHandler.GetInstance).Methods(http.MethodGet)
	protected.HandleFunc("/clusters/{cluster_id}/instances/{instance_id}", instanceHandler.UpdateInstance).Methods(http.MethodPut)
	protected.HandleFunc("/clusters/{cluster_id}/instances/{instance_id}", instanceHandler.DeleteInstance).Methods(http.MethodDelete)
	protected.HandleFunc("/clusters/{cluster_id}/instances/{instance_id}/entries", instanceHandler.ListInstanceEntries).Methods(http.MethodGet)
	protected.HandleFunc("/clusters/{cluster_id}/instances/{instance_id}/diagnostics", instanceHandler.GetInstanceDiagnostics).Methods(http.MethodGet)
	protected.HandleFunc("/clusters/{cluster_id}/instances/{instance_id}/logs/stream", instanceHandler.StreamInstanceLogs).Methods(http.MethodGet)
	protected.HandleFunc("/clusters/{cluster_id}/instances/{instance_id}/scale", instanceHandler.ScaleInstance).Methods(http.MethodPost)
	protected.HandleFunc("/clusters/{cluster_id}/instances/{instance_id}/values-diff", instanceHandler.GetInstanceValuesDiff).Methods(http.MethodGet)

	// ===== Monitoring 路由 =====
	protected.HandleFunc("/monitoring/clusters", monitoringHandler.ListClusterMonitoring).Methods(http.MethodGet)
	protected.HandleFunc("/monitoring/clusters/{cluster_id}", monitoringHandler.GetClusterMonitoring).Methods(http.MethodGet)
	protected.HandleFunc("/monitoring/clusters/{cluster_id}/metrics", monitoringHandler.GetClusterMonitoring).Methods(http.MethodGet)
	protected.HandleFunc("/monitoring/clusters/{cluster_id}/nodes", monitoringHandler.GetNodeMetrics).Methods(http.MethodGet)
	protected.HandleFunc("/monitoring/summary", monitoringHandler.GetMonitoringSummary).Methods(http.MethodGet)

	// ===== Workspace 路由 =====
	protected.HandleFunc("/workspaces", workspaceHandler.ListWorkspaces).Methods(http.MethodGet)
	protected.HandleFunc("/workspaces", workspaceHandler.CreateWorkspace).Methods(http.MethodPost)
	protected.HandleFunc("/workspaces/credentials/kubeconfig", workspaceHandler.IssueCurrentKubeconfig).Methods(http.MethodGet)
	protected.HandleFunc("/workspaces/{workspace_id}/clusters", workspaceHandler.InitClusterBinding).Methods(http.MethodPost)
	protected.HandleFunc("/workspaces/{workspace_id}/kubeconfig", workspaceHandler.IssueKubeconfig).Methods(http.MethodPost)
	protected.HandleFunc("/workspaces/{workspace_id}/suspend", workspaceHandler.SuspendWorkspace).Methods(http.MethodPost)

	// 处理 MethodNotAllowed 错误（OPTIONS 请求会触发）
	router.MethodNotAllowedHandler = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		if r.Method == http.MethodOptions {
			// CORS 预检已在中间件处理，这里直接返回
			w.WriteHeader(http.StatusNoContent)
			return
		}
		http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
	})

	return router
}

func authMiddleware(authService *service.AuthService) mux.MiddlewareFunc {
	return func(next http.Handler) http.Handler {
		return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
			header := r.Header.Get("Authorization")
			if !strings.HasPrefix(header, "Bearer ") {
				writeJSONError(w, http.StatusUnauthorized, "Unauthorized", "missing bearer token")
				return
			}
			token := strings.TrimSpace(strings.TrimPrefix(header, "Bearer "))
			if token == "" {
				writeJSONError(w, http.StatusUnauthorized, "Unauthorized", "missing bearer token")
				return
			}
			principal, err := authService.VerifyAccessToken(r.Context(), token)
			if err != nil {
				writeJSONError(w, http.StatusUnauthorized, "Unauthorized", err.Error())
				return
			}
			next.ServeHTTP(w, r.WithContext(authz.WithPrincipal(r.Context(), principal)))
		})
	}
}

func writeJSONError(w http.ResponseWriter, status int, code, message string) {
	w.Header().Set("Content-Type", "application/json")
	w.WriteHeader(status)
	_, _ = w.Write([]byte(fmt.Sprintf(`{"error":%q,"message":%q}`, code, message)))
}

// loggingMiddleware 日志中间件
func loggingMiddleware(next http.Handler) http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		start := time.Now()
		next.ServeHTTP(w, r)
		log.Printf("%s %s %s %v", r.Method, r.RequestURI, r.RemoteAddr, time.Since(start))
	})
}

// corsMiddleware CORS 中间件
func corsMiddleware(next http.Handler) http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		origin := r.Header.Get("Origin")
		if origin != "" {
			w.Header().Add("Vary", "Origin")
			if corsOriginAllowed(origin) {
				w.Header().Set("Access-Control-Allow-Origin", origin)
				w.Header().Set("Access-Control-Allow-Credentials", "true")
			}
		}
		w.Header().Set("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS")
		w.Header().Set("Access-Control-Allow-Headers", "Content-Type, Authorization, X-Requested-With")
		w.Header().Set("Access-Control-Max-Age", "86400")

		// 处理 OPTIONS 预检请求
		if r.Method == http.MethodOptions {
			w.WriteHeader(http.StatusNoContent)
			return
		}

		next.ServeHTTP(w, r)
	})
}

func corsOriginAllowed(origin string) bool {
	origin = strings.TrimSpace(origin)
	if origin == "" {
		return false
	}
	for _, allowed := range corsAllowedOrigins() {
		if origin == allowed {
			return true
		}
	}
	return false
}

func corsAllowedOrigins() []string {
	configured := strings.TrimSpace(os.Getenv("CORS_ALLOWED_ORIGINS"))
	if configured == "" {
		configured = strings.TrimSpace(os.Getenv("ALLOWED_ORIGINS"))
	}
	if configured == "" {
		return []string{
			"http://localhost:3000",
			"http://localhost:5173",
			"http://localhost:8080",
			"http://localhost:18080",
			"http://localhost:18081",
			"http://127.0.0.1:3000",
			"http://127.0.0.1:5173",
			"http://127.0.0.1:8080",
			"http://127.0.0.1:18080",
			"http://127.0.0.1:18081",
			"http://10.6.80.114:18080",
		}
	}
	origins := make([]string, 0)
	for _, origin := range strings.Split(configured, ",") {
		origin = strings.TrimSpace(origin)
		if origin == "" || origin == "*" {
			continue
		}
		origins = append(origins, origin)
	}
	return origins
}
