package autobrr

import (
	"context"
	"encoding/json"
	"net/http"
	"net/http/httptest"
	"testing"
)

type fakeSecrets struct{ token string }

func (f fakeSecrets) Get(_ context.Context, _ string) ([]byte, error) {
	return []byte(f.token), nil
}

func newFakeAutobrr(t *testing.T) *httptest.Server {
	t.Helper()
	mux := http.NewServeMux()
	mux.HandleFunc("/api/filters", func(w http.ResponseWriter, r *http.Request) {
		if r.Header.Get("X-API-Token") != "the-token" {
			w.WriteHeader(401)
			return
		}
		_ = json.NewEncoder(w).Encode([]Filter{
			{ID: 1, Name: "1080p Internal", Enabled: true, Priority: 5},
			{ID: 2, Name: "Anime", Enabled: false},
		})
	})
	mux.HandleFunc("/api/filters/1", func(w http.ResponseWriter, _ *http.Request) {
		_ = json.NewEncoder(w).Encode(Filter{ID: 1, Name: "1080p Internal", Enabled: true})
	})
	mux.HandleFunc("/api/release", func(w http.ResponseWriter, _ *http.Request) {
		_ = json.NewEncoder(w).Encode(map[string]any{
			"data": []Release{
				{ID: 100, FilterID: 1, FilterName: "1080p Internal", Name: "Test.Release.2024.1080p", Indexer: "abc", InfoHash: "deadbeef"},
				{ID: 99, FilterID: 1, Name: "Another.Release", Indexer: "abc"},
			},
			"count": 2,
		})
	})
	mux.HandleFunc("/api/indexer/status", func(w http.ResponseWriter, _ *http.Request) {
		_ = json.NewEncoder(w).Encode([]IndexerStatus{
			{Identifier: "abc", Name: "ABC", Status: "connected"},
		})
	})
	mux.HandleFunc("/api/healthz/liveness", func(w http.ResponseWriter, _ *http.Request) {
		w.WriteHeader(200)
	})
	return httptest.NewServer(mux)
}

func newClientForTest(t *testing.T, srv *httptest.Server) *Client {
	t.Helper()
	c, err := New(Config{
		ID:      "autobrr-test",
		BaseURL: srv.URL,
		Secrets: fakeSecrets{token: "the-token"},
	})
	if err != nil {
		t.Fatalf("New: %v", err)
	}
	return c
}

func TestFilters(t *testing.T) {
	srv := newFakeAutobrr(t)
	defer srv.Close()
	c := newClientForTest(t, srv)
	got, err := c.Filters(context.Background())
	if err != nil {
		t.Fatalf("Filters: %v", err)
	}
	if len(got) != 2 || got[0].Name != "1080p Internal" {
		t.Errorf("filters: %+v", got)
	}
}

func TestFilter(t *testing.T) {
	srv := newFakeAutobrr(t)
	defer srv.Close()
	c := newClientForTest(t, srv)
	f, err := c.Filter(context.Background(), 1)
	if err != nil {
		t.Fatalf("Filter: %v", err)
	}
	if f.ID != 1 || !f.Enabled {
		t.Errorf("filter: %+v", f)
	}
}

func TestRecentReleasesWrappedShape(t *testing.T) {
	srv := newFakeAutobrr(t)
	defer srv.Close()
	c := newClientForTest(t, srv)
	rs, err := c.RecentReleases(context.Background(), 10)
	if err != nil {
		t.Fatalf("RecentReleases: %v", err)
	}
	if len(rs) != 2 || rs[0].InfoHash != "deadbeef" {
		t.Errorf("releases: %+v", rs)
	}
}

func TestRecentReleasesDirectArray(t *testing.T) {
	srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) {
		_ = json.NewEncoder(w).Encode([]Release{{ID: 1, Name: "X"}})
	}))
	defer srv.Close()
	c, _ := New(Config{ID: "x", BaseURL: srv.URL, Secrets: fakeSecrets{token: "t"}})
	rs, err := c.RecentReleases(context.Background(), 10)
	if err != nil {
		t.Fatalf("RecentReleases: %v", err)
	}
	if len(rs) != 1 || rs[0].Name != "X" {
		t.Errorf("releases: %+v", rs)
	}
}

func TestIndexerStatuses(t *testing.T) {
	srv := newFakeAutobrr(t)
	defer srv.Close()
	c := newClientForTest(t, srv)
	got, err := c.IndexerStatuses(context.Background())
	if err != nil {
		t.Fatalf("IndexerStatuses: %v", err)
	}
	if len(got) != 1 || got[0].Status != "connected" {
		t.Errorf("statuses: %+v", got)
	}
}

func TestHealth(t *testing.T) {
	srv := newFakeAutobrr(t)
	defer srv.Close()
	c := newClientForTest(t, srv)
	if err := c.Health(context.Background()); err != nil {
		t.Errorf("Health: %v", err)
	}
}

func TestAuthFailure(t *testing.T) {
	srv := newFakeAutobrr(t)
	defer srv.Close()
	c, _ := New(Config{ID: "x", BaseURL: srv.URL, Secrets: fakeSecrets{token: "wrong"}})
	_, err := c.Filters(context.Background())
	if err == nil {
		t.Fatal("expected auth failure")
	}
}
