package controller

import (
	"dataservices/commons/config"
	"dataservices/commons/ginparser"
	dto "dataservices/internal/dto/dataapi"
	"dataservices/internal/entity"
	service "dataservices/internal/service/central"
	"errors"
	"fmt"
	"net/http"

	"github.com/tidbcloud/tiinf/errs"

	"github.com/gin-gonic/gin"
	"github.com/google/go-github/v50/github"
	"github.com/tidbcloud/tiinf/monitor/tilog"
	"go.uber.org/zap"
)

func Webhook(c *gin.Context) {
	ctx := c.Request.Context()
	headerDelivery := c.Request.Header.Get("X-GitHub-Delivery")
	headerEvent := c.Request.Header.Get("X-GitHub-Event")
	payload, err := github.ValidatePayload(c.Request, []byte(config.Global().GhappConf.WebhookSecret))
	if err != nil {
		tilog.Error(
			ctx,
			"DS-Central-/webhook[post]-Webhook validate payload failed",
			zap.Error(err),
			zap.String("X-GitHub-Delivery", headerDelivery),
			zap.String("X-GitHub-Event", headerEvent),
		)
		c.Status(http.StatusBadRequest)
		return
	}
	ghappEventid := service.SaveGithubEvent(ctx, headerDelivery, headerEvent, string(payload))

	event, err := github.ParseWebHook(github.WebHookType(c.Request), payload)
	if err != nil {
		tilog.Error(
			ctx,
			"DS-Central-/webhook[post]-Webhook parse webhook failed",
			zap.Error(err),
			zap.String("X-GitHub-Delivery", headerDelivery),
			zap.String("X-GitHub-Event", headerEvent),
		)
		c.Status(http.StatusBadRequest)
		return
	}

	tilog.Info(
		ctx,
		"start to process webhook",
		zap.Uint64("ghappEventid", ghappEventid),
		zap.String("X-GitHub-Delivery", headerDelivery),
		zap.String("X-GitHub-Event", headerEvent),
	)
	switch event := event.(type) {
	case *github.InstallationEvent:
		err = service.ProcessInstallationEvent(ctx, event)
	case *github.InstallationRepositoriesEvent:
		err = service.ProcessInstallationRepositoriesEvent(ctx, event)
	case *github.RepositoryEvent:
		err = service.ProcessRepositoriesEvent(ctx, event)
	case *github.GitHubAppAuthorizationEvent:
		err = service.ProcessGithubAuthorizationEvent(ctx, event)
	case *github.PushEvent:
		err = service.ProcessPushEvent(ctx, event)
	case *github.DeleteEvent:
		err = service.ProcessDeleteEvent(ctx, event)
	default:
		err = errors.New("unknown event type")
	}

	if err != nil {
		tilog.Error(
			ctx,
			"DS-Central-/webhook[post]-Webhook process webhook failed",
			zap.Error(err),
			zap.Uint64("ghappEventid", ghappEventid),
			zap.String("X-GitHub-Delivery", headerDelivery),
			zap.String("X-GitHub-Event", headerEvent),
		)
		c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
		return
	}

	tilog.Info(
		ctx,
		"webhook process succeed",
		zap.Uint64("ghappEventid", ghappEventid),
		zap.String("X-GitHub-Delivery", headerDelivery),
		zap.String("X-GitHub-Event", headerEvent),
	)
	c.Status(http.StatusOK)
}

func Callback(c *gin.Context) {
	ctx := c.Request.Context()
	code, state := c.Query("code"), c.Query("state")
	redirectUrl, err := service.ProcessAuthorizationCallback(ctx, code, state)
	if err != nil {
		tilog.Error(ctx, "DS-Central-/callback[get]-Callback authorize failed", zap.String("code", code), zap.String("state", state), zap.Error(err))
		// c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
		c.Redirect(http.StatusFound, fmt.Sprintf("%s?error=%s", config.Global().GhappConf.UpdateDataappRedirectUrl, err.Error()))
		return
	}
	tilog.Info(ctx, "redirect to front-end", zap.String("redirectUrl", redirectUrl))
	c.Redirect(http.StatusFound, redirectUrl)
}

