import { describe, expect, it, vi } from "vitest";
import { loadOrganizationMembers } from "../../helpers/organizationMembers.js";

const buildSupabase = ({
  fallbackResult,
  primaryResult,
}: {
  primaryResult: { data: unknown; error: { message: string } | null };
  fallbackResult?: { data: unknown; error: { message: string } | null };
}) => {
  const single = vi.fn().mockResolvedValue(
    fallbackResult ?? {
      data: null,
      error: { message: "fallback failed" },
    }
  );
  const order = vi.fn().mockResolvedValue(primaryResult);
  const primaryEq = vi.fn(() => ({ order }));
  const fallbackEq = vi.fn(() => ({ single }));
  const select = vi
    .fn()
    .mockImplementationOnce(() => ({ eq: primaryEq }))
    .mockImplementationOnce(() => ({ eq: fallbackEq }));
  const from = vi.fn(() => ({ select }));

  return {
    supabase: {
      from,
    },
    spies: {
      from,
      order,
      primaryEq,
      fallbackEq,
      select,
      single,
    },
  };
};

describe("loadOrganizationMembers", () => {
  it("returns organization members when the primary query succeeds", async () => {
    const members = [{ email: "owner@example.com", id: "owner-id" }];
    const { spies, supabase } = buildSupabase({
      primaryResult: {
        data: members,
        error: null,
      },
    });

    const result = await loadOrganizationMembers(supabase as never, {
      organizationId: 42,
      userId: "owner-id",
    });

    expect(result.data).toEqual(members);
    expect(result.error).toBeNull();
    expect(spies.from).toHaveBeenCalledTimes(1);
    expect(spies.primaryEq).toHaveBeenCalledWith("organization_id", 42);
    expect(spies.order).toHaveBeenCalledWith("created_at", { ascending: true });
  });

  it("falls back to the current user profile when the members query fails", async () => {
    const fallbackMember = { email: "owner@example.com", id: "owner-id" };
    const { spies, supabase } = buildSupabase({
      primaryResult: {
        data: null,
        error: { message: "members query failed" },
      },
      fallbackResult: {
        data: fallbackMember,
        error: null,
      },
    });

    const result = await loadOrganizationMembers(supabase as never, {
      organizationId: 42,
      userId: "owner-id",
    });

    expect(result.data).toEqual([fallbackMember]);
    expect(result.error).toBeNull();
    expect(spies.from).toHaveBeenCalledTimes(2);
    expect(spies.fallbackEq).toHaveBeenCalledWith("id", "owner-id");
    expect(spies.single).toHaveBeenCalledTimes(1);
  });

  it("returns the fallback error when both queries fail", async () => {
    const { supabase } = buildSupabase({
      primaryResult: {
        data: null,
        error: { message: "members query failed" },
      },
      fallbackResult: {
        data: null,
        error: { message: "fallback profile failed" },
      },
    });

    const result = await loadOrganizationMembers(supabase as never, {
      organizationId: 42,
      userId: "owner-id",
    });

    expect(result.data).toBeNull();
    expect(result.error).toEqual({ message: "fallback profile failed" });
  });
});
