package routes

import (
	"net/http"
	"time"

	"service/internal/infrastructure/cache"
	"service/internal/infrastructure/config"
	"service/internal/infrastructure/transport/http/middleware"

	antrolHttp "service/internal/infrastructure/transport/http/handlers/bpjs/antrol"
	aplicareHttp "service/internal/infrastructure/transport/http/handlers/bpjs/aplicare"
	apotekHttp "service/internal/infrastructure/transport/http/handlers/bpjs/apotek"
	vclaimHttp "service/internal/infrastructure/transport/http/handlers/bpjs/vclaim"
	authHttp "service/internal/infrastructure/transport/http/handlers/main/auth"
	healthHttp "service/internal/infrastructure/transport/http/handlers/main/health"
	roleHttp "service/internal/infrastructure/transport/http/handlers/main/master/roles"
	satuSehatRefHttp "service/internal/infrastructure/transport/http/handlers/satusehat/reference"
	satuSehatUsecaseHttp "service/internal/infrastructure/transport/http/handlers/satusehat/usecase"

	"github.com/gin-gonic/gin"
	swaggerFiles "github.com/swaggo/files"
	ginSwagger "github.com/swaggo/gin-swagger"
)

// ModuleHandlers menampung seluruh HTTP handler opsional dari berbagai modul.
// Jika sebuah handler bernilai nil, maka rutenya akan otomatis diabaikan (disabled).
type ModuleHandlers struct {
	Auth                    *authHttp.AuthHandler
	RolePages               *roleHttp.RolPagesHandler
	RolePermission          *roleHttp.RolPermissionHandler
	RoleMaster              *roleHttp.RoleMasterHandler
	Sep                     *vclaimHttp.SepHandler
	Peserta                 *vclaimHttp.PesertaHandler
	Antrol                  *antrolHttp.AntrolHandler
	AplicareBed             *aplicareHttp.BedHandler
	ApotekReference         *apotekHttp.ReferenceHandler
	SatuSehatAuth           *satuSehatRefHttp.AuthHandler
	SatuSehatPatient        *satuSehatRefHttp.PatientHandler
	SatuSehatPractitioner   *satuSehatRefHttp.PractitionerHandler
	SatuSehatOrganization   *satuSehatRefHttp.OrganizationHandler
	SatuSehatLocation       *satuSehatRefHttp.LocationHandler
	SatuSehatKFA            *satuSehatRefHttp.KFAHandler
	SSAllergyIntolerance    *satuSehatUsecaseHttp.AllergyIntoleranceHandler
	SSCarePlan              *satuSehatUsecaseHttp.CarePlanHandler
	SSClinicalImpression    *satuSehatUsecaseHttp.ClinicalImpressionHandler
	SSComposition           *satuSehatUsecaseHttp.CompositionHandler
	SSCondition             *satuSehatUsecaseHttp.ConditionHandler
	SSDiagnosticReport      *satuSehatUsecaseHttp.DiagnosticReportHandler
	SSEncounter             *satuSehatUsecaseHttp.EncounterHandler
	SSEpisodeOfCare         *satuSehatUsecaseHttp.EpisodeOfCareHandler
	SSImagingStudy          *satuSehatUsecaseHttp.ImagingStudyHandler
	SSImmunization          *satuSehatUsecaseHttp.ImmunizationHandler
	SSMedication            *satuSehatUsecaseHttp.MedicationHandler
	SSMedicationDispense    *satuSehatUsecaseHttp.MedicationDispenseHandler
	SSMedicationRequest     *satuSehatUsecaseHttp.MedicationRequestHandler
	SSMedicationStatement   *satuSehatUsecaseHttp.MedicationStatementHandler
	SSObservation           *satuSehatUsecaseHttp.ObservationHandler
	SSProcedure             *satuSehatUsecaseHttp.ProcedureHandler
	SSQuestionnaireResponse *satuSehatUsecaseHttp.QuestionnaireResponseHandler
	SSServiceRequest        *satuSehatUsecaseHttp.ServiceRequestHandler
	SSSpecimen              *satuSehatUsecaseHttp.SpecimenHandler
}

