package auth

import (
	"testing"

	"secondbit.org/uuid"
)

var clientStores = []ClientStore{NewMemstore()}

func compareClients(client1, client2 Client) (success bool, field string, val1, val2 interface{}) {
	if !client1.ID.Equal(client2.ID) {
		return false, "ID", client1.ID, client2.ID
	}
	if client1.Secret != client2.Secret {
		return false, "secret", client1.Secret, client2.Secret
	}
	if client1.RedirectURI != client2.RedirectURI {
		return false, "redirect URI", client1.RedirectURI, client2.RedirectURI
	}
	if !client1.OwnerID.Equal(client2.OwnerID) {
		return false, "owner ID", client1.OwnerID, client2.OwnerID
	}
	if client1.Name != client2.Name {
		return false, "name", client1.Name, client2.Name
	}
	if client1.Logo != client2.Logo {
		return false, "logo", client1.Logo, client2.Logo
	}
	if client1.Website != client2.Website {
		return false, "website", client1.Website, client2.Website
	}
	return true, "", nil, nil
}

func TestClientStoreSuccess(t *testing.T) {
	client := Client{
		ID:          uuid.NewID(),
		Secret:      "secret",
		RedirectURI: "redirectURI",
		OwnerID:     uuid.NewID(),
		Name:        "name",
		Logo:        "logo",
		Website:     "website",
	}
	for _, store := range clientStores {
		err := store.SaveClient(client)
		if err != nil {
			t.Errorf("Error saving client to %T: %s", store, err)
		}
		err = store.SaveClient(client)
		if err != ErrClientAlreadyExists {
			t.Errorf("Expected ErrClientAlreadyExists, got %v from %T", err, store)
		}
		retrieved, err := store.GetClient(client.ID)
		if err != nil {
			t.Errorf("Error retrieving client from %T: %s", store, err)
		}
		success, field, expectation, result := compareClients(client, retrieved)
		if !success {
			t.Errorf("Expected field %s to be %v, but %T returned %v", field, expectation, store, result)
		}
		clients, err := store.ListClientsByOwner(client.OwnerID, 25, 0)
		if err != nil {
			t.Errorf("Error retrieving clients by owner from %T: %s", store, err)
		}
		if len(clients) != 1 {
			t.Errorf("Expected 1 client in response from %T, got %+v", store, clients)
		}
		success, field, expectation, result = compareClients(client, clients[0])
		if !success {
			t.Errorf("Expected field %s to be %v, but %T returned %v", field, expectation, store, result)
		}
		err = store.DeleteClient(client.ID)
		if err != nil {
			t.Errorf("Error deleting client from %T: %s", store, err)
		}
		err = store.DeleteClient(client.ID)
		if err != ErrClientNotFound {
			t.Errorf("Expected ErrClientNotFound, got %s from %T", err, store)
		}
		retrieved, err = store.GetClient(client.ID)
		if err != ErrClientNotFound {
			t.Errorf("Expected ErrClientNotFound from %T, got %+v and %s", store, retrieved, err)
		}
		clients, err = store.ListClientsByOwner(client.OwnerID, 25, 0)
		if err != nil {
			t.Errorf("Error listing clients by owner from %T: %s", store, err)
		}
		if len(clients) != 0 {
			t.Errorf("Expected 0 clients in response from %T, got %+v", store, clients)
		}
	}
}
