import { compile } from "path-to-regexp";
import { waitFor } from "@testing-library/react";
import { renderHook } from "@testing-library/react";
import { API_ACL_RESOURCE_ENTRIES, API_ACL_ENTRY } from "../../api";
import { apiJsonPost, apiJsonPatch, apiJsonDelete } from "../../services/api";
import {
  useAclEntries,
  useAclEntryCreate,
  useAclEntryUpdate,
  useAclEntryDelete,
} from "../useAclEntries";

jest.mock("@truedat/core/services/api", () => {
  const originalModule = jest.requireActual("@truedat/core/services/api");

  return {
    __esModule: true,
    ...originalModule,
    apiJson: jest.fn(() => ({
      data: {
        _embedded: {
          acl_entries: [
            {
              _links: {
                self: {
                  href: "/api/acl_entries/1",
                  methods: ["GET", "DELETE", "POST"],
                },
              },
              acl_entry_id: 1,
              description: null,
              principal: {
                full_name: "Foo",
                id: 11,
                user_name: "foo@bar.com",
              },
              principal_type: "user",
              role_id: 111,
              role_name: "baz",
            },
          ],
        },
      },
    })),
    apiJsonPost: jest.fn(),
    apiJsonPatch: jest.fn(),
    apiJsonDelete: jest.fn(),
  };
});

const id = 1;
const resource = {
  type: "domain",
  id,
};

const payload = {
  acl_entry: {
    role_name: "role2",
    resource_type: resource.type,
    principal_type: "user",
    principal_id: 1,
    description: "foo",
  },
};

const acl_entry = {
  acl_entry_id: id,
  description: null,
  principal: {
    full_name: "Foo",
    id: 11,
    user_name: "foo@bar.com",
  },
  principal_type: "user",
  role_id: 111,
  role_name: "baz",
};

describe("hooks: useAclEntries", () => {
  it("use acl entries return acl entries correctly", () => {
    const {
      result: {
        current: { data },
      },
    } = renderHook(() => useAclEntries(resource));

    waitFor(() =>
      expect(data).toBe(
        expect.objectContaining({
          aclEntries: [acl_entry],
          actions: { canCreate: true },
        })
      )
    );
  });

  it("create acl entry trigger calls api json post with correct url and payload", () => {
    const {
      result: {
        current: { trigger },
      },
    } = renderHook(() => useAclEntryCreate(resource));

    trigger(payload);

    const url = compile(API_ACL_RESOURCE_ENTRIES)(resource);
    expect(apiJsonPost).toHaveBeenCalledWith(url, {
      ...payload,
    });
  });

  it("update acl entry trigger calls api json patch with correct url and payload", () => {
    const {
      result: {
        current: { trigger },
      },
    } = renderHook(() => useAclEntryUpdate(resource.id));

    trigger(payload);

    const url = compile(API_ACL_ENTRY)({ id: resource.id });
    expect(apiJsonPatch).toHaveBeenCalledWith(url, {
      ...payload,
    });
  });

  it("update acl entry trigger calls api json delete with correct url", () => {
    const {
      result: {
        current: { trigger },
      },
    } = renderHook(() => useAclEntryDelete(resource.id));

    trigger();

    const url = compile(API_ACL_ENTRY)({ id: resource.id });
    expect(apiJsonDelete).toHaveBeenCalledWith(
      url,
      expect.objectContaining({})
    );
  });
});
