package taskcore

import (
	"context"
	"testing"
	"time"

	"github.com/cloudcarver/anclax/pkg/utils"
	"github.com/cloudcarver/anclax/pkg/zcore/model"
	"github.com/cloudcarver/anclax/pkg/zgen/apigen"
	"github.com/cloudcarver/anclax/pkg/zgen/querier"
	"github.com/stretchr/testify/require"
	"go.uber.org/mock/gomock"
)

func TestUpdateCronJob(t *testing.T) {
	ctrl := gomock.NewController(t)
	defer ctrl.Finish()

	var (
		ctx            = context.Background()
		taskID         = int32(1)
		cronExpression = "*/5 * * * * *"
		taskSpec       = apigen.TaskSpec{
			Payload: []byte{},
		}
		currentTime      = time.Date(2025, 3, 31, 12, 0, 0, 0, time.UTC)
		expectedNextTime = time.Date(2025, 3, 31, 12, 0, 5, 0, time.UTC)
	)

	mockModel := model.NewMockModelInterface(ctrl)

	mockModel.EXPECT().GetTaskByID(ctx, taskID).Return(&querier.AnclaxTask{
		ID: taskID,
		Attributes: apigen.TaskAttributes{
			Cronjob: &apigen.TaskCronjob{
				CronExpression: cronExpression,
			},
		},
	}, nil)

	mockModel.EXPECT().UpdateTask(ctx, utils.NewJSONValueMatcher(t, querier.UpdateTaskParams{
		ID: taskID,
		Attributes: apigen.TaskAttributes{
			Cronjob: &apigen.TaskCronjob{
				CronExpression: cronExpression,
			},
		},
		Spec:      taskSpec,
		StartedAt: &expectedNextTime,
	}))

	taskStore := &TaskStore{
		model: mockModel,
		now: func() time.Time {
			return currentTime
		},
	}
	err := taskStore.UpdateCronJob(ctx, taskID, cronExpression, []byte{})
	require.NoError(t, err)
}

func TestPauseCronJob(t *testing.T) {
	ctrl := gomock.NewController(t)
	defer ctrl.Finish()

	var (
		ctx    = context.Background()
		taskID = int32(1)
	)

	mockModel := model.NewMockModelInterface(ctrl)

	mockModel.EXPECT().UpdateTaskStatus(ctx, querier.UpdateTaskStatusParams{
		ID:     taskID,
		Status: string(apigen.Paused),
	}).Return(nil)

	taskStore := &TaskStore{
		model: mockModel,
	}

	err := taskStore.PauseTask(ctx, taskID)
	require.NoError(t, err)
}

func TestResumeCronJob(t *testing.T) {
	ctrl := gomock.NewController(t)
	defer ctrl.Finish()

	var (
		ctx    = context.Background()
		taskID = int32(1)
	)

	mockModel := model.NewMockModelInterface(ctrl)

	mockModel.EXPECT().UpdateTaskStatus(ctx, querier.UpdateTaskStatusParams{
		ID:     taskID,
		Status: string(apigen.Pending),
	}).Return(nil)

	taskStore := &TaskStore{
		model: mockModel,
	}
	err := taskStore.ResumeTask(ctx, taskID)
	require.NoError(t, err)
}