// SetupRoutes mendaftarkan seluruh endpoint API secara dinamis berdasarkan
// modul-modul yang aktif (tidak nil) pada aplikasi.
func SetupRoutes(
	engine *gin.Engine,
	cfg *config.Config,
	cacheManager *cache.Manager,
	healthHandler *healthHttp.HealthHandler,
	h *ModuleHandlers,
) {
	// Handle 405 Method Not Allowed for better client feedback
	engine.HandleMethodNotAllowed = true

	// Health check endpoints - using consistent http.Status constants
	engine.GET("/health", func(c *gin.Context) {
		c.JSON(http.StatusOK, gin.H{
			"status":    "healthy",
			"timestamp": time.Now().UTC(),
			"service":   "service-general",
			"version":   "1.0.0",
		})
	})

	// Comprehensive health check with dependencies
	engine.GET("/health/complete", healthHandler.HealthCheckComplete)

	// Database health check
	engine.GET("/health/database", healthHandler.HealthCheckDatabase)

	// Redis/cache health check
	engine.GET("/health/cache", healthHandler.HealthCheckCache)

	// External services health check
	engine.GET("/health/external", healthHandler.HealthCheckExternal)

	// Minio service
	engine.GET("/health/minio", healthHandler.HealthCheckMinio)
	engine.POST("/health/minio/upload", healthHandler.TestUploadMinio)

	// All databases health check
	// engine.GET("/health/databases", healthHandler.HealthCheckAllDatabases)

	// Readiness check
	engine.GET("/ready", func(c *gin.Context) {
		c.JSON(http.StatusOK, gin.H{
			"status":    "ready",
			"timestamp": time.Now().UTC(),
		})
	})

	// Liveness check
	engine.GET("/live", func(c *gin.Context) {
		c.JSON(http.StatusOK, gin.H{
			"status":    "alive",
			"timestamp": time.Now().UTC(),
		})
	})

	// Redirect otomatis dari /swagger ke /swagger/index.html
	engine.GET("/swagger", func(c *gin.Context) {
		c.Redirect(http.StatusFound, "/swagger/index.html")
	})

	// Endpoint untuk Swagger UI
	engine.GET("/swagger/*any", ginSwagger.WrapHandler(swaggerFiles.Handler))

	// API v1 routes
	v1 := engine.Group("/api/v1")
	{
		// Register auth routes (Public)
		if h.Auth != nil {
			h.Auth.RegisterRoutes(v1)
		}

		// Private routes (Membutuhkan Autentikasi)
		protected := v1.Group("")
		protected.Use(middleware.AuthMiddleware(cfg, cacheManager))
		{
			if h.Auth != nil {
				h.Auth.RegisterProtectedRoutes(protected)
			}

			// --- Routes Modul Master ---
			if h.RolePages != nil {
				h.RolePages.RegisterRoutes(protected)
			}
			if h.RolePermission != nil {
				h.RolePermission.RegisterRoutes(protected)
			}
			if h.RoleMaster != nil {
				h.RoleMaster.RegisterRoutes(protected)
			}

			// --- Routes Modul BPJS VClaim ---
			if h.Sep != nil {
				h.Sep.RegisterRoutes(protected)
			}
			if h.Peserta != nil {
				h.Peserta.RegisterRoutes(protected)
			}

			// --- Routes Modul BPJS Antrol ---
			if h.Antrol != nil {
				h.Antrol.RegisterRoutes(protected)
			}

			// --- Routes Modul BPJS Aplicares ---
			if h.AplicareBed != nil {
				h.AplicareBed.RegisterRoutes(protected)
			}

			// --- Routes Modul BPJS Apotek ---
			if h.ApotekReference != nil {
				h.ApotekReference.RegisterRoutes(protected)
			}

			// --- Routes Modul Satu Sehat ---
			// Buat grup khusus untuk membatasi traffic hit API ke Kemenkes
			satuSehatGroup := protected.Group("")
			satuSehatGroup.Use(middleware.MemoryRateLimitMiddleware(5.0, 10)) // Max 5 RPS, Burst capacity 10
			{
				if h.SatuSehatAuth != nil {
					h.SatuSehatAuth.RegisterRoutes(satuSehatGroup)
				}
				if h.SatuSehatPatient != nil {
					h.SatuSehatPatient.RegisterRoutes(satuSehatGroup)
				}
				if h.SatuSehatPractitioner != nil {
					h.SatuSehatPractitioner.RegisterRoutes(satuSehatGroup)
				}
				if h.SatuSehatOrganization != nil {
					h.SatuSehatOrganization.RegisterRoutes(satuSehatGroup)
				}
				if h.SatuSehatLocation != nil {
					h.SatuSehatLocation.RegisterRoutes(satuSehatGroup)
				}
				if h.SatuSehatKFA != nil {
					h.SatuSehatKFA.RegisterRoutes(satuSehatGroup)
				}
				if h.SSAllergyIntolerance != nil {
					h.SSAllergyIntolerance.RegisterRoutes(satuSehatGroup)
				}
				if h.SSCarePlan != nil {
					h.SSCarePlan.RegisterRoutes(satuSehatGroup)
				}
				if h.SSClinicalImpression != nil {
					h.SSClinicalImpression.RegisterRoutes(satuSehatGroup)
				}
				if h.SSComposition != nil {
					h.SSComposition.RegisterRoutes(satuSehatGroup)
				}
				if h.SSCondition != nil {
					h.SSCondition.RegisterRoutes(satuSehatGroup)
				}
				if h.SSDiagnosticReport != nil {
					h.SSDiagnosticReport.RegisterRoutes(satuSehatGroup)
				}
				if h.SSEncounter != nil {
					h.SSEncounter.RegisterRoutes(satuSehatGroup)
				}
				if h.SSEpisodeOfCare != nil {
					h.SSEpisodeOfCare.RegisterRoutes(satuSehatGroup)
				}
				if h.SSImagingStudy != nil {
					h.SSImagingStudy.RegisterRoutes(satuSehatGroup)
				}
				if h.SSImmunization != nil {
					h.SSImmunization.RegisterRoutes(satuSehatGroup)
				}
				if h.SSMedication != nil {
					h.SSMedication.RegisterRoutes(satuSehatGroup)
				}
				if h.SSMedicationDispense != nil {
					h.SSMedicationDispense.RegisterRoutes(satuSehatGroup)
				}
				if h.SSMedicationRequest != nil {
					h.SSMedicationRequest.RegisterRoutes(satuSehatGroup)
				}
				if h.SSMedicationStatement != nil {
					h.SSMedicationStatement.RegisterRoutes(satuSehatGroup)
				}
				if h.SSObservation != nil {
					h.SSObservation.RegisterRoutes(satuSehatGroup)
				}
				if h.SSProcedure != nil {
					h.SSProcedure.RegisterRoutes(satuSehatGroup)
				}
				if h.SSQuestionnaireResponse != nil {
					h.SSQuestionnaireResponse.RegisterRoutes(satuSehatGroup)
				}
				if h.SSServiceRequest != nil {
					h.SSServiceRequest.RegisterRoutes(satuSehatGroup)
				}
				if h.SSSpecimen != nil {
					h.SSSpecimen.RegisterRoutes(satuSehatGroup)
				}
			}
		}
	}
}
