package coverart

import (
	"context"
	"errors"
	"testing"
)

// fakeProvider is a minimal Provider for registry tests. Does not
// implement any capability interface.
type fakeProvider struct {
	id          string
	display     string
	requiresKey bool
	defaultOn   bool
}

func (f *fakeProvider) ID() string                         { return f.id }
func (f *fakeProvider) DisplayName() string                { return f.display }
func (f *fakeProvider) RequiresAPIKey() bool               { return f.requiresKey }
func (f *fakeProvider) DefaultEnabled() bool               { return f.defaultOn }
func (f *fakeProvider) Configure(_ ProviderSettings) error { return nil }

// fakeAlbumProvider opts into the AlbumCoverProvider capability for
// the capability-filter test.
type fakeAlbumProvider struct {
	fakeProvider
}

func (f *fakeAlbumProvider) FetchAlbumCover(_ context.Context, _ AlbumRef) ([]byte, error) {
	return []byte("img"), nil
}

func TestRegister_AddsProvider(t *testing.T) {
	resetRegistryForTests()
	defer resetRegistryForTests()

	p := &fakeProvider{id: "fake1", display: "Fake One"}
	Register(p)

	all := AllProviders()
	if len(all) != 1 {
		t.Fatalf("AllProviders len = %d, want 1", len(all))
	}
	if all[0].ID() != "fake1" {
		t.Errorf("ID = %q, want %q", all[0].ID(), "fake1")
	}
}

func TestRegister_PanicsOnDuplicateID(t *testing.T) {
	resetRegistryForTests()
	defer resetRegistryForTests()

	Register(&fakeProvider{id: "dup"})

	defer func() {
		if r := recover(); r == nil {
			t.Fatal("expected panic on duplicate ID")
		}
	}()
	Register(&fakeProvider{id: "dup"}) // should panic
}

func TestProviderByID_Found(t *testing.T) {
	resetRegistryForTests()
	defer resetRegistryForTests()

	Register(&fakeProvider{id: "x", display: "X"})

	p, err := ProviderByID("x")
	if err != nil {
		t.Fatalf("err = %v, want nil", err)
	}
	if p.DisplayName() != "X" {
		t.Errorf("display = %q, want %q", p.DisplayName(), "X")
	}
}

func TestProviderByID_NotFound(t *testing.T) {
	resetRegistryForTests()
	defer resetRegistryForTests()

	_, err := ProviderByID("missing")
	if !errors.Is(err, ErrProviderNotFound) {
		t.Errorf("err = %v, want ErrProviderNotFound", err)
	}
}

func TestCapabilityFiltering(t *testing.T) {
	resetRegistryForTests()
	defer resetRegistryForTests()

	plain := &fakeProvider{id: "plain"}
	withAlbum := &fakeAlbumProvider{fakeProvider: fakeProvider{id: "alb"}}
	Register(plain)
	Register(withAlbum)

	if got := len(AllProviders()); got != 2 {
		t.Fatalf("AllProviders len = %d, want 2", got)
	}

	// Type-assert to count AlbumCoverProvider implementers — mimics
	// what SettingsService.EnabledAlbumProviders does internally.
	var albumProviders []AlbumCoverProvider
	for _, p := range AllProviders() {
		if ap, ok := p.(AlbumCoverProvider); ok {
			albumProviders = append(albumProviders, ap)
		}
	}
	if len(albumProviders) != 1 {
		t.Fatalf("AlbumCoverProvider count = %d, want 1", len(albumProviders))
	}
	if albumProviders[0].ID() != "alb" {
		t.Errorf("AlbumCoverProvider[0].ID = %q, want %q", albumProviders[0].ID(), "alb")
	}
}
