package diagcontroller

import (
	"context"
	"time"

	"github.com/pingcap/log"
	"github.com/tidbcloud/observability/pkg/diagcontroller/resources"
	"go.uber.org/zap"
)

type ResourceController struct {
	resource resources.Resourcer
}

func NewResourceController(res resources.Resourcer) *ResourceController {
	return &ResourceController{
		resource: res,
	}
}

func (c *ResourceController) Start(ctx context.Context) {
	c.syncResource(ctx)
}

func (c *ResourceController) syncResource(ctx context.Context) {
	ticker := time.NewTicker(c.resource.Interval())
	for {
		select {
		case <-ctx.Done():
			ticker.Stop()
			return
		case <-ticker.C:
			if !c.resource.IsExist() {
				log.Info("resource is not exist, skip", zap.String("Resource_Name", c.resource.Name()))
				continue
			}
			c.syncResourceOnce()
		}
	}
}

func (c *ResourceController) syncResourceOnce() {
	if err := c.offlineResource(); err != nil {
		log.Error("offline resource failed", zap.Error(err))
		return
	}
	if err := c.scaleResource(); err != nil {
		log.Error("scale resource failed", zap.Error(err))
		return
	}
}

func (c *ResourceController) offlineResource() error {
	return c.resource.Offline()
}

func (c *ResourceController) scaleResource() error {
	scaleCount, err := c.resource.GetScaleCount()
	if err != nil {
		return err
	}
	if scaleCount < 0 {
		return c.resource.ScaleDown(-scaleCount)
	}
	if scaleCount > 0 {
		return c.resource.ScaleUp(scaleCount)
	}

	log.Info("no need to scale resource", zap.String("Resource_Name", c.resource.Name()))
	return nil
}
