package api

import (
	"errors"
	"github.com/gin-gonic/gin"
	"github.com/pingcap/dbaas/billing2/billing_errors"
	"github.com/pingcap/dbaas/billing2/constant"
	"github.com/pingcap/dbaas/billing2/db/entity"
	"github.com/pingcap/dbaas/billing2/forms"
	"github.com/pingcap/dbaas/billing2/handler/cloudmarketplacehandler"
	"github.com/pingcap/dbaas/billing2/utils/ginutils"
)

type subscription struct {
	SubscriptionId string `uri:"subscription_id" binding:"required"`
	TenantID       uint   `uri:"tenant_id" binding:"required"`
}

// @Summary Get Azure Token
// @Schemes
// @Accept json
// @Produce json
// @Success 200 {object} string
// @Router /marketplace/azure/token [get]
func (s *API) GetAzureToken(c *gin.Context) (ginutils.HandlerFuncResult, error) {

	handler, err := cloudmarketplacehandler.GetMarketplaceHandler().GetMarketplace(entity.PaymentType_AZURE)
	if err != nil {
		return nil, err
	}
	token, err := handler.GetToken()
	if err != nil {
		return nil, err
	}
	return token, err
}

type paymentCodeStruct struct {
	PaymentCode string `uri:"payment_code" binding:"required"`
}

// @Summary Get Azure subscriptions
// @Schemes
// @Accept json
// @Produce json
// @Param payment_code path string true "payment_code"
// @Success 200 {object} forms.SubscriptionList
// @Router /marketplace/azure/subscriptions/{payment_code} [get]
func (s *API) GetAzureSubscriptions(c *gin.Context) (ginutils.HandlerFuncResult, error) {
	paymentCode := &paymentCodeStruct{}
	err := c.ShouldBindUri(paymentCode)
	if err != nil {
		return nil, err
	}
	handler, err := cloudmarketplacehandler.GetMarketplaceHandler().GetMarketplace(entity.PaymentType_AZURE)

	if err != nil {
		return nil, err
	}
	return handler.GetSubscriptionsByAzureSubscriptionID(paymentCode.PaymentCode, false)
}

// @Summary Delete Azure Subscription
// @Schemes
// @Accept json
// @Produce json
// @Param subscription_id path string true "subscription_id"
// @Success 200 {object} forms.OKType
// @Router /marketplace/tenants/{tenant_id}/azure/subscriptions/{subscription_id} [DELETE]
func (s *API) DeleteAzureSubscription(c *gin.Context) (ginutils.HandlerFuncResult, error) {
	subscriptionStruct := &subscription{}

	err := c.ShouldBindUri(subscriptionStruct)
	if err != nil {
		return nil, billing_errors.NewInvalidInputError(err)
	}
	handler, err := cloudmarketplacehandler.GetMarketplaceHandler().GetMarketplace(entity.PaymentType_AZURE)
	if err != nil {
		return nil, err
	}
	billingConfigID, _ := getBillingConfigIDFromURI(c)
	oldPaymentMethod, err := paymentModel.GetPaymentMethodWithPaymentType(subscriptionStruct.TenantID, billingConfigID, entity.PaymentType_AZURE)
	if err != nil {
		return nil, err
	}
	if oldPaymentMethod.PaymentCode != subscriptionStruct.SubscriptionId {
		return nil, billing_errors.NewInvalidInputError(errors.New("subscriptionId is error"))

	}
	err = handler.CancelSubscription(subscriptionStruct.SubscriptionId)
	if err != nil {
		return nil, err
	}
	return forms.OK, err
}

// @Summary Active Azure Subscription
// @Schemes
// @Accept json
// @Produce json
// @Param subscription_id path string true "subscription_id"
// @Success 200 {object} forms.OKType
// @Router /marketplace/tenants/{tenant_id}/azure/subscriptions/{subscription_id} [POST]
func (s *API) ActiveAzureSubscription(c *gin.Context) (ginutils.HandlerFuncResult, error) {
	var subReq subscription
	if err := c.ShouldBindUri(&subReq); err != nil {
		return nil, billing_errors.NewInvalidInputError(err)
	}

	handler, err := cloudmarketplacehandler.GetMarketplaceHandler().
		GetMarketplace(entity.PaymentType_AZURE)
	if err != nil {
		return nil, err
	}

	currentSub, err := handler.GetSubscription(subReq.SubscriptionId)
	if err != nil {
		return nil, err
	}

	if currentSub.SaasSubscriptionStatus != constant.AzureSubscriptionStatusPending {
		return nil, billing_errors.NewInvalidInputError(errors.New("subscriptionId is error"))
	}

	billingConfigID, _ := getBillingConfigIDFromURI(c)
	oldPaymentMethod, err := paymentModel.GetPaymentMethodWithPaymentType(subReq.TenantID, billingConfigID, entity.PaymentType_AZURE)

	if err == nil {
		oldSub, err := handler.GetSubscription(oldPaymentMethod.PaymentCode)
		if err != nil {
			return nil, err
		}
		if oldSub.SaasSubscriptionStatus == constant.AzureSubscriptionStatusSubscribed {
			if err := handler.CancelSubscription(oldPaymentMethod.PaymentCode); err != nil {
				return nil, err
			}
		}
	}
	if err := handler.ActivateSubscription(subReq.SubscriptionId); err != nil {
		return nil, err
	}
	if _, err := paymentModel.UpdatePaymentCode(subReq.TenantID, oldPaymentMethod.PaymentMethodID, subReq.SubscriptionId, nil); err != nil {
		return nil, err
	}
	if !oldPaymentMethod.Payable {
		paymentModel.SyncPayable(subReq.TenantID)
	}
	return forms.OK, nil
}
func InitializeMarketplaceRouter(router ginutils.MyRoute) {
	s := &API{}
	router.HandleWithError("GET", "/marketplace/azure/token", s.GetAzureToken)
	router.HandleWithError("GET", "/marketplace/azure/subscriptions/:payment_code", s.GetAzureSubscriptions)
	router.HandleWithError("DELETE", "/marketplace/tenants/:tenant_id/azure/subscriptions/:subscription_id", s.DeleteAzureSubscription)
	router.HandleWithError("POST", "/marketplace/tenants/:tenant_id/azure/subscriptions/:subscription_id", s.ActiveAzureSubscription)

}
