package aws

import (
	"fmt"
	"sync"

	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/aws/credentials"
	"github.com/aws/aws-sdk-go/aws/session"
	"github.com/aws/aws-sdk-go/service/autoscaling"
	"github.com/aws/aws-sdk-go/service/eks"
	"github.com/pingcap/log"
	"go.uber.org/zap"

	"github.com/pingcap-inc/clinic/pkg/config"
)

type EKSCli struct {
	cli           *eks.EKS
	asg           *autoscaling.AutoScaling
	name          string
	locker        sync.Mutex
	nodeGroupName string
}

func NewEKSCli(eksCfg config.EKSConfig) (*EKSCli, error) {
	awsConfig := &aws.Config{
		Region: aws.String(eksCfg.Region),
	}

	// if cfg.AWSStorage.
	if eksCfg.AccessKey != "" && eksCfg.SecretKey != "" {
		awsConfig = awsConfig.WithCredentials(credentials.NewStaticCredentials(eksCfg.AccessKey, eksCfg.SecretKey, eksCfg.Token))
	}
	awsSessionOpts := session.Options{
		Config: *awsConfig,
	}
	ses, err := session.NewSessionWithOptions(awsSessionOpts)
	if err != nil {
		return nil, err
	}

	return &EKSCli{
		asg:           autoscaling.New(ses),
		cli:           eks.New(ses),
		locker:        sync.Mutex{},
		name:          eksCfg.ClusterName,
		nodeGroupName: eksCfg.ImportNodeGroup,
	}, nil
}

func (e *EKSCli) ScaleUpNode() error {
	e.locker.Lock()
	defer e.locker.Unlock()

	o, err := e.cli.DescribeNodegroup(&eks.DescribeNodegroupInput{
		ClusterName:   aws.String(e.name),
		NodegroupName: aws.String(e.nodeGroupName),
	})
	if err != nil {
		return err
	}

	if o.Nodegroup == nil || o.Nodegroup.ScalingConfig == nil || o.Nodegroup.Resources == nil {
		return nil
	}

	desired := *o.Nodegroup.ScalingConfig.DesiredSize + 1
	if desired > *o.Nodegroup.ScalingConfig.MaxSize {
		return nil
	}

	if len(o.Nodegroup.Resources.AutoScalingGroups) != 1 {
		for _, group := range o.Nodegroup.Resources.AutoScalingGroups {
			log.Error("asg group", zap.String("group", *group.Name))
		}

		return fmt.Errorf("too many asg groups for %s, size=%d", e.nodeGroupName, len(o.Nodegroup.Resources.AutoScalingGroups))
	}

	group := o.Nodegroup.Resources.AutoScalingGroups[0]
	_, err = e.asg.SetDesiredCapacity(&autoscaling.SetDesiredCapacityInput{
		AutoScalingGroupName: group.Name,
		DesiredCapacity:      aws.Int64(desired),
		HonorCooldown:        aws.Bool(false),
	})
	if err != nil {
		log.Error("set desired for autoscaling group failed", zap.String("group", *group.Name), zap.Error(err))
		return err
	}

	log.Info("increase desired for asg group", zap.String("group", *group.Name), zap.Int64("current", desired))
	return nil
}
