package taskboard

import (
	"context"
	"fmt"
	"strings"
	"time"

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

func taskScopeID(taskID string) string {
	return strings.TrimSpace(taskID)
}

func taskScopeIdentityKey(taskID string) string {
	return "scope/task/" + taskScopeID(taskID)
}

func (txs TxStore) ensureTaskScope(ctx context.Context, tx coredb.Tx, workspaceID string, taskID string, createdByMemberID string, now time.Time) (string, error) {
	taskScopeID := taskScopeID(taskID)
	if taskScopeID == "" {
		return "", fmt.Errorf("task id is required for canonical task scope")
	}
	if _, err := tx.Exec(ctx, `
INSERT INTO scopes (
    id,
    workspace_id,
    type,
    parent_scope_id,
    root_message_id,
    root_message_short_id,
    identity_key,
    latest_seq,
    latest_global_seq,
    latest_activity_seq,
    latest_message_at,
    visible_message_count,
    visible_last_message_at,
    archived_until_seq,
    status,
    created_by_member_id,
    created_at,
    updated_at,
    archived_at
) VALUES ($1, $2, 'task', NULL, NULL, NULL, $3, 0, 0, 0, NULL, 0, NULL, 0, 'active', $4, $5, $5, NULL)
ON DUPLICATE KEY UPDATE
    updated_at = updated_at
`, taskScopeID, workspaceID, taskScopeIdentityKey(taskScopeID), createdByMemberID, now); err != nil {
		return "", fmt.Errorf("ensure canonical task scope: %w", err)
	}
	return taskScopeID, nil
}

func (txs TxStore) loadTaskScopeID(ctx context.Context, queryer coredb.QueryRower, taskID string) (string, error) {
	row := queryer.QueryRow(ctx, `
SELECT task_scope_id
FROM tasks
WHERE id = $1
`, taskID)

	var taskScopeID string
	if err := row.Scan(&taskScopeID); err != nil {
		if coredb.IsNotFound(err) {
			return "", ErrNotFound
		}
		return "", fmt.Errorf("load canonical task scope id: %w", err)
	}
	if strings.TrimSpace(taskScopeID) == "" {
		return "", fmt.Errorf("canonical task scope id is empty for task %s", strings.TrimSpace(taskID))
	}
	return taskScopeID, nil
}

func (txs TxStore) tombstoneTaskScope(ctx context.Context, tx coredb.Tx, taskScopeID string, now time.Time) error {
	trimmedTaskScopeID := strings.TrimSpace(taskScopeID)
	if trimmedTaskScopeID == "" {
		return fmt.Errorf("canonical task scope id is required")
	}
	commandTag, err := tx.Exec(ctx, `
UPDATE scopes
SET status = 'deleted',
    archived_at = COALESCE(archived_at, $2),
    updated_at = $2
WHERE id = $1
  AND type = 'task'
`, trimmedTaskScopeID, now)
	if err != nil {
		return fmt.Errorf("tombstone canonical task scope: %w", err)
	}
	if commandTag.RowsAffected() == 0 {
		return fmt.Errorf("tombstone canonical task scope: %w", ErrNotFound)
	}
	if _, err := tx.Exec(ctx, `
UPDATE im_conversation_index
SET archived_at = COALESCE(archived_at, $2),
    updated_at = $2
WHERE scope_id = $1
  AND kind = 'task'
`, trimmedTaskScopeID, now); err != nil {
		return fmt.Errorf("archive deleted task conversations: %w", err)
	}
	if _, err := tx.Exec(ctx, `
UPDATE scope_fanout_outbox
SET status = 'suppressed',
    suppressed_at = $2,
    suppression_reason = 'task_deleted',
    lease_owner = NULL,
    lease_expires_at = NULL,
    last_error = ''
WHERE scope_id = $1
  AND status IN ('pending', 'leased', 'pending_v2', 'leased_v2', 'failed')
`, trimmedTaskScopeID, now); err != nil {
		return fmt.Errorf("suppress deleted task fanout: %w", err)
	}
	return nil
}
