package router

import (
	"github.com/gin-gonic/gin"
	"github.com/prometheus/client_golang/prometheus/promhttp"
	swaggerFiles "github.com/swaggo/files"
	ginSwagger "github.com/swaggo/gin-swagger"

	"github.com/user-management-system/internal/api/handler"
	"github.com/user-management-system/internal/api/middleware"
	"github.com/user-management-system/internal/monitoring"
)

type Router struct {
	engine               *gin.Engine
	authHandler          *handler.AuthHandler
	userHandler          *handler.UserHandler
	roleHandler          *handler.RoleHandler
	permissionHandler    *handler.PermissionHandler
	deviceHandler        *handler.DeviceHandler
	logHandler           *handler.LogHandler
	passwordResetHandler *handler.PasswordResetHandler
	captchaHandler       *handler.CaptchaHandler
	totpHandler          *handler.TOTPHandler
	webhookHandler       *handler.WebhookHandler
	exportHandler        *handler.ExportHandler
	statsHandler         *handler.StatsHandler
	smsHandler           *handler.SMSHandler
	avatarHandler        *handler.AvatarHandler
	customFieldHandler   *handler.CustomFieldHandler
	themeHandler         *handler.ThemeHandler
	authMiddleware       *middleware.AuthMiddleware
	rateLimitMiddleware  *middleware.RateLimitMiddleware
	opLogMiddleware      *middleware.OperationLogMiddleware
	ipFilterMiddleware   *middleware.IPFilterMiddleware
	ssoHandler           *handler.SSOHandler
	settingsHandler      *handler.SettingsHandler
	metrics              *monitoring.Metrics // CRIT-01/02: Prometheus 指标
}

func NewRouter(
	authHandler *handler.AuthHandler,
	userHandler *handler.UserHandler,
	roleHandler *handler.RoleHandler,
	permissionHandler *handler.PermissionHandler,
	deviceHandler *handler.DeviceHandler,
	logHandler *handler.LogHandler,
	authMiddleware *middleware.AuthMiddleware,
	rateLimitMiddleware *middleware.RateLimitMiddleware,
	opLogMiddleware *middleware.OperationLogMiddleware,
	passwordResetHandler *handler.PasswordResetHandler,
	captchaHandler *handler.CaptchaHandler,
	totpHandler *handler.TOTPHandler,
	webhookHandler *handler.WebhookHandler,
	ipFilterMiddleware *middleware.IPFilterMiddleware,
	exportHandler *handler.ExportHandler,
	statsHandler *handler.StatsHandler,
	smsHandler *handler.SMSHandler,
	customFieldHandler *handler.CustomFieldHandler,
	themeHandler *handler.ThemeHandler,
	ssoHandler *handler.SSOHandler,
	settingsHandler *handler.SettingsHandler,
	metrics *monitoring.Metrics,
	avatarHandler ...*handler.AvatarHandler,
) *Router {
	engine := gin.New()
	var avatar *handler.AvatarHandler
	if len(avatarHandler) > 0 {
		avatar = avatarHandler[0]
	}

	return &Router{
		engine:               engine,
		authHandler:          authHandler,
		userHandler:          userHandler,
		roleHandler:          roleHandler,
		permissionHandler:    permissionHandler,
		deviceHandler:        deviceHandler,
		logHandler:           logHandler,
		passwordResetHandler: passwordResetHandler,
		captchaHandler:       captchaHandler,
		totpHandler:          totpHandler,
		webhookHandler:       webhookHandler,
		exportHandler:        exportHandler,
		statsHandler:         statsHandler,
		smsHandler:           smsHandler,
		customFieldHandler:   customFieldHandler,
		themeHandler:         themeHandler,
		ssoHandler:           ssoHandler,
		settingsHandler:      settingsHandler,
		avatarHandler:        avatar,
		authMiddleware:       authMiddleware,
		rateLimitMiddleware:  rateLimitMiddleware,
		opLogMiddleware:      opLogMiddleware,
		ipFilterMiddleware:   ipFilterMiddleware,
		metrics:              metrics,
	}
}