// GeneratePreflightRequest godoc
//
//	@Summary		generate the preflight request
//	@Description	generate the preflight request
//	@Tags			github_integration
//	@Param			org_id		path	string	true	"org ID"
//	@Param			project_id	path	string	true	"project ID"
//	@Produce		json
//	@Success		200	{object}	dto.GetAuthorizeUrlResp
//	@Router			/orgs/{org_id}/projects/{project_id}/preflight-request [POST]
func GeneratePreflightRequest(c *gin.Context) {
	ctx := c.Request.Context()
	validateKeys := &[]string{ginparser.PARAM_ORG_ID, ginparser.PARAM_PROJECT_ID}
	params := ginparser.NewCommonParamsByGin(c)
	createdBy, _ := params.GetUserEmail()
	validateErr := params.ValidateUrl(validateKeys)
	if validateErr != nil {
		tilog.Error(ctx, "DS-Central-/orgs/{org_id}/projects/{project_id}/preflight-request[POST]-GeneratePreflightRequest param validate failed!", zap.Error(validateErr), zap.String("user", createdBy))
		commonError(c, validateErr)
		return
	}
	url, err := service.GeneratePreflightRequest(ctx, params.OrgID, params.ProjectID, createdBy)
	if err != nil {
		tilog.Error(ctx, "DS-Central-/orgs/{org_id}/projects/{project_id}/preflight-request[POST]-GeneratePreflightRequest generate preflight request failed", zap.Error(err), zap.String("user", createdBy))
		commonError(c, err)
		return
	}
	tilog.Info(ctx, "generate preflight success", zap.String("preflight_request_id", url.PreflightRequestId), zap.String("user", createdBy))
	respJson := &dto.GetAuthorizeUrlResp{
		BaseResp: dto.SuccessBaseResp(),
		Data:     url,
	}
	c.JSON(http.StatusOK, respJson)
}

// GetDataappAuthorizeUrl godoc
//
//	@Summary		get url of authoriztion
//	@Description	get url of authoriztion
//	@Tags			github_integration
//	@Param			org_id		path	string	true	"org ID"
//	@Param			project_id	path	string	true	"project ID"
//	@Param			app_id		path	string	true	"app ID"
//	@Produce		json
//	@Success		200	{object}	dto.GetAuthorizeUrlResp
//	@Router			/orgs/{org_id}/projects/{project_id}/apps/{app_id}/authorize-url [get]
func GetDataappAuthorizeUrl(c *gin.Context) {
	ctx := c.Request.Context()
	validateKeys := &[]string{ginparser.PARAM_ORG_ID, ginparser.PARAM_PROJECT_ID, ginparser.PARAM_APP_ID}
	params := ginparser.NewCommonParamsByGin(c)
	createdBy, _ := params.GetUserEmail()
	validateErr := params.ValidateUrl(validateKeys)
	if validateErr != nil {
		tilog.Error(ctx, "DS-Central-/orgs/{org_id}/projects/{project_id}/apps/{app_id}/authorize-url[get]-GetDataappAuthorizeUrl param validate failed!", zap.Error(validateErr), zap.String("user", createdBy))
		commonError(c, validateErr)
		return
	}
	url, err := service.GetAuthorizeUrl(ctx, params.AppID)
	if err != nil {
		tilog.Error(ctx, "DS-Central-/orgs/{org_id}/projects/{project_id}/apps/{app_id}/authorize-url[get]-GetDataappAuthorizeUrl get authorize url failed", zap.Error(err), zap.String("user", createdBy))
		commonError(c, err)
		return
	}
	respJson := &dto.GetAuthorizeUrlResp{
		BaseResp: dto.SuccessBaseResp(),
		Data:     url,
	}
	c.JSON(http.StatusOK, respJson)
}

