package spindle

import (
	"context"
	"net/http"
	"testing"

	"github.com/bluesky-social/indigo/atproto/identity"
	"github.com/bluesky-social/indigo/atproto/syntax"

	"tangled.org/core/spindle/knotclient"
)

func noKnotEnv(t *testing.T) (*ensureEnv, syntax.DID) {
	env := newEnsureEnv(t)
	did := syntax.DID("did:plc:noknot")
	dir := identity.NewMockDirectory()
	dir.Insert(identity.Identity{DID: did})
	env.s.knots = knotclient.New(dir, http.DefaultClient, true)
	return env, did
}

func TestADidWithNoKnotIsNotRetried(t *testing.T) {
	env, did := noKnotEnv(t)

	if err := env.s.processEvent(context.Background(), markEvent(did, env.spindleDid(), testOwner)); err == nil {
		t.Fatal("setup: the refresh of a did with no knot succeeded")
	}
	if attempts, err := env.s.db.RepoRetryAttempts(did); err != nil || attempts != 0 {
		t.Fatalf("retry attempts = %d, %v, want none for a did with no knot", attempts, err)
	}
}

// fills 5000 rows, which repoRetryCap has to stay at or below
func TestRepoRetryTableStopsTakingNewDidsWhenFull(t *testing.T) {
	env := newEnsureEnv(t)
	if _, err := env.s.db.Exec(`with recursive n(i) as (select 1 union all select i + 1 from n where i < 5000)
		insert into repo_retries (repo_did, attempts, due) select 'did:plc:fill' || i, 1, 0 from n`); err != nil {
		t.Fatal(err)
	}

	env.s.failRepoRefresh("did:plc:newcomer")
	if attempts, err := env.s.db.RepoRetryAttempts("did:plc:newcomer"); err != nil || attempts != 0 {
		t.Fatalf("a new did got into a full retry table, attempts = %d, %v", attempts, err)
	}
	var rows int
	if err := env.s.db.QueryRow(`select count(*) from repo_retries`).Scan(&rows); err != nil || rows != 5000 {
		t.Fatalf("retry rows = %d, %v, want 5000", rows, err)
	}

	env.s.failRepoRefresh("did:plc:fill1")
	if attempts, err := env.s.db.RepoRetryAttempts("did:plc:fill1"); err != nil || attempts != 2 {
		t.Fatalf("a did already in the table has attempts = %d, %v, want 2", attempts, err)
	}
}
