package message

import (
	"context"
	"errors"
	"fmt"
	"strings"

	"github.com/tidbcloud/AgentTeam/internal/coredb"
)

// LockActiveTaskScopeForMutation serializes a Task-scoped mutation with the
// authoritative Task delete path while the caller's transaction is open. For a
// subtask, the parent row is locked before the child row so deleting the
// parent cannot overtake a mutation that is already in progress.
//
// The returned boolean is false when the Task disappeared before the lock was
// acquired. The caller must not write Task-owned state in that case.
func LockActiveTaskScopeForMutation(
	ctx context.Context,
	tx coredb.Tx,
	workspaceID string,
	taskScopeID string,
) (bool, error) {
	workspaceID = strings.TrimSpace(workspaceID)
	taskScopeID = strings.TrimSpace(taskScopeID)
	if tx == nil || workspaceID == "" || taskScopeID == "" {
		return false, fmt.Errorf("Task mutation lifecycle transaction, workspace, and scope are required")
	}

	hints, available, err := loadTaskScopeLifecycleHints(ctx, tx, workspaceID, []string{taskScopeID})
	if err != nil || !available {
		return false, err
	}
	lockedRoots, err := lockTaskScopeLifecycleRoots(ctx, tx, workspaceID, hints)
	if errors.Is(err, errTaskScopeLifecycleTopologyChanged) {
		return false, nil
	}
	if err != nil || lockedRoots == nil {
		return false, err
	}
	active, err := lockTaskScopeLifecycleChildren(ctx, tx, workspaceID, hints, lockedRoots)
	if errors.Is(err, errTaskScopeLifecycleTopologyChanged) {
		return false, nil
	}
	if err != nil {
		return false, err
	}
	if !active {
		return false, nil
	}

	var scopeStatus string
	err = tx.QueryRow(ctx, `
SELECT status
FROM scopes
WHERE workspace_id = $1
  AND id = $2
  AND type = 'task'
FOR UPDATE
`, workspaceID, taskScopeID).Scan(&scopeStatus)
	if coredb.IsNotFound(err) {
		return false, nil
	}
	if err != nil {
		return false, fmt.Errorf("lock Task mutation lifecycle scope: %w", err)
	}
	return strings.TrimSpace(scopeStatus) == "active", nil
}
