import React from "react";
import { fireEvent, render, screen, waitFor } from "@testing-library/react";
import "@testing-library/jest-dom";
import { jest } from "@jest/globals";

import { permissionTypes } from "../../constants/userConstants.js";
import {
  getAllMenu,
  getManageRole,
  getRoleDetails,
  updateRolePermission,
} from "../../constants/apiEndPoints.js";

let permissionId = "";

const mockGetApi = jest.fn();
const mockPostApi = jest.fn();

jest.unstable_mockModule("react-router-dom", () => ({
  __esModule: true,
  useOutletContext: () => ({ permissionId }),
}));

jest.unstable_mockModule("../../context/UserContext.js", () => ({
  __esModule: true,
  useUser: () => ({
    user: {
      user_email: "test@example.com",
    },
  }),
}));

jest.unstable_mockModule("../../services/apiService.js", () => ({
  __esModule: true,
  default: () => ({
    getApi: mockGetApi,
    postApi: mockPostApi,
  }),
}));

jest.unstable_mockModule("../../components/CommonTable.js", () => ({
  __esModule: true,
  default: ({ data, columns, handleModifyPermissions }) => {
    const rowCount = Array.isArray(data) ? data.length : data?.Records?.length ?? 0;

    return (
      <div data-testid="common-table">
        <div data-testid="rows">{rowCount}</div>
        <div data-testid="cols">{columns?.length ?? 0}</div>
        <button
          type="button"
          data-testid="modify-permissions"
          onClick={() =>
            handleModifyPermissions(
              { Role_Id: 10, RoleId: 10, RoleName: "Admin", ViewType: "3" },
              "delete"
            )
          }
        >
          Modify Permissions
        </button>
      </div>
    );
  },
}));

jest.unstable_mockModule("../../components/Loader.js", () => ({
  __esModule: true,
  default: () => <div data-testid="loader" />,
}));

jest.unstable_mockModule("./ManageRolesPermissionsPopup.js", () => ({
  __esModule: true,
  default: ({ open, actionType, onSave, getRoleData }) => (
    <div data-testid="popup">
      <div data-testid="popup-open">{open ? "open" : "closed"}</div>
      <div data-testid="popup-action">{actionType ?? ""}</div>
      <button
        type="button"
        data-testid="trigger-save"
        onClick={async () => {
          await onSave([{ RoleId: 10 }], "Save");
        }}
      >
        Trigger Save
      </button>
      <button
        type="button"
        data-testid="trigger-update"
        onClick={async () => {
          await onSave([{ RoleId: 10 }], "Update");
        }}
      >
        Trigger Update
      </button>
      <button
        type="button"
        data-testid="trigger-get-role-data"
        onClick={async () => {
          await getRoleData(10);
        }}
      >
        Trigger GetRoleData
      </button>
    </div>
  ),
}));

describe("ManageRoles", () => {
  let ManageRoles;

  beforeAll(async () => {
    ({ default: ManageRoles } = await import("./ManageRoles.js"));
  });

  beforeEach(() => {
    mockGetApi.mockReset();
    mockPostApi.mockReset();

    mockGetApi.mockImplementation(async (endpoint) => {
      if (endpoint === getAllMenu) return { Records: [{ Id: 1, Name: "Module A" }] };
      return { Records: [] };
    });

    mockPostApi.mockImplementation(async (endpoint) => {
      if (endpoint === getManageRole) {
        return {
          Records: [{ RoleId: 10, RoleName: "Admin", Status: true }],
          TotalRecords: 1,
        };
      }
      if (endpoint === updateRolePermission) {
        return { Records: [{ RoleId: 10, RoleName: "Admin" }] };
      }
      if (endpoint === getRoleDetails) {
        return { Records: [{ RoleId: 10, RoleName: "Admin" }] };
      }
      return { Records: [] };
    });
  });

  it("shows Add Role when user has full access and opens popup", async () => {
    permissionId = `${permissionTypes[0].key}`;

    render(<ManageRoles secondaryTitle="Manage Roles" />);

    await waitFor(() => {
      expect(mockPostApi).toHaveBeenCalled();
      expect(mockGetApi).toHaveBeenCalled();
    });

    const addRoleButton = screen.getByRole("button", { name: /add role/i });
    fireEvent.click(addRoleButton);

    expect(screen.getByTestId("popup-open")).toHaveTextContent("open");
    expect(screen.getByTestId("popup-action")).toHaveTextContent("addEdit");
  });

  it("does not show Add Role when user lacks full access", async () => {
    permissionId = "999";

    render(<ManageRoles secondaryTitle="Manage Roles" />);

    await waitFor(() => {
      expect(mockPostApi).toHaveBeenCalled();
      expect(mockGetApi).toHaveBeenCalled();
    });

    expect(screen.queryByRole("button", { name: /add role/i })).not.toBeInTheDocument();
  });

  it("opens delete action via CommonTable modify handler", async () => {
    permissionId = `${permissionTypes[0].key}`;

    render(<ManageRoles secondaryTitle="Manage Roles" />);

    await waitFor(() => {
      expect(mockPostApi).toHaveBeenCalled();
    });

    fireEvent.click(screen.getByTestId("modify-permissions"));

    expect(screen.getByTestId("popup-open")).toHaveTextContent("open");
    expect(screen.getByTestId("popup-action")).toHaveTextContent("delete");
  });

  it("calls updateRolePermission through handleSave and can fetch role details", async () => {
    permissionId = `${permissionTypes[0].key}`;

    render(<ManageRoles secondaryTitle="Manage Roles" />);

    await waitFor(() => {
      expect(mockPostApi).toHaveBeenCalled();
    });

    fireEvent.click(screen.getByTestId("trigger-save"));

    await waitFor(() => {
      expect(mockPostApi).toHaveBeenCalledWith(updateRolePermission, expect.anything());
    });

    fireEvent.click(screen.getByTestId("trigger-get-role-data"));

    await waitFor(() => {
      expect(mockPostApi).toHaveBeenCalledWith(getRoleDetails, expect.anything());
    });
  });
});
