import React, { useState, useEffect, useCallback } from "react";
import PropTypes from "prop-types";
import { toast } from "react-toastify";
import { consentType, saveType } from "../../constants/userConstants.js";
import "./ManageRolesPermissionsPopup.css";
import { UserRoleHeirarchy } from "../../constants/userStatus.js";
import ConsentPopup from "../../common/ConsentPopup.js";
import { deleteRole } from "../../constants/apiEndPoints.js";
import useApiService from "../../services/apiService.js";
import { CreateEditRoleDialog } from "./CreateEditRoleDialog.js";


function getInitialPermissions(allModules) {
  return allModules.map((module) => ({
    FeatureSubId: module.Id,
    SubFeatureName: module.Name,
    selectedPermission: null,
  }));
}


function formatPermissions(permissions) {
  return permissions
    .filter((module) => module.selectedPermission)
    .map((module) => ({
      FeatureSubId: `${module.FeatureSubId}`,
      PermissionId: `${module.selectedPermission}`,
    }));
}


function DeletePopup({
  totalAccessUsers,
  roleName,
  handleClose,
  handleConfirm,
  editRoleData,
  setNewRoleId,
  allRoles,
}) {
  return (
    <div className="popup">
      <ConsentPopup
        consentTypeAction={consentType.DeleteRole}
        title={
          totalAccessUsers
            ? "Delete & Role Change Confirmation"
            : "Delete Role Confirmation"
        }
        message={
          totalAccessUsers
            ? `${roleName} role is assigned to ${totalAccessUsers} users. Are you sure you want to delete this role?`
            : `Are you sure you want to delete ${roleName} role?`
        }
        actionMessagePositive={
          totalAccessUsers ? "Change & Delete" : "Yes, Delete"
        }
        actionMessageNegative="No, Cancel"
        onClose={handleClose}
        onAccept={handleConfirm}
        onRoleSelection={handleConfirm}
        editRoleData={editRoleData}
        setChangedRoleId={setNewRoleId}
        allRoles={allRoles}
        totalAccessUsers={totalAccessUsers}
      />
    </div>
  );
}

DeletePopup.propTypes = {
  totalAccessUsers: PropTypes.number,
  roleName: PropTypes.string.isRequired,
  handleClose: PropTypes.func.isRequired,
  handleConfirm: PropTypes.func.isRequired,
  editRoleData: PropTypes.shape({
    Role_Id: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
    RoleName: PropTypes.string,
  }),
  setNewRoleId: PropTypes.func,
  allRoles: PropTypes.arrayOf(
    PropTypes.shape({
      RoleId: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
      RoleName: PropTypes.string,
      ViewType: PropTypes.string,
    })
  ),
};