// ListDataappAuthorizedRepositories godoc
//
//	@Summary		list authorized github repositories of a dataapp
//	@Description	list authorized github repositories of a dataapp
//	@Tags			github_integration
//	@Param			org_id		path	string	true	"org ID"
//	@Param			project_id	path	string	true	"project ID"
//	@Param			app_id		path	string	true	"app ID"
//	@Produce		json
//	@Success		200	{object}	dto.ListAuthorizedRepositoriesResp
//	@Router			/orgs/{org_id}/projects/{project_id}/apps/{app_id}/repositories  [get]
func ListDataappAuthorizedRepositories(c *gin.Context) {
	ctx := c.Request.Context()
	validateKeys := &[]string{ginparser.PARAM_ORG_ID, ginparser.PARAM_PROJECT_ID, ginparser.PARAM_APP_ID}
	params := ginparser.NewCommonParamsByGin(c)
	createdBy, _ := params.GetUserEmail()
	validateErr := params.ValidateUrl(validateKeys)
	if validateErr != nil {
		tilog.Error(ctx, "DS-Central-/orgs/{org_id}/projects/{project_id}/apps/{app_id}/repositories[get]-ListDataappAuthorizedRepositories param validate failed!", zap.Error(validateErr), zap.String("user", createdBy))
		commonError(c, validateErr)
		return
	}
	repos, err := service.ListAuthorizedRepositories(ctx, params.AppID, 0)
	if err != nil {
		tilog.Error(ctx, "DS-Central-/orgs/{org_id}/projects/{project_id}/apps/{app_id}/repositories[get]-ListDataappAuthorizedRepositories list repos failed", zap.Error(err), zap.String("user", createdBy))
		commonError(c, err)
		return
	}
	respJson := &dto.ListAuthorizedRepositoriesResp{
		BaseResp: dto.SuccessBaseResp(),
		Data:     repos,
	}
	c.JSON(http.StatusOK, respJson)
}

// ListPreflightRequestAuthorizedRepositories godoc
//
//	@Summary		list authorized github repositories of a preflight request
//	@Description	list authorized github repositories of a preflight request
//	@Tags			github_integration
//	@Param			org_id		path	string	true	"org ID"
//	@Param			project_id	path	string	true	"project ID"
//	@Param			request_id	path	string	true	"preflight request ID"
//	@Produce		json
//	@Success		200	{object}	dto.ListAuthorizedRepositoriesResp
//	@Router			/orgs/{org_id}/projects/{project_id}/preflight-request/{request_id}/repositories  [get]
func ListPreflightRequestAuthorizedRepositories(c *gin.Context) {
	ctx := c.Request.Context()
	validateKeys := &[]string{ginparser.PARAM_ORG_ID, ginparser.PARAM_PROJECT_ID, ginparser.PARAM_PREFLIGHT_REQUEST_ID}
	params := ginparser.NewCommonParamsByGin(c)
	createdBy, _ := params.GetUserEmail()
	validateErr := params.ValidateUrl(validateKeys)
	if validateErr != nil {
		tilog.Error(ctx, "DS-Central-/orgs/{org_id}/projects/{project_id}/preflight-request/{request_id}/repositories[get]-ListPreflightRequestAuthorizedRepositories param validate failed!", zap.Error(validateErr), zap.String("user", createdBy))
		commonError(c, validateErr)
		return
	}
	err := service.ValidatePreflightRequestId(ctx, params.OrgID, params.ProjectID, params.PreflightRequestId)
	if err != nil {
		tilog.Error(ctx, "DS-Central-/orgs/{org_id}/projects/{project_id}/preflight-request/{request_id}/repositories[get]-ListPreflightRequestAuthorizedRepositories preflight_request_id validate failed!", zap.Error(err), zap.String("user", createdBy))
		commonError(c, err)
		return
	}
	repos, err := service.ListAuthorizedRepositories(ctx, 0, params.PreflightRequestId)
	if err != nil {
		tilog.Error(ctx, "DS-Central-/orgs/{org_id}/projects/{project_id}/preflight-request/{request_id}/repositories[get]-ListPreflightRequestAuthorizedRepositories list repos failed", zap.Error(err), zap.String("user", createdBy))
		commonError(c, err)
		return
	}
	respJson := &dto.ListAuthorizedRepositoriesResp{
		BaseResp: dto.SuccessBaseResp(),
		Data:     repos,
	}
	c.JSON(http.StatusOK, respJson)
}

