package admin

import (
	"errors"

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

type RegionMachinePrice struct {
	Region       string
	Provider     string
	InstanceType string
	PriceHistory []ComponentPrice
}

func (m UserContext) ListRegionMachinePrice() ([]*RegionMachinePrice, error) {
	if m.tenantAndUser.ID == 0 {
		return nil, errors.New("not a normal user")
	}

	var (
		prices           []entity.RegionMachinePrice
		regionMachineMap = make(map[entity.ID]entity.RegionMachine)
		profileMap       = make(map[entity.ID]entity.MachineProfile)
	)

	err := db.Transaction(func(tx *gorm.DB) error {
		var regionMachines []entity.RegionMachine
		err := entity.NewRegionMachineQuerySet(tx).PreloadRegion().PreloadMachineProfile().All(&regionMachines)
		if err != nil {
			return err
		}
		for _, regionMachine := range regionMachines {
			regionMachineMap[regionMachine.ID] = regionMachine
		}

		var profiles []entity.MachineProfile
		err = entity.NewMachineProfileQuerySet(tx).PreloadProvider().All(&profiles)
		if err != nil {
			return err
		}
		for _, profile := range profiles {
			profileMap[profile.ID] = profile
		}

		return entity.NewRegionMachinePriceQuerySet(tx).PreloadRegionMachine().All(&prices)
	})
	if err != nil {
		return nil, err
	}

	var regionMachinePriceMap = make(map[entity.ID]*RegionMachinePrice)
	var regionMachinePrices []*RegionMachinePrice
	for _, item := range prices {
		regionMachinePrice, found := regionMachinePriceMap[item.RegionMachineID]
		if !found {
			regionMachine := regionMachineMap[item.RegionMachineID]
			profile := profileMap[regionMachine.MachineProfileID]
			regionMachinePrice = &RegionMachinePrice{
				Region:       regionMachine.Region.Name,
				Provider:     profile.Provider.Name.String(),
				InstanceType: profile.InstanceType.String(),
			}
			regionMachinePriceMap[item.RegionMachineID] = regionMachinePrice
			regionMachinePrices = append(regionMachinePrices, regionMachinePrice)
		}
		regionMachinePrice.PriceHistory = append(regionMachinePrice.PriceHistory, ComponentPrice{
			StartTime: item.EffectedAt.Unix(),
			Price:     item.Price,
		})
	}
	return regionMachinePrices, nil
}