function ManageRolesPermissionsPopup({
  open,
  onClose,
  onSave,
  getRoleData,
  roleData = null,
  allModules = [],
  actionType,
  setActionType,
  editRoleData,
  getRoleTable,
  getAllRoles,
  allRoles,
}) {
  const { postApi } = useApiService();
  const [roleName, setRoleName] = useState("");
  const [roleId, setRoleId] = useState("");
  const [viewType, setViewType] = useState("");
  const [permissions, setPermissions] = useState([]);
  const [showPermissions, setShowPermissions] = useState(false);
  const [newRoleId, setNewRoleId] = useState(null);
  const [totalAccessUsers, setTotalAccessUsers] = useState(0);
  const [oldViewtype, setOldViewtype] = useState();


  useEffect(() => {
    if (!open) {
      resetState();
      return;
    }
    initializeRole();
  }, [open, roleData, allModules]);

  const resetState = () => {
    setRoleId(0);
    setRoleName("");
    setViewType(UserRoleHeirarchy[2].key);
    setPermissions([]);
    setShowPermissions(false);
    setTotalAccessUsers(0);
  };

  const initializeRole = () => {
    const currentRoleId = roleData?.RoleId || roleData?.Role_Id || "";
    setRoleId(currentRoleId);
    setRoleName(roleData?.RoleName || "");
    setViewType(roleData?.ViewType || "");
    if (currentRoleId) fetchRoleData(currentRoleId);
    else setPermissions(getInitialPermissions(allModules));
  };

  const fetchRoleData = async (roleId) => {
    try {
      const data = await getRoleData(roleId);
      const responseData = data || [];

      const firstRecord = responseData[0] || {};
      setViewType(firstRecord.ViewType);
      setOldViewtype(firstRecord.ViewType);
      setRoleName(firstRecord.RoleName || "");

      if (editRoleData) setTotalAccessUsers(firstRecord.TotalUsers || 0);

      setPermissions(
        allModules.map((module) => {
          const match = responseData.find(
            (item) =>
              item.FeatureSubFeature_Id?.toString() === module.Id?.toString()
          );
          return {
            FeatureSubId: module.Id,
            SubFeatureName: module.Name,
            selectedPermission: match ? Number(match.Permission_Id) : null,
          };
        })
      );
    } catch (error) {
      console.error("Error fetching role data:", error);
      toast.error("Failed to fetch role data.");
    }
  };

  // -------------------- Validation --------------------
  const isValidRoleName = (name) => {
    const parts = name.trim().split(" ");
    return parts.length > 0 && parts.every((word) => /^[A-Za-z]+$/.test(word));
  };

  // -------------------- Role Save --------------------
  const handleRoleSave = useCallback(async () => {
    if (!isValidRoleName(roleName)) {
      toast.warning(
        "Role name must contain only letters and a single space between words."
      );
      return;
    }

    const payload = buildRolePayload(roleData, permissions, roleName, viewType);

    try {
      const savedRoleId = await saveRole(payload);
      if (savedRoleId) {
        toast.success(
          roleData?.RoleId || roleData?.Role_Id
            ? "Role has been updated successfully!"
            : "Role has been created successfully!"
        );
        setShowPermissions(true);
        setRoleId(savedRoleId);
        await fetchRoleData(savedRoleId);
      } else {
        toast.error("Something went wrong. Please try again.");
        onClose();
      }
    } catch (error) {
      console.error("Error saving role:", error);
      toast.error("Failed to create or update role. Please try again.");
    }
  }, [roleName, roleData, permissions, viewType, onSave, onClose]);

  const buildRolePayload = (roleData, permissions, roleName, viewType) => [
    {
      RoleId: roleData?.RoleId || roleData?.Role_Id || 0,
      Permissions:
        roleData?.RoleId || roleData?.Role_Id
          ? formatPermissions(permissions)
          : [{ FeatureSubId: "", PermissionId: "" }],
      RoleName: roleName,
      ViewType: Number.parseInt(viewType || UserRoleHeirarchy[2].key),
      IsActive: true,
      IsDeleted: false,
    },
  ];

  const saveRole = async (payload) => onSave(payload, saveType.Save);

  // -------------------- Permissions --------------------
  const handlePermissionChange = (moduleIndex, permissionId) => {
    setPermissions((prev) => {
      const updated = [...prev];
      updated[moduleIndex].selectedPermission = permissionId;
      return updated;
    });
  };

  const handlePermissionSave = async () => {
    const updatedRoleId = roleData?.Role_Id || roleData?.RoleId || roleId;
    const payload = buildRolePayload(roleData, permissions, roleName, viewType);

    try {
      const response = await onSave(payload, saveType.Update);
      if (response) toast.success("Permissions have been updated successfully!");
      else toast.error("Failed to update permissions. Please try again.");

      await fetchRoleData(updatedRoleId);
      onClose();
    } catch (error) {
      console.error("Error updating permissions:", error);
      toast.error("Failed to update permissions. Please try again.");
    }
  };

  // -------------------- Delete Role --------------------
  const handleCloseConsentPopup = () => setActionType(null);

  const handleConfirmConsentPopup = async () => {
    const payload = {
      SearchText: null,
      PageSize: 0,
      PageNumber: 0,
      IgnorePaging: true,
      Filter: {
        RoleId: editRoleData.Role_Id,
        RepRoleId: newRoleId || 0,
      },
      SortOrder: null,
      SortColumn: null,
    };
    try {
      const response = await postApi(deleteRole, payload);
      toast.success(response?.Records?.[0]?.Message || "Role deleted successfully!");
      getRoleTable({});
      getAllRoles();
      setActionType(null);
    } catch (error) {
      console.error("Error deleting role:", error);
    }
  };

  // -------------------- Render --------------------
  if (!open) return null;

  if (actionType === "delete") {
    return (
      <DeletePopup
        totalAccessUsers={totalAccessUsers}
        roleName={roleName}
        handleClose={handleCloseConsentPopup}
        handleConfirm={handleConfirmConsentPopup}
        editRoleData={editRoleData}
        setNewRoleId={setNewRoleId}
        allRoles={allRoles}
      />
    );
  }

  if (actionType === "addEdit") {
    return (
      <CreateEditRoleDialog
        open={open}
        onClose={onClose}
        roleData={roleData}
        showPermissions={showPermissions}
        roleName={roleName}
        handleRoleSave={handleRoleSave}
        viewType={viewType}
        oldViewtype={oldViewtype}
        setRoleName={setRoleName}
        setViewType={setViewType}
        permissions={permissions}
        handlePermissionSave={handlePermissionSave}
        handlePermissionChange={handlePermissionChange}
        setShowPermissions={setShowPermissions}
      />
    );
  }

  return null;
}


export default ManageRolesPermissionsPopup;

ManageRolesPermissionsPopup.propTypes = {
  open: PropTypes.bool.isRequired,
  onClose: PropTypes.func.isRequired,
  onSave: PropTypes.func.isRequired,
  getRoleData: PropTypes.func.isRequired,
  roleData: PropTypes.shape({
    RoleId: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
    Role_Id: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
    RoleName: PropTypes.string,
    ViewType: PropTypes.string,
  }),
  allModules: PropTypes.arrayOf(
    PropTypes.shape({
      Id: PropTypes.oneOfType([PropTypes.string, PropTypes.number]).isRequired,
      Name: PropTypes.string.isRequired,
    })
  ),
  actionType: PropTypes.string,
  setActionType: PropTypes.func,
  editRoleData: PropTypes.shape({
    Role_Id: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
    RoleName: PropTypes.string,
  }),
  getRoleTable: PropTypes.func,
  getAllRoles: PropTypes.func,
  allRoles: PropTypes.arrayOf(
    PropTypes.shape({
      RoleId: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
      RoleName: PropTypes.string,
      ViewType: PropTypes.string,
    })
  ),
};