// ListDataappAuthorizedRepositories godoc
//
//	@Summary		list authorized github branches of a data app
//	@Description	list authorized github branches of a dataapp
//	@Tags			github_integration
//	@Param			org_id		path	string	true	"org ID"
//	@Param			project_id	path	string	true	"project ID"
//	@Param			app_id		path	string	true	"app ID"
//	@Param			repo_id		path	string	true	"ghtub repository ID"
//	@Produce		json
//	@Success		200	{object}	dto.ListBranchesResp
//	@Router			/orgs/{org_id}/projects/{project_id}/apps/{app_id}/repositories/{repo_id}/branches  [get]
func ListDataappRepositoryBranches(c *gin.Context) {
	ctx := c.Request.Context()
	validateKeys := &[]string{ginparser.PARAM_ORG_ID, ginparser.PARAM_PROJECT_ID, ginparser.PARAM_APP_ID}
	params := ginparser.NewCommonParamsByGin(c)
	createdBy, _ := params.GetUserEmail()
	validateErr := params.ValidateUrl(validateKeys)
	if validateErr != nil {
		tilog.Error(ctx, "DS-Central-/orgs/{org_id}/projects/{project_id}/apps/{app_id}/repositories/{repo_id}/branches[get]-ListDataappRepositoryBranches param validate failed!", zap.Error(validateErr), zap.String("user", createdBy))
		commonError(c, validateErr)
		return
	}
	branches, err := service.ListBranches(ctx, params.AppID, 0, params.RepoID)
	if err != nil {
		tilog.Error(ctx, "DS-Central-/orgs/{org_id}/projects/{project_id}/apps/{app_id}/repositories/{repo_id}/branches[get]-ListDataappRepositoryBranches list branches failed", zap.Error(err), zap.String("user", createdBy))
		commonError(c, err)
		return
	}
	respJson := &dto.ListBranchesResp{
		BaseResp: dto.SuccessBaseResp(),
		Data:     branches,
	}
	c.JSON(http.StatusOK, respJson)
}

// ListDataappAuthorizedRepositories godoc
//
//	@Summary		list authorized github branches of a data app
//	@Description	list authorized github branches of a dataapp
//	@Tags			github_integration
//	@Param			org_id		path	string	true	"org ID"
//	@Param			project_id	path	string	true	"project ID"
//	@Param			request_id	path	string	true	"preflight request ID"
//	@Param			repo_id		path	string	true	"ghtub repository ID"
//	@Produce		json
//	@Success		200	{object}	dto.ListBranchesResp
//	@Router			/orgs/{org_id}/projects/{project_id}/preflight-request/{request_id}/repositories/{repo_id}/branches  [get]
func ListPreflightRequestRepositoryBranches(c *gin.Context) {
	ctx := c.Request.Context()
	validateKeys := &[]string{ginparser.PARAM_ORG_ID, ginparser.PARAM_PROJECT_ID, ginparser.PARAM_PREFLIGHT_REQUEST_ID}
	params := ginparser.NewCommonParamsByGin(c)
	createdBy, _ := params.GetUserEmail()
	validateErr := params.ValidateUrl(validateKeys)
	if validateErr != nil {
		tilog.Error(ctx, "DS-Central-/orgs/{org_id}/projects/{project_id}/preflight-request/{request_id}/repositories/{repo_id}/branches[get]-ListPreflightRequestRepositoryBranches param validate failed!", zap.Error(validateErr), zap.String("user", createdBy))
		commonError(c, validateErr)
		return
	}
	err := service.ValidatePreflightRequestId(ctx, params.OrgID, params.ProjectID, params.PreflightRequestId)
	if err != nil {
		tilog.Error(ctx, "DS-Central-/orgs/{org_id}/projects/{project_id}/preflight-request/{request_id}/repositories/{repo_id}/branches[get]-ListPreflightRequestRepositoryBranches preflight_request_id validate failed!", zap.Error(err), zap.String("user", createdBy))
		commonError(c, err)
		return
	}
	branches, err := service.ListBranches(ctx, 0, params.PreflightRequestId, params.RepoID)
	if err != nil {
		tilog.Error(ctx, "DS-Central-/orgs/{org_id}/projects/{project_id}/preflight-request/{request_id}/repositories/{repo_id}/branches[get]-ListPreflightRequestRepositoryBranches list branches failed", zap.Error(err), zap.String("user", createdBy))
		commonError(c, err)
		return
	}
	respJson := &dto.ListBranchesResp{
		BaseResp: dto.SuccessBaseResp(),
		Data:     branches,
	}
	c.JSON(http.StatusOK, respJson)
}

