package automation

import (
	"context"
	"fmt"
	"testing"
	"time"

	"github.com/stretchr/testify/require"
	"github.com/tidbcloud/AgentTeam/internal/automation/dsl"
	"github.com/tidbcloud/AgentTeam/internal/service/automation/runtime"
	automationstore "github.com/tidbcloud/AgentTeam/internal/store/automation"
)

func TestDeliverAutomationWaitSignalResolvesSubscribersAcrossBatchBoundary(t *testing.T) {
	ctx := context.Background()
	db, err := openServiceTestSQLiteDB(t)
	require.NoError(t, err)
	migrateAutomationServiceTestSchema(t, db)
	store := automationstore.New(db)
	now := time.Date(2026, 6, 7, 9, 47, 0, 0, time.UTC)
	ids := 0
	newID := func(prefix string) (string, error) {
		ids++
		return fmt.Sprintf("%sboundary%03d", prefix, ids), nil
	}
	spec := dsl.DefinitionSpec{Name: "Boundary task wait", Jobs: map[string]dsl.JobSpec{
		"task":   {Steps: []dsl.StepSpec{{Uses: "agentteam/agent-task", With: map[string]any{"task_id": "tsk_boundary"}}}},
		"deploy": {Needs: []string{"task"}, Steps: []dsl.StepSpec{{Run: "make deploy"}}},
	}}
	const subscriberCount = automationWaitSignalDeliveryBatchSize + 1
	runIDs := make([]string, 0, subscriberCount)
	for i := 0; i < subscriberCount; i++ {
		runID := fmt.Sprintf("run-deliver-boundary-%03d", i)
		runIDs = append(runIDs, runID)
		run := automationstore.AutomationRun{ID: runID, WorkspaceID: "ws-1", Name: "Boundary task wait", Status: automationstore.AutomationRunStatusWaiting, CreatedByPrincipalID: "user-1", CreatedAt: now, UpdatedAt: now}
		rt, err := runtime.BuildInitialRuntime(run, spec, now, newID)
		require.NoError(t, err)
		require.Len(t, rt.Waits, 1)
		require.Equal(t, "tsk_boundary", rt.Waits[0].ResourceID)
		_, err = store.CreateRunWithRuntime(ctx, run, rt.JobRuns, rt.Events, rt.Jobs, rt.Waits)
		require.NoError(t, err)
	}

	service := NewAutomationsService(store, func() time.Time { return now.Add(time.Minute) }, nil)
	delivered, err := service.DeliverAutomationWaitSignal(ctx, "ws-1", "automation-eventer", AutomationWaitSignalMutation{WaitKind: automationstore.AutomationWaitKindAgentTask, ResourceID: "tsk_boundary", TaskNumber: 42, Status: "done"})
	require.NoError(t, err)
	require.Equal(t, automationstore.AutomationWaitStatusResolved, delivered.Status)

	var resolvedEvents int
	for _, runID := range runIDs {
		waits, err := store.ListWaits(ctx, "ws-1", runID, "")
		require.NoError(t, err)
		require.Len(t, waits, 1)
		require.Equal(t, automationstore.AutomationWaitStatusResolved, waits[0].Status)

		jobRuns, err := store.ListJobRuns(ctx, "ws-1", runID)
		require.NoError(t, err)
		require.Equal(t, automationstore.AutomationJobRunStatusSucceeded, jobRuns[0].Status)
		require.Equal(t, automationstore.AutomationJobRunStatusQueued, jobRuns[1].Status)

		events, err := store.ListEvents(ctx, "ws-1", runID, 1, 20)
		require.NoError(t, err)
		for _, event := range events {
			if event.EventType == "wait_resolved" {
				resolvedEvents++
			}
		}
	}
	require.Equal(t, subscriberCount, resolvedEvents)

	again, err := service.DeliverAutomationWaitSignal(ctx, "ws-1", "automation-eventer", AutomationWaitSignalMutation{WaitKind: automationstore.AutomationWaitKindAgentTask, ResourceID: "tsk_boundary", TaskNumber: 42, Status: "done"})
	require.NoError(t, err)
	require.Equal(t, automationstore.AutomationWaitStatusResolved, again.Status)
}
