package upload_api

import (
	"context"

	"github.com/gin-gonic/gin"
	"github.com/pingcap/errors"
	"go.uber.org/atomic"
	"go.uber.org/fx"

	error2 "github.com/pingcap-inc/clinic/pkg/api/error"
	"github.com/pingcap-inc/clinic/pkg/auditlog"
	"github.com/pingcap-inc/clinic/pkg/config"
	"github.com/pingcap-inc/clinic/pkg/task_manager"
	"github.com/pingcap-inc/clinic/pkg/upload_api/upload"
	"github.com/pingcap-inc/clinic/pkg/upload_file/manager"
)

type APIService struct {
	Params *APIServiceParams
	RG     *gin.RouterGroup
}

type APIServiceParams struct {
	Ctx            context.Context
	Gin            *gin.Engine
	Cfg            *config.Config
	Manager        *manager.FileStoreageManager
	AuditCli       *auditlog.AuditLogClient
	TaskManagerCli *task_manager.TaskManagerClient
}

var initialized atomic.Bool

func NewAPIService(params *APIServiceParams) *APIService {
	svc := &APIService{
		Params: params,
	}

	svc.Params.Gin.Use(gin.Recovery())
	svc.Params.Gin.Use(error2.ErrorHandlerFn)

	svc.RG = svc.Params.Gin.Group("/upload/api/v1")
	return svc
}

func (s *APIService) Start() error {
	if initialized.Swap(true) {
		return errors.New("global api service is already initialized")
	}

	app := fx.New(
		fx.Supply(s.RG, s.Params.Cfg, s.Params.Manager, s.Params.AuditCli, s.Params.TaskManagerCli),
		upload.Moudel,
	)

	if err := app.Start(s.Params.Ctx); err != nil {
		return err
	}

	return nil
}