// PreflightValidateRepoBranchDirectory godoc
//
//	@Summary		validate repo/branch/direcotory a data app
//	@Description	validate repo/branch/direcotory a data app
//	@Tags			github_integration
//	@Param			org_id			path	string							true	"org ID"
//	@Param			project_id		path	string							true	"project ID"
//	@Param			request_id		path	string							true	"preflight request ID"
//	@Param			repo_id			path	string							true	"ghtub repository ID"
//	@Param			request_body	body	dto.RepoBranchDirValidateReq	true	"request_body"
//	@Produce		json
//	@Success		200	{object}	dto.RepoBranchDirValidateResp
//	@Router			/orgs/{org_id}/projects/{project_id}/preflight-request/{request_id}/repositories/{repo_id}/validate [post]
func PreflightValidateRepoBranchDirectory(c *gin.Context) {
	ctx := c.Request.Context()
	validateKeys := &[]string{ginparser.PARAM_ORG_ID, ginparser.PARAM_PROJECT_ID, ginparser.PARAM_PREFLIGHT_REQUEST_ID}
	params := ginparser.NewCommonParamsByGin(c)
	createdBy, _ := params.GetUserEmail()
	validateErr := params.ValidateUrl(validateKeys)
	if validateErr != nil {
		tilog.Error(ctx, "DS-Central-/orgs/{org_id}/projects/{project_id}/preflight-request/{request_id}/repositories/{repo_id}/validate[post]-PreflightValidateRepoBranchDirectory param validate failed!", zap.Error(validateErr), zap.String("user", createdBy))
		commonError(c, validateErr)
		return
	}
	err := service.ValidatePreflightRequestId(ctx, params.OrgID, params.ProjectID, params.PreflightRequestId)
	if err != nil {
		tilog.Error(ctx, "DS-Central-/orgs/{org_id}/projects/{project_id}/preflight-request/{request_id}/repositories/{repo_id}/validate[post]-PreflightValidateRepoBranchDirectory preflight_request_id validate failed!", zap.Error(err), zap.String("user", createdBy))
		commonError(c, err)
		return
	}

	var input dto.RepoBranchDirValidateReq
	err = params.BindParam(&input)
	if err != nil {
		tilog.Error(ctx, "DS-Central-/orgs/{org_id}/projects/{project_id}/preflight-request/{request_id}/repositories/{repo_id}/validate[post]-PreflightValidateRepoBranchDirectory LinkDataappWithGithub param bind failed!", zap.Error(err), zap.String("user", createdBy))
		commonError(c, errs.NewBadRequest("Bind Params Failed", err))
		return
	}
	tilog.Info(ctx, "RepoBranchDirValidateReq payload", zap.Any("input", input), zap.String("user", createdBy))
	res, err := service.ValidateRepoBranchDir(
		ctx,
		0,
		params.PreflightRequestId,
		params.RepoID,
		input.Branch,
		input.Directory,
	)
	if err != nil {
		tilog.Error(ctx, "DS-Central-/orgs/{org_id}/projects/{project_id}/preflight-request/{request_id}/repositories/{repo_id}/validate[post]-PreflightValidateRepoBranchDirectory validate repo branch directory failed", zap.Error(err), zap.String("user", createdBy))
		commonError(c, err)
		return
	}
	respJson := &dto.RepoBranchDirValidateResp{
		BaseResp: dto.SuccessBaseResp(),
		Data:     res,
	}
	c.JSON(http.StatusOK, respJson)
}

