package admin

import (
	"fmt"
	"time"

	"github.com/pingcap/errcode"
	"github.com/pingcap/errors"
	"github.com/tidbcloud/central-sdk/db"
	"github.com/tidbcloud/central-sdk/db/entity"
	"gorm.io/gorm"
)

type TenantHeartbeatFee struct {
	TenantID         uint64
	NodeUsageFee     float64
	ClusterFeeDetail []ClusterHeartbeatFee
}

type ClusterHeartbeatFee struct {
	ClusterID          uint64
	ClusterName        string
	ClusterProfileName string
	TotalFee           float64
	DetailFee          []HeartbeatFee
}

type HeartbeatFee struct {
	StartTime time.Time
	EndTime   time.Time
	Fee       float64
	Status    string
	Detail    string
}

func (m UserContext) GetTenantHeartbeatFee(tenantID uint64, startTime, endTime int64) (*TenantHeartbeatFee, error) {
	if m.tenantAndUser.ID == 0 {
		return nil, errcode.NewInvalidInputErr(errors.New("not a normal user"))
	}
	tf, err := m.billingClient.GetTenantHeartbeatFee(fmt.Sprintf("%d", tenantID), startTime, endTime)
	if err != nil {
		return nil, err
	}
	apiTenantFee := TenantHeartbeatFee{
		TenantID:     tenantID,
		NodeUsageFee: tf.NodeUsageFee,
	}
	if len(tf.ClusterFeeDetail) <= 0 {
		return &apiTenantFee, nil
	}
	var clusterIDs []entity.ID
	var profileIDS []entity.ID
	for _, cd := range tf.ClusterFeeDetail {
		clusterIDs = append(clusterIDs, entity.ID(cd.ClusterID))
		profileIDS = append(profileIDS, entity.ID(cd.ClusterProfileID))
	}
	clusterIDNameMap := make(map[uint64]string)
	profileIDNameMap := make(map[uint64]string)
	err = db.Transaction(func(tx *gorm.DB) error {
		var clusters []entity.Cluster
		if err := entity.NewClusterQuerySet(tx).IDIn(clusterIDs...).All(&clusters); err != nil {
			return err
		}
		var profiles []entity.ClusterProfile
		if err := entity.NewClusterProfileQuerySet(tx).IDIn(profileIDS...).All(&profiles); err != nil {
			return err
		}
		for _, item := range clusters {
			clusterIDNameMap[item.ID.Uint64()] = item.Name
		}
		for _, item := range profiles {
			profileIDNameMap[item.ID.Uint64()] = item.Name
		}
		return nil
	})
	if err != nil {
		return nil, err
	}
	for _, item := range tf.ClusterFeeDetail {
		cf := ClusterHeartbeatFee{
			ClusterID:          item.ClusterID,
			ClusterName:        clusterIDNameMap[item.ClusterID],
			ClusterProfileName: profileIDNameMap[item.ClusterProfileID],
			TotalFee:           item.TotalFee,
		}
		for _, heartbeatFee := range item.DetailFee {
			cf.DetailFee = append(cf.DetailFee, HeartbeatFee{
				StartTime: time.Unix(heartbeatFee.StartTime, 0),
				EndTime:   time.Unix(heartbeatFee.EndTime, 0),
				Fee:       heartbeatFee.Fee,
				Status:    heartbeatFee.Status,
				Detail:    heartbeatFee.Detail,
			})
		}
		apiTenantFee.ClusterFeeDetail = append(apiTenantFee.ClusterFeeDetail, cf)
	}

	return &apiTenantFee, nil
}