func (r *Router) Setup() *gin.Engine {
	r.engine.Use(middleware.Recover())
	r.engine.Use(middleware.TraceID()) // 可观察性补强：每个请求生成唯一 trace_id
	r.engine.Use(middleware.ErrorHandler())
	r.engine.Use(middleware.Logger())
	r.engine.Use(middleware.SecurityHeaders())
	r.engine.Use(middleware.NoStoreSensitiveResponses())
	r.engine.Use(middleware.CORS())
	// P1-1：GZIP 压缩 — 对 JSON/文本响应 > 1 KiB 自动压缩，列表接口带宽降低 50-70%
	r.engine.Use(middleware.GzipMiddleware())
	r.engine.Use(middleware.ResponseWrapper())

	// CRIT-01/02 修复：挂载 Prometheus 中间件，暴露 /metrics 端点
	// WARN-01 修复：/metrics 端点加内网 IP 限制，防止指标数据对外泄露
	if r.metrics != nil {
		r.engine.Use(monitoring.PrometheusMiddleware(r.metrics))
		r.engine.GET("/metrics",
			middleware.InternalOnly(),
			gin.WrapH(promhttp.HandlerFor(
				r.metrics.GetRegistry(),
				promhttp.HandlerOpts{EnableOpenMetrics: true},
			)),
		)
	}

	r.engine.Static("/uploads", "./uploads")
	r.engine.GET("/swagger/*any", ginSwagger.WrapHandler(swaggerFiles.Handler))

	if r.ipFilterMiddleware != nil {
		r.engine.Use(r.ipFilterMiddleware.Filter())
	}
	if r.opLogMiddleware != nil {
		r.engine.Use(r.opLogMiddleware.Record())
	}

	v1 := r.engine.Group("/api/v1")
	{
		authGroup := v1.Group("/auth")
		{
			authGroup.POST("/register", r.rateLimitMiddleware.Register(), r.authHandler.Register)
			authGroup.POST("/bootstrap-admin", r.rateLimitMiddleware.Register(), r.authHandler.BootstrapAdmin)
			authGroup.POST("/login", r.rateLimitMiddleware.Login(), r.authHandler.Login)
			authGroup.POST("/login/totp-verify", r.rateLimitMiddleware.Login(), r.authHandler.VerifyTOTPAfterPasswordLogin)
			authGroup.POST("/refresh", r.rateLimitMiddleware.Refresh(), r.authHandler.RefreshToken)
			authGroup.GET("/capabilities", r.authHandler.GetAuthCapabilities)
			authGroup.GET("/csrf-token", r.authHandler.GetCSRFToken)

			authGroup.POST("/activate-email", r.authHandler.ActivateEmail)
			authGroup.POST("/resend-activation", r.authHandler.ResendActivationEmail)

			if r.authHandler.SupportsEmailCodeLogin() {
				authGroup.POST("/send-email-code", r.rateLimitMiddleware.Register(), r.authHandler.SendEmailCode)
				authGroup.POST("/login/email-code", r.rateLimitMiddleware.Login(), r.authHandler.LoginByEmailCode)
			}

			if r.smsHandler != nil {
				authGroup.POST("/send-code", r.rateLimitMiddleware.Register(), r.smsHandler.SendCode)
				authGroup.POST("/login/code", r.rateLimitMiddleware.Login(), r.smsHandler.LoginByCode)
			}

			if r.passwordResetHandler != nil {
				authGroup.POST("/forgot-password", r.passwordResetHandler.ForgotPassword)
				authGroup.POST("/password/validate", r.passwordResetHandler.ValidateResetToken)
				authGroup.POST("/reset-password", r.passwordResetHandler.ResetPassword)
				// 短信密码重置
				authGroup.POST("/forgot-password/phone", r.passwordResetHandler.ForgotPasswordByPhone)
				authGroup.POST("/reset-password/phone", r.passwordResetHandler.ResetPasswordByPhone)
			}

			if r.captchaHandler != nil {
				authGroup.GET("/captcha", r.captchaHandler.GenerateCaptcha)
				authGroup.GET("/captcha/image", r.captchaHandler.GetCaptchaImage)
				authGroup.POST("/captcha/verify", r.captchaHandler.VerifyCaptcha)
			}

			authGroup.GET("/oauth/providers", r.authHandler.GetEnabledOAuthProviders)
			authGroup.GET("/oauth/:provider", r.authHandler.OAuthLogin)
			authGroup.GET("/oauth/:provider/callback", r.authHandler.OAuthCallback)
			authGroup.POST("/oauth/exchange", r.authHandler.OAuthExchange)
		}

		// 公开主题接口（无需认证）
		if r.themeHandler != nil {
			themePublic := v1.Group("")
			{
				themePublic.GET("/theme/active", r.themeHandler.GetActiveTheme)
			}
		}

		protected := v1.Group("")
		protected.Use(r.authMiddleware.Required())
		protected.Use(r.rateLimitMiddleware.API())
		{
			protected.POST("/auth/logout", r.authHandler.Logout)
			protected.GET("/auth/userinfo", r.authHandler.GetUserInfo)

			protected.POST("/users/me/bind-email/code", r.authHandler.SendEmailBindCode)
			protected.POST("/users/me/bind-email", r.authHandler.BindEmail)
			protected.DELETE("/users/me/bind-email", r.authHandler.UnbindEmail)
			protected.POST("/users/me/bind-phone/code", r.authHandler.SendPhoneBindCode)
			protected.POST("/users/me/bind-phone", r.authHandler.BindPhone)
			protected.DELETE("/users/me/bind-phone", r.authHandler.UnbindPhone)
			protected.GET("/users/me/social-accounts", r.authHandler.GetSocialAccounts)
			protected.POST("/users/me/bind-social", r.authHandler.BindSocialAccount)
			protected.DELETE("/users/me/bind-social/:provider", r.authHandler.UnbindSocialAccount)

			users := protected.Group("/users")
			{
				users.POST("", middleware.RequirePermission("user:manage"), r.userHandler.CreateUser)
				users.GET("", middleware.RequirePermission("user:manage"), r.userHandler.ListUsers)
				users.GET("/:id", middleware.RequirePermission("user:manage"), r.userHandler.GetUser)
				users.PUT("/:id", r.userHandler.UpdateUser)
				users.DELETE("/:id", middleware.RequirePermission("user:delete"), r.userHandler.DeleteUser)
				users.PUT("/:id/password", r.userHandler.UpdatePassword)
				users.PUT("/:id/status", middleware.RequirePermission("user:manage"), r.userHandler.UpdateUserStatus)
				users.GET("/:id/roles", r.userHandler.GetUserRoles)
				users.PUT("/:id/roles", middleware.RequirePermission("user:manage"), r.userHandler.AssignRoles)
				users.PUT("/batch/status", middleware.RequirePermission("user:manage"), r.userHandler.BatchUpdateStatus)
				users.DELETE("/batch", middleware.RequirePermission("user:delete"), r.userHandler.BatchDelete)

				if r.avatarHandler != nil {
					users.POST("/:id/avatar", r.avatarHandler.UploadAvatar)
				}
			}

			roles := protected.Group("/roles")
			roles.Use(middleware.AdminOnly())
			{
				roles.POST("", r.roleHandler.CreateRole)
				roles.GET("", r.roleHandler.ListRoles)
				roles.GET("/:id", r.roleHandler.GetRole)
				roles.PUT("/:id", r.roleHandler.UpdateRole)
				roles.DELETE("/:id", r.roleHandler.DeleteRole)
				roles.PUT("/:id/status", r.roleHandler.UpdateRoleStatus)
				roles.GET("/:id/permissions", r.roleHandler.GetRolePermissions)
				roles.PUT("/:id/permissions", r.roleHandler.AssignPermissions)
			}

			permissions := protected.Group("/permissions")
			permissions.Use(middleware.AdminOnly())
			{
				permissions.POST("", r.permissionHandler.CreatePermission)
				permissions.GET("", r.permissionHandler.ListPermissions)
				permissions.GET("/tree", r.permissionHandler.GetPermissionTree)
				permissions.GET("/:id", r.permissionHandler.GetPermission)
				permissions.PUT("/:id", r.permissionHandler.UpdatePermission)
				permissions.DELETE("/:id", r.permissionHandler.DeletePermission)
				permissions.PUT("/:id/status", r.permissionHandler.UpdatePermissionStatus)
			}

			devices := protected.Group("/devices")
			{
				devices.GET("", r.deviceHandler.GetMyDevices)
				devices.POST("", r.deviceHandler.CreateDevice)
				devices.GET("/:id", r.deviceHandler.GetDevice)
				devices.PUT("/:id", r.deviceHandler.UpdateDevice)
				devices.DELETE("/:id", r.deviceHandler.DeleteDevice)
				devices.PUT("/:id/status", r.deviceHandler.UpdateDeviceStatus)
				devices.POST("/:id/trust", r.deviceHandler.TrustDevice)
				devices.POST("/by-device-id/:deviceId/trust", r.deviceHandler.TrustDeviceByDeviceID)
				devices.DELETE("/:id/trust", r.deviceHandler.UntrustDevice)
				devices.GET("/me/trusted", r.deviceHandler.GetMyTrustedDevices)
				devices.POST("/me/logout-others", r.deviceHandler.LogoutAllOtherDevices)
				devices.GET("/users/:id", r.deviceHandler.GetUserDevices)
			}

			adminDevices := protected.Group("/admin/devices")
			adminDevices.Use(middleware.AdminOnly())
			{
				adminDevices.GET("", r.deviceHandler.GetAllDevices)
				adminDevices.DELETE("/:id", r.deviceHandler.DeleteDevice)
				adminDevices.PUT("/:id/status", r.deviceHandler.UpdateDeviceStatus)
				adminDevices.POST("/:id/trust", r.deviceHandler.TrustDevice)
				adminDevices.DELETE("/:id/trust", r.deviceHandler.UntrustDevice)
			}

			if r.logHandler != nil {
				logs := protected.Group("/logs")
				{
					logs.GET("/login/me", r.logHandler.GetMyLoginLogs)
					logs.GET("/operation/me", r.logHandler.GetMyOperationLogs)

					adminLogs := logs.Group("")
					adminLogs.Use(middleware.AdminOnly())
					{
						adminLogs.GET("/login", r.logHandler.GetLoginLogs)
						adminLogs.GET("/login/export", r.logHandler.ExportLoginLogs)
						adminLogs.GET("/operation", r.logHandler.GetOperationLogs)
					}
				}
			}

			if r.totpHandler != nil {
				twoFA := protected.Group("/auth/2fa")
				{
					twoFA.GET("/status", r.totpHandler.GetTOTPStatus)
					twoFA.GET("/setup", r.totpHandler.SetupTOTP)
					twoFA.POST("/enable", r.totpHandler.EnableTOTP)
					twoFA.POST("/disable", r.totpHandler.DisableTOTP)
					twoFA.POST("/verify", r.totpHandler.VerifyTOTP)
				}
			}

			if r.webhookHandler != nil {
				webhooks := protected.Group("/webhooks")
				{
					webhooks.POST("", r.webhookHandler.CreateWebhook)
					webhooks.GET("", r.webhookHandler.ListWebhooks)
					webhooks.PUT("/:id", r.webhookHandler.UpdateWebhook)
					webhooks.DELETE("/:id", r.webhookHandler.DeleteWebhook)
					webhooks.GET("/:id/deliveries", r.webhookHandler.GetWebhookDeliveries)
				}
			}

			if r.exportHandler != nil {
				adminUsers := protected.Group("/admin/users")
				adminUsers.Use(middleware.AdminOnly())
				{
					adminUsers.GET("/export", r.exportHandler.ExportUsers)
					adminUsers.POST("/import", r.exportHandler.ImportUsers)
					adminUsers.GET("/import/template", r.exportHandler.GetImportTemplate)
				}
			}

			adminMgmt := protected.Group("/admin/admins")
			adminMgmt.Use(middleware.AdminOnly())
			{
				adminMgmt.GET("", r.userHandler.ListAdmins)
				adminMgmt.POST("", r.userHandler.CreateAdmin)
				adminMgmt.DELETE("/:id", r.userHandler.DeleteAdmin)
			}

			if r.statsHandler != nil {
				adminStats := protected.Group("/admin/stats")
				adminStats.Use(middleware.AdminOnly())
				{
					adminStats.GET("/dashboard", r.statsHandler.GetDashboard)
					adminStats.GET("/users", r.statsHandler.GetUserStats)
				}
			}

			if r.settingsHandler != nil {
				adminSettings := protected.Group("/admin/settings")
				adminSettings.Use(middleware.AdminOnly())
				{
					adminSettings.GET("", r.settingsHandler.GetSettings)
				}
			}

			if r.customFieldHandler != nil {
				// 自定义字段管理（管理员）
				customFields := protected.Group("/custom-fields")
				customFields.Use(middleware.AdminOnly())
				{
					customFields.POST("", r.customFieldHandler.CreateField)
					customFields.GET("", r.customFieldHandler.ListFields)
					customFields.GET("/:id", r.customFieldHandler.GetField)
					customFields.PUT("/:id", r.customFieldHandler.UpdateField)
					customFields.DELETE("/:id", r.customFieldHandler.DeleteField)
				}

				// 用户自定义字段值（用户自己的）
				userFields := protected.Group("/users/me/custom-fields")
				{
					userFields.GET("", r.customFieldHandler.GetUserFieldValues)
					userFields.PUT("", r.customFieldHandler.SetUserFieldValues)
				}
			}

			if r.themeHandler != nil {
				// 主题管理（管理员）
				themes := protected.Group("/themes")
				themes.Use(middleware.AdminOnly())
				{
					themes.POST("", r.themeHandler.CreateTheme)
					themes.GET("", r.themeHandler.ListAllThemes)
					themes.GET("/default", r.themeHandler.GetDefaultTheme)
					themes.PUT("/default/:id", r.themeHandler.SetDefaultTheme)
					themes.GET("/:id", r.themeHandler.GetTheme)
					themes.PUT("/:id", r.themeHandler.UpdateTheme)
					themes.DELETE("/:id", r.themeHandler.DeleteTheme)
				}
			}

			// SSO 单点登录接口（需要认证）
			if r.ssoHandler != nil {
				sso := protected.Group("/sso")
				{
					sso.GET("/authorize", r.ssoHandler.Authorize)
					sso.POST("/token", r.ssoHandler.Token)
					sso.POST("/introspect", r.ssoHandler.Introspect)
					sso.POST("/revoke", r.ssoHandler.Revoke)
					sso.GET("/userinfo", r.ssoHandler.UserInfo)
				}
			}
		}
	}

	return r.engine
}

func (r *Router) GetEngine() *gin.Engine {
	return r.engine
}
