package awssubscriptionmngt

import (
	"errors"

	"github.com/pingcap/dbaas/billing2/billing_errors"
	"github.com/pingcap/dbaas/billing2/db"
	"github.com/pingcap/dbaas/billing2/db/entity"
	"github.com/pingcap/dbaas/billing2/forms"
	"github.com/pingcap/dbaas/billing2/utils/log"
	"go.uber.org/zap"
)

type AWSSubscriptionMngt struct{}

func (s *AWSSubscriptionMngt) CreateOrActiveSubscriptionRecord(record *forms.AWSSubscriptionRecord) (*forms.AWSSubscriptionRecord, error) {
	var entityRecord entity.AWSSubscriptionManagement
	err := entity.NewAWSSubscriptionManagementQuerySet(db.GetDB()).CustomerIdentifierEq(record.CustomerIdentifier).ProductCodeEq(record.ProductCode).One(&entityRecord)
	if err != nil {
		if errors.Is(err, billing_errors.ObjectNotExistsError) {
			// create a new record
			err = (&entity.AWSSubscriptionManagement{
				ProductCode:        record.ProductCode,
				CustomerIdentifier: record.CustomerIdentifier,
				InTrial:            record.InTrial,
				IsSubscribed:       true,
			}).Create(db.GetDB())
			if err != nil {
				log.Error("error creating aws subscription record", zap.Error(err))
				return nil, err
			}
			log.Info("success to create aws subscription record", zap.Any("record", record))
			return record, nil
		}
		log.Error("error querying aws subscription record", zap.Error(err))
		return nil, err
	}
	log.Info("aws subscription record already exists, it is re-subscribe", zap.Any("record", record))
	// non `free-trial`` to `free-trial` is forbidden, omit
	if !entityRecord.InTrial && record.InTrial {
		log.Info("omit to update aws subscription record, it is non free-trial to free-trial", zap.Any("record", record))
		return record, nil
	}
	// active subscription status
	err = entity.NewAWSSubscriptionManagementQuerySet(db.GetDB()).
		ProductCodeEq(record.ProductCode).
		CustomerIdentifierEq(record.CustomerIdentifier).
		GetUpdater().
		SetIsSubscribed(true).
		SetInTrial(record.InTrial).
		Update()
	if err != nil {
		log.Error("error update aws subscription", zap.String("identifier", record.CustomerIdentifier), zap.Error(err))
		return nil, err
	}
	return record, nil
}

func (s *AWSSubscriptionMngt) InActiveSubscriptionRecord(productCode string, customerIdentifier string) (*forms.AWSSubscriptionRecord, error) {
	var subscription entity.AWSSubscriptionManagement
	err := entity.NewAWSSubscriptionManagementQuerySet(db.GetDB()).ProductCodeEq(productCode).CustomerIdentifierEq(customerIdentifier).One(&subscription)
	if err != nil {
		if errors.Is(err, billing_errors.ObjectNotExistsError) {
			return &forms.AWSSubscriptionRecord{}, nil
		}
		log.Error("error querying aws subscription record", zap.String("customerIdentifier", customerIdentifier), zap.String("productCode", productCode), zap.Error(err))
		return nil, err
	}
	if !subscription.IsSubscribed {
		// idemponent
		log.Info("aws subscription record already unsubscribed", zap.Any("record", subscription))
		return &forms.AWSSubscriptionRecord{
			ProductCode:        subscription.ProductCode,
			CustomerIdentifier: subscription.CustomerIdentifier,
			InTrial:            subscription.InTrial,
		}, nil
	}
	err = entity.NewAWSSubscriptionManagementQuerySet(db.GetDB()).ProductCodeEq(productCode).CustomerIdentifierEq(customerIdentifier).GetUpdater().SetIsSubscribed(false).Update()
	if err != nil {
		log.Error("error inactive aws subscription", zap.String("customerIdentifier", customerIdentifier), zap.String("productCode", productCode), zap.Error(err))
		return nil, err
	}
	return &forms.AWSSubscriptionRecord{
		ProductCode:        subscription.ProductCode,
		CustomerIdentifier: subscription.CustomerIdentifier,
		InTrial:            subscription.InTrial,
	}, nil
}

func (s *AWSSubscriptionMngt) GetSubscriptionRecord(productCode string, customerIdentifier string) (*forms.AWSSubscriptionRecord, error) {
	var subscription entity.AWSSubscriptionManagement
	err := entity.NewAWSSubscriptionManagementQuerySet(db.GetDB()).ProductCodeEq(productCode).CustomerIdentifierEq(customerIdentifier).One(&subscription)
	if err != nil {
		if errors.Is(err, billing_errors.ObjectNotExistsError) {
			log.Info("aws subscription record is not exist", zap.String("customerIdentifier", customerIdentifier), zap.String("productCode", productCode))
			return &forms.AWSSubscriptionRecord{}, nil
		}
		return nil, err
	}
	return &forms.AWSSubscriptionRecord{
		ProductCode:        subscription.ProductCode,
		CustomerIdentifier: subscription.CustomerIdentifier,
		IsSubscribed:       subscription.IsSubscribed,
		InTrial:            subscription.InTrial,
	}, nil
}
