package admin

import (
	"testing"
)

// TestNewAdmin verifies that NewAdmin creates an admin with correct defaults.
func TestNewAdmin(t *testing.T) {
	username := "testadmin"
	email := "testadmin@example.com"

	admin := NewAdmin(username, email)

	if admin.Username != username {
		t.Errorf("expected username %q, got %q", username, admin.Username)
	}
	if admin.Email != email {
		t.Errorf("expected email %q, got %q", email, admin.Email)
	}
	if admin.Role != RoleAdmin {
		t.Errorf("expected role %q, got %q", RoleAdmin, admin.Role)
	}
	if !admin.Active {
		t.Error("expected admin to be active by default")
	}
}

// TestAdmin_SetRole verifies role assignment.
func TestAdmin_SetRole(t *testing.T) {
	admin := NewAdmin("admin1", "admin1@example.com")

	tests := []struct {
		name     string
		role     Role
		expected Role
	}{
		{"super admin", RoleSuperAdmin, RoleSuperAdmin},
		{"regular admin", RoleAdmin, RoleAdmin},
		{"readonly", RoleReadOnly, RoleReadOnly},
	}

	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			admin.SetRole(tt.role)
			if admin.Role != tt.expected {
				t.Errorf("expected role %q, got %q", tt.expected, admin.Role)
			}
		})
	}
}

// TestAdmin_Deactivate verifies that deactivating an admin sets Active to false.
func TestAdmin_Deactivate(t *testing.T) {
	admin := NewAdmin("admin2", "admin2@example.com")

	admin.Deactivate()

	if admin.Active {
		t.Error("expected admin to be deactivated")
	}
}

// TestAdmin_Activate verifies that activating an admin sets Active to true.
func TestAdmin_Activate(t *testing.T) {
	admin := NewAdmin("admin3", "admin3@example.com")
	admin.Deactivate()

	admin.Activate()

	if !admin.Active {
		t.Error("expected admin to be activated")
	}
}

// TestAdmin_HasPermission verifies permission checks.
func TestAdmin_HasPermission(t *testing.T) {
	tests := []struct {
		name       string
		role       Role
		permission Permission
		expected   bool
	}{
		{"super admin can delete", RoleSuperAdmin, PermissionDelete, true},
		{"super admin can write", RoleSuperAdmin, PermissionWrite, true},
		{"super admin can read", RoleSuperAdmin, PermissionRead, true},
		{"admin can write", RoleAdmin, PermissionWrite, true},
		{"admin can read", RoleAdmin, PermissionRead, true},
		{"admin cannot delete", RoleAdmin, PermissionDelete, false},
		{"readonly can read", RoleReadOnly, PermissionRead, true},
		{"readonly cannot write", RoleReadOnly, PermissionWrite, false},
		{"readonly cannot delete", RoleReadOnly, PermissionDelete, false},
	}

	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			admin := NewAdmin("admin", "admin@example.com")
			admin.SetRole(tt.role)
			got := admin.HasPermission(tt.permission)
			if got != tt.expected {
				t.Errorf("HasPermission(%v) = %v, want %v", tt.permission, got, tt.expected)
			}
		})
	}
}

// TestAdmin_UpdateEmail verifies email update.
func TestAdmin_UpdateEmail(t *testing.T) {
	admin := NewAdmin("admin4", "old@example.com")

	newEmail := "new@example.com"
	admin.UpdateEmail(newEmail)

	if admin.Email != newEmail {
		t.Errorf("expected email %q, got %q", newEmail, admin.Email)
	}
}

// TestAdmin_UpdateEmail_Empty verifies that empty email is rejected.
func TestAdmin_UpdateEmail_Empty(t *testing.T) {
	admin := NewAdmin("admin5", "valid@example.com")

	err := admin.UpdateEmail("")

	if err == nil {
		t.Error("expected error for empty email, got nil")
	}
}

// TestAdminStore_Add verifies adding an admin to the store.
func TestAdminStore_Add(t *testing.T) {
	store := NewAdminStore()
	admin := NewAdmin("storeadmin", "storeadmin@example.com")

	err := store.Add(admin)

	if err != nil {
		t.Fatalf("unexpected error: %v", err)
	}
	got, ok := store.Get("storeadmin")
	if !ok {
		t.Fatal("expected admin to be found in store")
	}
	if got.Username != "storeadmin" {
		t.Errorf("expected username %q, got %q", "storeadmin", got.Username)
	}
}

// TestAdminStore_Add_Duplicate verifies that adding a duplicate admin returns an error.
func TestAdminStore_Add_Duplicate(t *testing.T) {
	store := NewAdminStore()
	admin := NewAdmin("dupadmin", "dupadmin@example.com")

	_ = store.Add(admin)
	err := store.Add(admin)

	if err == nil {
		t.Error("expected error for duplicate admin, got nil")
	}
}

// TestAdminStore_Remove verifies removing an admin from the store.
func TestAdminStore_Remove(t *testing.T) {
	store := NewAdminStore()
	admin := NewAdmin("removeadmin", "removeadmin@example.com")
	_ = store.Add(admin)

	err := store.Remove("removeadmin")

	if err != nil {
		t.Fatalf("unexpected error: %v", err)
	}
	_, ok := store.Get("removeadmin")
	if ok {
		t.Error("expected admin to be removed from store")
	}
}

// TestAdminStore_Remove_NotFound verifies that removing a non-existent admin returns an error.
func TestAdminStore_Remove_NotFound(t *testing.T) {
	store := NewAdminStore()

	err := store.Remove("nonexistent")

	if err == nil {
		t.Error("expected error for non-existent admin, got nil")
	}
}

// TestAdminStore_List verifies listing all admins.
func TestAdminStore_List(t *testing.T) {
	store := NewAdminStore()
	_ = store.Add(NewAdmin("admin_a", "a@example.com"))
	_ = store.Add(NewAdmin("admin_b", "b@example.com"))

	list := store.List()

	if len(list) != 2 {
		t.Errorf("expected 2 admins, got %d", len(list))
	}
}