// DataappValidateRepoBranchDirectory godoc
//
//	@Summary		validate repo/branch/direcotory a preflight request
//	@Description	validate repo/branch/direcotory a preflight request
//	@Tags			github_integration
//	@Param			org_id			path	string							true	"org ID"
//	@Param			project_id		path	string							true	"project ID"
//	@Param			app_id			path	string							true	"app ID"
//	@Param			repo_id			path	string							true	"ghtub repository ID"
//	@Param			request_body	body	dto.RepoBranchDirValidateReq	true	"request_body"
//	@Produce		json
//	@Success		200	{object}	dto.RepoBranchDirValidateResp
//	@Router			/orgs/{org_id}/projects/{project_id}/apps/{app_id}/repositories/{repo_id}/validate [post]
func DataappValidateRepoBranchDirectory(c *gin.Context) {
	ctx := c.Request.Context()
	validateKeys := &[]string{ginparser.PARAM_ORG_ID, ginparser.PARAM_PROJECT_ID, ginparser.PARAM_APP_ID}
	params := ginparser.NewCommonParamsByGin(c)
	createdBy, _ := params.GetUserEmail()
	validateErr := params.ValidateUrl(validateKeys)
	if validateErr != nil {
		tilog.Error(ctx, "DS-Central-/orgs/{org_id}/projects/{project_id}/apps/{app_id}/repositories/{repo_id}/validate[post]-DataappValidateRepoBranchDirectory param validate failed!", zap.Error(validateErr), zap.String("user", createdBy))
		commonError(c, validateErr)
		return
	}
	var input dto.RepoBranchDirValidateReq
	err := params.BindParam(&input)
	if err != nil {
		tilog.Error(ctx, "DS-Central-/orgs/{org_id}/projects/{project_id}/apps/{app_id}/repositories/{repo_id}/validate[post]-DataappValidateRepoBranchDirectory LinkDataappWithGithub param bind failed!", zap.Error(err), zap.String("user", createdBy))
		commonError(c, errs.NewBadRequest("Bind Params Failed", err))
		return
	}
	tilog.Info(ctx, "RepoBranchDirValidateReq payload", zap.Any("input", input), zap.String("user", createdBy))

	res, err := service.ValidateRepoBranchDir(
		ctx,
		params.AppID,
		0,
		params.RepoID,
		input.Branch,
		input.Directory,
	)
	if err != nil {
		tilog.Error(ctx, "DS-Central-/orgs/{org_id}/projects/{project_id}/apps/{app_id}/repositories/{repo_id}/validate[post]-DataappValidateRepoBranchDirectory validate repo branch directory failed", zap.Error(err), zap.String("user", createdBy))
		commonError(c, err)
		return
	}
	respJson := &dto.RepoBranchDirValidateResp{
		BaseResp: dto.SuccessBaseResp(),
		Data:     res,
	}
	c.JSON(http.StatusOK, respJson)
}

// GetDataappGithubLinkageState godoc
//
//	@Summary		get github linkage status
//	@Description	get github linkage status
//	@Tags			github_integration
//	@Param			org_id		path	string	true	"org ID"
//	@Param			project_id	path	string	true	"project ID"
//	@Param			app_id		path	string	true	"app ID"
//	@Produce		json
//	@Success		200	{object}	dto.GithubLinkageStatusResp
//	@Router			/orgs/{org_id}/projects/{project_id}/apps/{app_id}/github [get]
func GetDataappGithubLinkageState(c *gin.Context) {
	ctx := c.Request.Context()
	validateKeys := &[]string{ginparser.PARAM_ORG_ID, ginparser.PARAM_PROJECT_ID, ginparser.PARAM_APP_ID}
	params := ginparser.NewCommonParamsByGin(c)
	createdBy, _ := params.GetUserEmail()
	validateErr := params.ValidateUrl(validateKeys)
	if validateErr != nil {
		tilog.Error(ctx, "DS-Central-/orgs/{org_id}/projects/{project_id}/apps/{app_id}/github[get]-GetDataappGithubLinkageState param validate failed!", zap.Error(validateErr), zap.String("user", createdBy))
		commonError(c, validateErr)
		return
	}

	res, err := service.GetDataappGithubLinkageStatus(ctx, params.AppID)
	if err != nil {
		tilog.Error(ctx, "DS-Central-/orgs/{org_id}/projects/{project_id}/apps/{app_id}/github[get]-GetDataappGithubLinkageState execution failed", zap.Error(err), zap.String("user", createdBy))
		commonError(c, err)
		return
	}
	resp := dto.GithubLinkageStatusResp{
		BaseResp: dto.SuccessBaseResp(),
		Data:     res,
	}
	c.JSON(http.StatusOK, resp)
}

