package schedule

import (
	"context"
	"fmt"
	"time"

	"github.com/tidbcloud/AgentTeam/internal/core/runeffect"
)

// AutomationRunMessageBinding links a transcript message to the schedule run
// that produced it. Callers must bind inside the message write transaction so
// read projections never observe the message without its source.
type AutomationRunMessageBinding struct {
	WorkspaceID string
	ID          string
	MessageID   string
	Now         time.Time
}

// BindAutomationRunMessage links a schedule run to its transcript message in
// the caller's transaction without marking the run complete.
func (store *TxStore) BindAutomationRunMessage(ctx context.Context, params AutomationRunMessageBinding) (AutomationRun, error) {
	execer, err := execerFromTxStore(store)
	if err != nil {
		return AutomationRun{}, err
	}
	workspaceID := trim(params.WorkspaceID)
	if workspaceID == "" {
		return AutomationRun{}, badRequest("workspaceId is required")
	}
	runID := trim(params.ID)
	if runID == "" {
		return AutomationRun{}, badRequest("automationRunId is required")
	}
	messageID := trim(params.MessageID)
	if messageID == "" {
		return AutomationRun{}, badRequest("messageId is required")
	}
	run, err := loadAutomationRun(ctx, execer, workspaceID, runID, true)
	if err != nil {
		return AutomationRun{}, err
	}
	if run.AutomationKind != AutomationKindSchedule {
		return AutomationRun{}, conflict("automation run is not a schedule run")
	}
	if run.MessageID != "" {
		if run.MessageID != messageID {
			return AutomationRun{}, conflict("automation run is already bound to a different message")
		}
		return run, nil
	}
	if run.Status != string(runeffect.StatusRunning) {
		return AutomationRun{}, conflict("automation run is not running")
	}

	now := utcOrNow(params.Now)
	result, err := execer.Exec(ctx, `
UPDATE automation_runs
SET message_id = $2,
    updated_at = $3
WHERE id = $1
`, run.ID, messageID, now)
	if err != nil {
		return AutomationRun{}, fmt.Errorf("bind schedule automation run message: %w", err)
	}
	if result.RowsAffected() == 0 {
		return AutomationRun{}, notFound("automation run not found")
	}
	run.MessageID = messageID
	run.UpdatedAt = now
	return run, nil
}
