package service

import (
	"context"
	"time"

	scalerpb "github.com/tidbcloud/aws-shared-provider/pkg/tidbworker/proto/scaler"
	"github.com/tidbcloud/aws-shared-provider/pkg/tidbworker/schema/ttl_task"
	"gorm.io/gorm"
	"gorm.io/gorm/clause"
)

var ttlTaskNow = time.Now

func (s *ScalerService) RegisterTTLTask(
	ctx context.Context,
	request *scalerpb.RegisterTTLTaskRequest,
) (*scalerpb.Response, error) {
	if request == nil || request.GetHeader() == nil {
		return scalerResponse(ErrBadRequest), nil
	}

	err := s.GetDB().WithContext(ctx).Transaction(func(tx *gorm.DB) error {
		ttlTableInfo := &ttl_task.TTLTableInfo{
			KeyspaceName: request.GetHeader().GetKeyspaceName(),
			TableID:      request.GetTableId(),
			IsEnable:     request.GetTtlJobEnable(),
		}
		err := tx.Clauses(clause.OnConflict{
			Columns:   []clause.Column{{Name: "keyspace_name"}, {Name: "table_id"}},
			DoUpdates: clause.AssignmentColumns([]string{"registered_at"}),
		}).Create(ttlTableInfo).Error
		if err != nil {
			return err
		}

		now := ttlTaskNow().Unix()
		err = tx.Model(&ttl_task.Task{}).
			Where("keyspace_name = ?", request.GetHeader().GetKeyspaceName()).
			Where("table_id = ?", request.GetTableId()).
			Where("last_ttl_run_time <= ?", now).
			Update("state", ttl_task.StateDeleted).Error
		if err != nil {
			return err
		}

		return tx.Clauses(clause.OnConflict{
			Columns: []clause.Column{
				{Name: "keyspace_name"},
				{Name: "table_id"},
				{Name: "last_ttl_run_time"},
			},
			DoUpdates: clause.AssignmentColumns([]string{"tidb_pool", "state", "registered_at"}),
		}).Create(&ttl_task.Task{
			KeyspaceName:   request.GetHeader().GetKeyspaceName(),
			TidbPool:       request.GetHeader().GetTidbPool(),
			LastTTLRunTime: now,
			TableID:        request.GetTableId(),
			State:          ttl_task.StatePending,
		}).Error
	})
	return scalerResponse(err), nil
}

func (s *ScalerService) DeleteTTLTableInfo(
	ctx context.Context,
	request *scalerpb.DeleteTTLTableInfoRequest,
) (*scalerpb.Response, error) {
	if request == nil || request.GetHeader() == nil {
		return scalerResponse(ErrBadRequest), nil
	}

	err := s.GetDB().WithContext(ctx).Transaction(func(tx *gorm.DB) error {
		err := tx.Model(&ttl_task.TTLTableInfo{}).
			Where("keyspace_name = ?", request.GetHeader().GetKeyspaceName()).
			Where("table_id = ?", request.GetTableId()).
			Delete(nil).
			Error
		if err != nil {
			return err
		}

		return tx.Model(&ttl_task.Task{}).
			Where("keyspace_name = ?", request.GetHeader().GetKeyspaceName()).
			Where("table_id = ?", request.GetTableId()).
			Update("state", ttl_task.StateDeleted).
			Error
	})
	return scalerResponse(err), nil
}

func (s *ScalerService) RecycleTTLTask(ctx context.Context,
	request *scalerpb.RecycleTTLTaskRequest,
) (*scalerpb.Response, error) {
	if request == nil || request.GetHeader() == nil {
		return scalerResponse(ErrBadRequest), nil
	}

	err := s.GetDB().WithContext(ctx).Model(&ttl_task.Task{}).
		Where("keyspace_name = ?", request.GetHeader().GetKeyspaceName()).
		Where("last_ttl_run_time < ?", request.GetFinishTime()).
		Update("state", ttl_task.StateDone).
		Error
	return scalerResponse(err), nil
}

func (s *ScalerService) UpdateTTLJobEnable(
	ctx context.Context,
	request *scalerpb.UpdateTTLJobEnableRequest,
) (*scalerpb.Response, error) {
	if request == nil || request.GetHeader() == nil {
		return scalerResponse(ErrBadRequest), nil
	}

	err := s.GetDB().WithContext(ctx).Model(&ttl_task.TTLTableInfo{}).
		Where("keyspace_name = ?", request.GetHeader().GetKeyspaceName()).
		Update("is_enable", request.GetTtlJobEnable()).
		Error
	return scalerResponse(err), nil
}