// LinkDataappWithGithub godoc
//
//	@Summary		link dataapp with github
//	@Description	link dataapp with github
//	@Tags			github_integration
//	@Param			org_id			path	string					true	"org ID"
//	@Param			project_id		path	string					true	"project ID"
//	@Param			app_id			path	string					true	"app ID"
//	@Param			request_body	body	entity.LinkGithubParam	true	"request_body"
//	@Accept			json
//	@Produce		json
//	@Success		200	{object}	dto.CommonApiResp
//	@Router			/orgs/{org_id}/projects/{project_id}/apps/{app_id}/github/link [post]
func LinkDataappWithGithub(c *gin.Context) {
	ctx := c.Request.Context()
	validateKeys := &[]string{ginparser.PARAM_ORG_ID, ginparser.PARAM_PROJECT_ID, ginparser.PARAM_APP_ID}
	params := ginparser.NewCommonParamsByGin(c)
	createdBy, _ := params.GetUserEmail()
	validateErr := params.ValidateUrl(validateKeys)
	if validateErr != nil {
		tilog.Error(ctx, "DS-Central-/orgs/{org_id}/projects/{project_id}/apps/{app_id}/github/link[post]-LinkDataappWithGithub param validate failed!", zap.Error(validateErr), zap.String("user", createdBy))
		commonError(c, validateErr)
		return
	}

	var input entity.LinkGithubParam
	err := params.BindParam(&input)
	if err != nil {
		tilog.Error(ctx, "DS-Central-/orgs/{org_id}/projects/{project_id}/apps/{app_id}/github/link[post]-LinkDataappWithGithub param bind failed!", zap.Error(err), zap.String("user", createdBy))
		commonError(c, errs.NewBadRequest("Bind Params Failed", err))
		return
	}
	tilog.Info(ctx, "LinkDataappWithGithub payload", zap.Any("input", input), zap.String("user", createdBy))
	param := entity.PreflightLinkGithubParam{
		LinkGithubInnerParam: input.LinkGithubInnerParam,
		PreflightRequestId:   "",
	}
	err = service.EnableDataAppGithubAutoDeploy(ctx, params.AppID, param, input.EnableAutoDeploy)
	if err != nil {
		tilog.Error(ctx, "DS-Central-/orgs/{org_id}/projects/{project_id}/apps/{app_id}/github/link[post]-LinkDataappWithGithub execution failed!", zap.Error(err), zap.Uint64("app_id", params.AppID), zap.String("user", createdBy))
		commonError(c, err)
		return
	}
	// NOTE: 20230530 do not trigger deployment while edit github linkage
	// if _, err = service.TriggerDataAppUpdateFromUI(ctx, params.AppID, createdBy); err != nil {
	// 	tilog.Error(ctx, "TriggerDataAppUpdateFromUI failed!", zap.Error(err), zap.Uint64("app_id", params.AppID), zap.String("user", createdBy))
	// 	commonError(c, err)
	// 	return
	// }

	resJson := dto.SuccessV2()
	c.JSON(http.StatusOK, resJson)
}

// UnlinkDataappWithGithub godoc
//
//	@Summary		unlink dataapp with github
//	@Description	unlink dataapp with github
//	@Tags			github_integration
//	@Param			org_id		path	string	true	"org ID"
//	@Param			project_id	path	string	true	"project ID"
//	@Param			app_id		path	string	true	"app ID"
//	@Produce		json
//	@Success		200	{object}	dto.CommonApiResp
//	@Router			/orgs/{org_id}/projects/{project_id}/apps/{app_id}/github/unlink [post]
func UnlinkDataappWithGithub(c *gin.Context) {
	ctx := c.Request.Context()
	validateKeys := &[]string{ginparser.PARAM_ORG_ID, ginparser.PARAM_PROJECT_ID, ginparser.PARAM_APP_ID}
	params := ginparser.NewCommonParamsByGin(c)
	createdBy, _ := params.GetUserEmail()
	validateErr := params.ValidateUrl(validateKeys)
	if validateErr != nil {
		tilog.Error(ctx, "DS-Central-/orgs/{org_id}/projects/{project_id}/apps/{app_id}/github/unlink[post]-UnlinkDataappWithGithub param validate failed!", zap.Error(validateErr), zap.String("user", createdBy))
		commonError(c, validateErr)
		return
	}

	err := service.UnlinkDataappWithGithub(ctx, params.AppID)
	if err != nil {
		tilog.Error(ctx, "DS-Central-/orgs/{org_id}/projects/{project_id}/apps/{app_id}/github/unlink[post]-UnlinkDataappWithGithub execution failed", zap.Error(err), zap.Uint64("app_id", params.AppID), zap.String("user", createdBy))
		commonError(c, err)
		return
	}
	resJson := dto.SuccessV2()

	c.JSON(http.StatusOK, resJson)
}
