import React, { useEffect, useState } from "react";
import IconButton from "../common/IconButton";
import { useForm } from "react-hook-form";
import { zodResolver } from "@hookform/resolvers/zod";
import { bucketScheam } from "./DirectorySchema";
import showToast from "../../services/toastService";
import Directory from "../../pages/Directory/Directory";
import { DirectoryRepository } from "../../repositories/DirectoryRepository";
import { cacheData, getCachedData } from "../../slices/apiDataManager";
import { useBuckets } from "../../hooks/useDirectory";
import EmployeeList from "./EmployeeList";
import { useAllEmployees, useEmployees } from "../../hooks/useEmployees";
import { useSortableData } from "../../hooks/useSortableData";
import ConfirmModal from "../common/ConfirmModal";
import { useHasUserPermission } from "../../hooks/useHasUserPermission";
import { DIRECTORY_ADMIN, DIRECTORY_MANAGER } from "../../utils/constants";
import { useProfile } from "../../hooks/useProfile";

const ManageBucket = () => {
  const { profile } = useProfile();
  const [bucketList, setBucketList] = useState([]);
  const { employeesList } = useAllEmployees(false);
  const [selectedEmployee, setSelectEmployee] = useState([]);
  const { buckets, loading, refetch } = useBuckets();
  const [action_bucket, setAction_bucket] = useState(false);
  const [isSubmitting, setSubmitting] = useState(false);
  const [selected_bucket, select_bucket] = useState(null);
  const [deleteBucket, setDeleteBucket] = useState(null);
  const [searchTerm, setSearchTerm] = useState("");
  const DirManager = useHasUserPermission(DIRECTORY_MANAGER);
  const DirAdmin = useHasUserPermission(DIRECTORY_ADMIN);
  const {
    items: sortedBuckteList,
    requestSort,
    sortConfig,
  } = useSortableData(bucketList, {
    key: (e) => `${e.name}`,
    direction: "asc",
  });
  const getSortIcon = () => {
    if (!sortConfig) return null;
    return sortConfig.direction === "asc" ? (
      <i className="bx bx-caret-up text-secondary"></i>
    ) : (
      <i className="bx bx-caret-down text-secondary"></i>
    );
  };

  const {
    register,
    handleSubmit,
    reset,
    formState: { errors },
  } = useForm({
    resolver: zodResolver(bucketScheam),
    defaultValues: {
      name: "",
      description: "",
    },
  });

  const onSubmit = async (data) => {
    setSubmitting(true);

    try {
      const cache_buckets = getCachedData("buckets") || [];
      let response;

      const arraysAreEqual = (a, b) => {
        if (a.length !== b.length) return false;
        const setA = new Set(a);
        const setB = new Set(b);
        return [...setA].every((id) => setB.has(id));
      };

      if (selected_bucket) {
        const payload = { ...data, id: selected_bucket.id };

        response = await DirectoryRepository.UpdateBuckets(
          selected_bucket.id,
          payload
        );

        const updatedBuckets = cache_buckets.map((bucket) =>
          bucket.id === selected_bucket.id ? response?.data : bucket
        );

        cacheData("buckets", updatedBuckets);
        setBucketList(updatedBuckets);

        const existingEmployeeIds = selected_bucket?.employeeIds || [];
        const employeesToUpdate = selectedEmployee.filter((emp) => {
          const isExisting = existingEmployeeIds.includes(emp.employeeId);
          return (!isExisting && emp.isActive) || (isExisting && !emp.isActive);
        });

        const newActiveEmployeeIds = selectedEmployee
          .filter((emp) => {
            const isExisting = existingEmployeeIds.includes(emp.employeeId);
            return (
              (!isExisting && emp.isActive) || (isExisting && !emp.isActive)
            );
          })
          .map((emp) => emp.employeeId);

        if (
          !arraysAreEqual(newActiveEmployeeIds, existingEmployeeIds) &&
          employeesToUpdate.length !== 0
        ) {
          try {
            response = await DirectoryRepository.AssignedBuckets(
              selected_bucket.id,
              employeesToUpdate
            );
          } catch (assignError) {
            const assignMessage =
              assignError?.response?.data?.message ||
              assignError?.message ||
              "Error assigning employees.";
            showToast(assignMessage, "error");
          }
        }
        const updatedData = cache_buckets?.map((bucket) =>
          bucket.id === response?.data?.id ? response.data : bucket
        );

        cacheData("buckets", updatedData);

        setBucketList(updatedData);
        showToast("Bucket Updated Successfully", "success");
      } else {
        response = await DirectoryRepository.CreateBuckets(data);

        const updatedBuckets = [...cache_buckets, response?.data];
        cacheData("buckets", updatedBuckets);
        setBucketList(updatedBuckets);

        showToast("Bucket Created Successfully", "success");
      }

      handleBack();
    } catch (error) {
      const message =
        error?.response?.data?.message ||
        error?.message ||
        "Error occurred during API call";
      showToast(message, "error");
    } finally {
      setSubmitting(false);
    }
  };

  const handleDeleteContact = async () => {
    try {
      const resp = await DirectoryRepository.DeleteBucket(deleteBucket);
      const cache_buckets = getCachedData("buckets") || [];
      const updatedBuckets = cache_buckets.filter(
        (bucket) => bucket.id !== deleteBucket
      );
      cacheData("buckets", updatedBuckets);
      setBucketList(updatedBuckets);
      showToast("Bucket deleted successfully", "success");
      setDeleteBucket(null);
    } catch (error) {
      const message =
        error?.response?.data?.message ||
        error?.message ||
        "Error occurred during API call.";
      showToast(message, "error");
    }
  };

  useEffect(() => {
    reset({
      name: selected_bucket?.name || "",
      description: selected_bucket?.description || "",
    });
  }, [selected_bucket]);

  useEffect(() => {
    setBucketList(buckets);
  }, [buckets]);

  const handleBack = () => {
    select_bucket(null);
    setAction_bucket(false);
    setSubmitting(false);
    reset({ name: "", description: "" });
    setSelectEmployee([]);
  };

  const sortedBucktesList = sortedBuckteList?.filter((bucket) => {
    const term = searchTerm?.toLowerCase();
    const name = bucket.name?.toLowerCase();
    return name?.includes(term);
  });

  return (
    <>
      {deleteBucket && (
        <div
          className={`modal fade ${deleteBucket ? "show" : ""}`}
          tabIndex="-1"
          role="dialog"
          style={{
            display: deleteBucket ? "block" : "none",
            backgroundColor: deleteBucket ? "rgba(0,0,0,0.5)" : "transparent",
          }}
        >
          <ConfirmModal
            type={"delete"}
            header={"Delete Bucket"}
            message={"Are you sure you want to delete this bucket?"}
            onSubmit={handleDeleteContact}
            onClose={() => setDeleteBucket(null)}
          />
        </div>
      )}

      <div className="container m-0 p-0" style={{ minHeight: "00px" }}>
        <div className="d-flex justify-content-center">
          <p className="fs-6 fw-semibold m-0">Manage Buckets</p>
        </div>
        <div className="d-flex justify-content-between px-2 px-sm-0 mt-5 mt-3 align-items-center ">
          {action_bucket ? (
            <i
              className={`fa-solid fa-arrow-left fs-5 cursor-pointer`}
              onClick={handleBack}
            ></i>
          ) : (
            <div className="d-flex align-items-center gap-2">
              <input
                type="search"
                className="form-control form-control-sm"
                placeholder="Search Bucket ..."
                value={searchTerm}
                onChange={(e) => setSearchTerm(e.target.value)}
              />
              <i
                className={`bx bx-refresh cursor-pointer fs-4 ${loading ? "spin" : ""
                  }`}
                title="Refresh"
                onClick={() => refetch()}
              />
            </div>
          )}

          <button
            type="button"
            className={`btn btn-sm btn-primary ms-auto ${action_bucket ? "d-none" : ""
              }`}
            onClick={() => {
              setAction_bucket(true);
              select_bucket(null);
              reset({ name: "", description: "" });
              setSelectEmployee([]);
            }}
          >
            <i className="bx bx-plus-circle me-2"></i>
            Add Bucket
          </button>
        </div>
        <div>
          {!action_bucket ? (
            <div className="row row-cols-1 row-cols-md-2 row-cols-lg-3 g-3 pt-3 px-2 px-sm-0">
              {loading && (
                <div className="col-12">
                  <div
                    className="d-flex justify-content-center align-items-center py-5 w-100"
                    style={{ marginLeft: "250px" }}
                  >
                    Loading...
                  </div>
                </div>
              )}

              {!loading && buckets.length === 0 && searchTerm.trim() === "" && (
                <div className="col-12">
                  <div
                    className="d-flex justify-content-center align-items-center py-5 w-100"
                    style={{ marginLeft: "250px" }}
                  >
                    No buckets available.
                  </div>
                </div>
              )}

              {!loading && buckets.length > 0 && sortedBucktesList.length === 0 && (
                <div className="col-12">
                  <div
                    className="d-flex justify-content-center align-items-center py-5 w-100"
                    style={{ marginLeft: "250px" }}
                  >
                    No matching buckets found.
                  </div>
                </div>
              )}
              {!loading &&
                sortedBucktesList.map((bucket) => (
                  <div className="col" key={bucket.id}>
                    <div className="card h-100">
                      <div className="card-body p-4">
                        <h6 className="card-title d-flex justify-content-between align-items-center">
                          <span>{bucket.name}</span>
                          {(DirManager ||
                            DirAdmin ||
                            bucket?.createdBy?.id ===
                            profile?.employeeInfo?.id) && (
                              <div className="d-flex gap-2">
                                <i
                                  className="bx bx-edit bx-sm text-primary cursor-pointer"
                                  onClick={() => {
                                    select_bucket(bucket);
                                    setAction_bucket(true);
                                    const initialSelectedEmployees = employeesList
                                      .filter((emp) =>
                                        bucket.employeeIds?.includes(
                                          emp.employeeId
                                        )
                                      )
                                      .map((emp) => ({ ...emp, isActive: true }));
                                    setSelectEmployee(initialSelectedEmployees);
                                  }}
                                ></i>
                                <i
                                  className="bx bx-trash bx-sm text-danger cursor-pointer ms-0"
                                  onClick={() => setDeleteBucket(bucket?.id)}
                                ></i>
                              </div>
                            )}
                        </h6>
                        <h6 className="card-subtitle mb-2 text-muted  text-start">
                          Contacts:{" "}
                          {bucket.numberOfContacts
                            ? bucket.numberOfContacts
                            : 0}
                        </h6>
                        <p
                          className="card-text text-start"
                          title={bucket.description}
                        >
                          {bucket.description || "No description available."}
                        </p>
                      </div>
                    </div>
                  </div>
                ))}
            </div>
          ) : (
            <>
              <form onSubmit={handleSubmit(onSubmit)} className="px-2 px-sm-0">
                <div className="mb-3">
                  <label htmlFor="bucketName" className="form-label">
                    Bucket Name
                  </label>
                  <input
                    id="bucketName"
                    className="form-control form-control-sm"
                    {...register("name")}
                  />
                  {errors.name && (
                    <small className="danger-text">{errors.name.message}</small>
                  )}
                </div>
                <div className="mb-3">
                  <label htmlFor="bucketDescription" className="form-label">
                    Bucket Description
                  </label>
                  <textarea
                    id="bucketDescription"
                    className="form-control form-control-sm"
                    rows="3"
                    {...register("description")}
                  />
                  {errors.description && (
                    <small className="danger-text">
                      {errors.description.message}
                    </small>
                  )}
                </div>

                {selected_bucket && (
                  <EmployeeList
                    employees={employeesList}
                    onChange={(data) => setSelectEmployee(data)}
                    bucket={selected_bucket}
                  />
                )}

                <div className="mt-4 d-flex justify-content-center gap-3">
                  <button
                    type="button"
                    onClick={handleBack}
                    className="btn btn-sm btn-secondary"
                    disabled={isSubmitting}
                  >
                    Cancel
                  </button>
                  <button
                    type="submit"
                    className="btn btn-sm btn-primary"
                    disabled={isSubmitting}
                  >
                    {isSubmitting ? "Please wait..." : "Submit"}
                  </button>
                </div>
              </form>
            </>
          )}
        </div>
      </div>
    </>
  );
};

export default ManageBucket;
