package controller

import (
	"dataservices/commons/ginparser"
	dto "dataservices/internal/dto/dataapi"
	service "dataservices/internal/service/central"
	"net/http"

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

// ListDefaultDomains godoc
//
//	@Summary		list default domain
//	@Description	list default domain
//	@Tags			customdomain
//	@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.ListDefaultDomainsResponse
//	@Router			/orgs/{org_id}/projects/{project_id}/apps/{app_id}/default-domains [get]
func ListDefaultDomains(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}/default-domains[get]-ListDefaultDomains param validate failed!", zap.Error(validateErr), zap.String("user", createdBy))
		commonError(c, validateErr)
		return
	}
	data, err := service.ListDefaultDomains(ctx, params.AppID)
	if err != nil {
		tilog.Error(ctx, "DS-Central-/orgs/{org_id}/projects/{project_id}/apps/{app_id}/default-domains[get]-ListDefaultDomains list default domains failed!", zap.Error(err), zap.String("user", createdBy))
		commonError(c, err)
		return
	}
	resp := &dto.ListDefaultDomainsResponse{
		BaseResp: dto.SuccessBaseResp(),
		Data:     data,
	}
	c.JSON(http.StatusOK, resp)
}

// CreateCustomDomain godoc
//
//	@Summary		create custom domain
//	@Description	create custom domain
//	@Tags			customdomain
//	@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	dto.CustomDomainRequest	true	"request_body"
//	@Accept			json
//	@Produce		json
//	@Success		200	{object}	dto.CustomDomainResponse
//	@Router			/orgs/{org_id}/projects/{project_id}/apps/{app_id}/custom-domains [post]
func CreateCustomDomain(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}/custom-domains[post]-CreateCustomDomain param validate failed!", zap.Error(validateErr), zap.String("user", createdBy))
		commonError(c, validateErr)
		return
	}
	var req dto.CustomDomainRequest
	if err := params.BindParam(&req); err != nil {
		tilog.Error(ctx, "DS-Central-/orgs/{org_id}/projects/{project_id}/apps/{app_id}/custom-domains[post]-CreateCustomDomain param bind failed!", zap.Error(err), zap.String("user", createdBy))
		commonError(c, errs.NewBadRequest("Bind Params Failed", err))
		return
	}
	domain, err := service.CreateCustomDomain(ctx, params.AppID, &req, createdBy)
	if err != nil {
		tilog.Error(ctx, "DS-Central-/orgs/{org_id}/projects/{project_id}/apps/{app_id}/custom-domains[post]-CreateCustomDomain create customdomain failed!", zap.Error(err), zap.String("user", createdBy))
		commonError(c, err)
		return
	}
	resp := &dto.CustomDomainResponse{
		BaseResp: dto.SuccessBaseResp(),
		Data:     domain,
	}
	c.JSON(http.StatusOK, resp)
}

// ListCustomDomains godoc
//
//	@Summary		list custom domain
//	@Description	list custom domain
//	@Tags			customdomain
//	@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.ListCustomDomainsResponse
//	@Router			/orgs/{org_id}/projects/{project_id}/apps/{app_id}/custom-domains [get]
func ListCustomDomains(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}/custom-domains[get]-ListCustomDomains param validate failed!", zap.Error(validateErr), zap.String("user", createdBy))
		commonError(c, validateErr)
		return
	}
	data, err := service.ListCustomDomains(ctx, params.AppID)
	if err != nil {
		tilog.Error(ctx, "DS-Central-/orgs/{org_id}/projects/{project_id}/apps/{app_id}/custom-domains[get]-ListCustomDomains list custom domains failed!", zap.Error(err), zap.String("user", createdBy))
		commonError(c, err)
		return
	}
	resp := dto.ListCustomDomainsResponse{
		BaseResp: dto.SuccessBaseResp(),
		Data:     data,
	}
	c.JSON(http.StatusOK, resp)
}

// DeleteCustomDomain godoc
//
//	@Summary		delete custom domain
//	@Description	delete custom domain
//	@Tags			customdomain
//	@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}/custom-domains/{custom_domain_id} [delete]
func DeleteCustomDomain(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}/custom-domains [delete]-DeleteCustomDomain param validate failed!", zap.Error(validateErr), zap.String("user", createdBy))
		commonError(c, validateErr)
		return
	}

	err := service.DeleteCustomDomain(ctx, params.AppID, params.CustomDomainId)
	if err != nil {
		tilog.Error(ctx, "DS-Central-/orgs/{org_id}/projects/{project_id}/apps/{app_id}/custom-domains [delete]-DeleteCustomDomain delete custom domain failed!", zap.Error(err), zap.String("user", createdBy))
		commonError(c, err)
		return
	}
	resJson := dto.SuccessV2()

	c.JSON(http.StatusOK, resJson)
}

// EditCustomDomain godoc
//
//	@Summary		edit custom domain
//	@Description	edit custom domain
//	@Tags			customdomain
//	@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	dto.CustomDomainRequest	true	"request_body"
//	@Accept			json
//	@Produce		json
//	@Success		200	{object}	dto.CustomDomainResponse
//	@Router			/orgs/{org_id}/projects/{project_id}/apps/{app_id}/custom-domains/{custom_domain_id} [put]
func EditCustomDomain(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}/custom-domains [put]-EditCustomDomain param validate failed!", zap.Error(validateErr), zap.String("user", createdBy))
		commonError(c, validateErr)
		return
	}
	var req dto.CustomDomainRequest
	if err := params.BindParam(&req); err != nil {
		tilog.Error(ctx, "DS-Central-/orgs/{org_id}/projects/{project_id}/apps/{app_id}/custom-domains[put]-EditCustomDomain param bind failed!", zap.Error(err), zap.String("user", createdBy))
		commonError(c, errs.NewBadRequest("Bind Params Failed", err))
		return
	}

	domain, err := service.EditCustomDomain(ctx, params.AppID, params.CustomDomainId, &req, createdBy)
	if err != nil {
		tilog.Error(ctx, "DS-Central-/orgs/{org_id}/projects/{project_id}/apps/{app_id}/custom-domains [put]-EditCustomDomain edit custom domain failed!", zap.Error(err), zap.String("user", createdBy))
		commonError(c, err)
		return
	}
	resp := &dto.CustomDomainResponse{
		BaseResp: dto.SuccessBaseResp(),
		Data:     domain,
	}
	c.JSON(http.StatusOK, resp)

}

func InnerNotifyCustomDomainExpired(c *gin.Context) {
	ctx := c.Request.Context()
	var req dto.NotifyCustomDomainExpiredRequest
	if err := c.BindJSON(&req); err != nil {
		tilog.Error(ctx, "InnerNotifyCustomDomainExpired bind params failed", zap.Error(err))
		c.JSON(http.StatusBadRequest, dto.BaseResp{ErrCode: http.StatusBadRequest, ErrMsg: "parameter validate failed"})
		return
	}
	if err := service.NotifyCustomDomainExpired(ctx, req.CustomDomainName, req.DefaultDomainName); err != nil {
		tilog.Error(ctx, "InnerNotifyCustomDomainExpired call service failed", zap.Error(err))
		c.JSON(http.StatusInternalServerError, dto.BaseResp{ErrCode: http.StatusInternalServerError, ErrMsg: err.Error()})
		return
	}

	c.Status(http.StatusOK)
}
