package alert

import (
	"sync"

	"github.com/gin-gonic/gin"

	"github.com/pingcap-inc/clinic_cloud_server/pkg/alert/notification"
	"github.com/pingcap-inc/clinic_cloud_server/pkg/alert/repo"
	"github.com/pingcap-inc/clinic_cloud_server/pkg/client/account"
	"github.com/pingcap-inc/clinic_cloud_server/pkg/client/billing"
	"github.com/pingcap-inc/clinic_cloud_server/pkg/client/core_svc"
	"github.com/pingcap-inc/clinic_cloud_server/pkg/client/mgmt_svc"
	"github.com/pingcap-inc/clinic_cloud_server/pkg/config"
)

type Service struct {
	cfg                   *config.Config
	accountClient         *account.Client
	billingClient         *billing.Client
	coreSvcClient         *core_svc.Client
	mgmtSvcClient         *mgmt_svc.Client
	notificationClient    notification.Interface
	alertSubscriberRepo   *repo.AlertSubscriberRepo
	alertNotificationRepo *repo.AlertNotificationRepo
	alertQuotaRepo        *repo.AlertQuotaRepo
	once                  sync.Once
}

func NewService(
	cfg *config.Config,
	accountClient *account.Client,
	billingClient *billing.Client,
	coreSvcClient *core_svc.Client,
	mgmtSvcClient *mgmt_svc.Client,
) *Service {
	svc := &Service{
		cfg:                   cfg,
		accountClient:         accountClient,
		billingClient:         billingClient,
		coreSvcClient:         coreSvcClient,
		mgmtSvcClient:         mgmtSvcClient,
		alertSubscriberRepo:   &repo.AlertSubscriberRepo{},
		alertNotificationRepo: &repo.AlertNotificationRepo{},
		alertQuotaRepo:        &repo.AlertQuotaRepo{},
		notificationClient:    notification.New(accountClient),
	}
	return svc
}

func (s *Service) RegisterRouter(r *gin.RouterGroup) {
	r.GET("/orgs/:orgId/projects/:projectId/alertSubscribers", s.ListAlertSubscribers)
	r.POST("/orgs/:orgId/projects/:projectId/alertSubscribers", s.CreateAlertSubscriber)
	r.DELETE("/orgs/:orgId/projects/:projectId/alertSubscribers/:alertSubscriberId", s.DeleteAlertSubscriber)

	r.GET("/orgs/:orgId/projects/:projectId/alertSubscriberQuota", s.GetAlertSubscriberQuota)
}

// RegisterNextGenRouter registers alert subscriber APIs for next-gen clusters
func (s *Service) RegisterNextGenRouter(r *gin.RouterGroup) {
	// In the next-gen architecture, since there is no project,
	// the alert subscription appears at the cluster level.
	r.GET("/orgs/:orgId/clusters/:clusterId/alertSubscribers", s.ListNextGenAlertSubscribers)
	r.POST("/orgs/:orgId/clusters/:clusterId/alertSubscribers", s.CreateNextGenAlertSubscriber)
	r.DELETE("/orgs/:orgId/clusters/:clusterId/alertSubscribers/:alertSubscriberId", s.DeleteNextGenAlertSubscriber)

	r.GET("/orgs/:orgId/clusters/:clusterId/alertSubscriberQuota", s.GetNextGenAlertSubscriberQuota)
}

func (s *Service) RegisterEssentialRouter(r *gin.RouterGroup) {
	r.GET("/orgs/:orgId/projects/:projectId/clusters/:clusterId/alertSubscribers", s.ListEssentialAlertSubscribers)
	r.POST("/orgs/:orgId/projects/:projectId/clusters/:clusterId/alertSubscribers", s.CreateEssentialAlertSubscriber)
	r.DELETE("/orgs/:orgId/projects/:projectId/clusters/:clusterId/alertSubscribers/:alertSubscriberId", s.DeleteEssentialAlertSubscriber)

	r.GET("/orgs/:orgId/projects/:projectId/clusters/:clusterId/alertSubscriberQuota", s.GetEssentialAlertSubscriberQuota)
}

func (s *Service) RegisterInternalRouter(r *gin.RouterGroup) {
	r.POST("/alertNotification", s.PushAlertNotification)
}
