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

import { CreateEditRoleDialog } from "./CreateEditRoleDialog.js";
import { permissionTypes } from "../../constants/userConstants.js";
import { UserRoleHeirarchy } from "../../constants/userStatus.js";

function Harness({
  initialRoleData = null,
  initialRoleName = "",
  initialViewType = UserRoleHeirarchy[2].key,
  initialOldViewtype = UserRoleHeirarchy[2].key,
  initialShowPermissions = false,
  initialPermissions = [{ FeatureSubId: 1, SubFeatureName: "Module A", selectedPermission: null }],
  onClose = () => {},
  handleRoleSave = () => {},
  handlePermissionSave = () => {},
  handlePermissionChange = () => {},
}) {
  const [roleName, setRoleName] = useState(initialRoleName);
  const [viewType, setViewType] = useState(initialViewType);
  const [showPermissions, setShowPermissions] = useState(initialShowPermissions);

  return (
    <CreateEditRoleDialog
      open
      onClose={onClose}
      roleData={initialRoleData}
      showPermissions={showPermissions}
      roleName={roleName}
      handleRoleSave={handleRoleSave}
      viewType={viewType}
      setRoleName={setRoleName}
      setViewType={setViewType}
      permissions={initialPermissions}
      handlePermissionSave={handlePermissionSave}
      handlePermissionChange={handlePermissionChange}
      oldViewtype={initialOldViewtype}
      setShowPermissions={setShowPermissions}
    />
  );
}

describe("CreateEditRoleDialog", () => {
  it("renders create mode and keeps Save disabled until role name is set", () => {
    render(<Harness />);

    expect(screen.getByText("Create Role")).toBeInTheDocument();

    const saveButton = screen.getByRole("button", { name: /save/i });
    expect(saveButton).toBeDisabled();

    const roleNameInput = screen.getByLabelText(/role name/i);
    fireEvent.change(roleNameInput, { target: { value: "Admin" } });

    expect(saveButton).toBeEnabled();
  });

  it("rejects non-letter characters and collapses multiple spaces", () => {
    render(<Harness />);

    const roleNameInput = screen.getByLabelText(/role name/i);

    fireEvent.change(roleNameInput, { target: { value: "Admin1" } });
    expect(roleNameInput).toHaveValue("");

    fireEvent.change(roleNameInput, { target: { value: "Admin   User" } });
    expect(roleNameInput).toHaveValue("Admin User");
  });

  it("renders edit mode and enables Update when viewType changes", () => {
    render(
      <Harness
        initialRoleData={{ Role_Id: 10, RoleName: "Admin", ViewType: UserRoleHeirarchy[2].key }}
        initialRoleName="Admin"
        initialViewType={UserRoleHeirarchy[2].key}
        initialOldViewtype={UserRoleHeirarchy[2].key}
      />
    );

    expect(screen.getByText("Edit Role")).toBeInTheDocument();

    const updateButton = screen.getByRole("button", { name: /update/i });
    expect(updateButton).toBeDisabled();

    const differentRole = UserRoleHeirarchy.find((r) => r.key !== UserRoleHeirarchy[2].key);
    const newViewRadio = screen.getByRole("radio", { name: differentRole.value });
    fireEvent.click(newViewRadio);

    expect(updateButton).toBeEnabled();
  });

  it("shows EDIT PERMISSIONS button for Role_Id and switches to permissions view", () => {
    const handlePermissionChange = jest.fn();

    render(
      <Harness
        initialRoleData={{ Role_Id: 10, RoleName: "Admin", ViewType: UserRoleHeirarchy[2].key }}
        initialRoleName="Admin"
        initialPermissions={[
          { FeatureSubId: 1, SubFeatureName: "Module A", selectedPermission: null },
        ]}
        handlePermissionChange={handlePermissionChange}
      />
    );

    const editPermissions = screen.getByRole("button", { name: /edit permissions/i });
    fireEvent.click(editPermissions);

    expect(screen.getByRole("button", { name: /update permissions/i })).toBeInTheDocument();

    const option = screen.getByRole("radio", { name: permissionTypes[0].value });
    fireEvent.click(option);

    expect(handlePermissionChange).toHaveBeenCalledWith(0, Number(permissionTypes[0].key));
  });
});
