import React, { useEffect, useState, useMemo, useCallback } from "react";
import moment from "moment";
import Avatar from "../common/Avatar";
import { convertShortTime } from "../../utils/dateUtils";
import RenderAttendanceStatus from "./RenderAttendanceStatus";
import { useSelector, useDispatch } from "react-redux";
import { fetchAttendanceData, setAttendanceData } from "../../slices/apiSlice/attedanceLogsSlice"; // Make sure setAttendanceData is correctly imported
import DateRangePicker from "../common/DateRangePicker";
import eventBus from "../../services/eventBus";

// Custom hook for pagination
const usePagination = (data, itemsPerPage) => {
  const [currentPage, setCurrentPage] = useState(1);
  // Ensure data is an array before accessing length
  const totalItems = Array.isArray(data) ? data.length : 0;
  const maxPage = Math.ceil(totalItems / itemsPerPage);

  const currentItems = useMemo(() => {
    if (!Array.isArray(data) || data.length === 0) {
      return [];
    }
    const startIndex = (currentPage - 1) * itemsPerPage;
    const endIndex = startIndex + itemsPerPage;
    return data.slice(startIndex, endIndex);
  }, [data, currentPage, itemsPerPage]);

  const paginate = useCallback((pageNumber) => {
    if (pageNumber > 0 && pageNumber <= maxPage) {
      setCurrentPage(pageNumber);
    }
  }, [maxPage]);

  const resetPage = useCallback(() => setCurrentPage(1), []);

  return {
    currentPage,
    totalPages: maxPage,
    currentItems,
    paginate,
    resetPage,
  };
};

const AttendanceLog = ({
  handleModalData,
  projectId,
  setshowOnlyCheckout,
  showOnlyCheckout,
  searchQuery,
}) => {
  const selectedProject = useSelector(
    (store) => store.localVariables.projectId
  );
  // Initialize date range with sensible defaults, e.g., last 7 days or current day
  const defaultEndDate = moment().format("YYYY-MM-DD");
  const defaultStartDate = moment().subtract(6, 'days').format("YYYY-MM-DD"); // Last 7 days including today

  const [dateRange, setDateRange] = useState({ 
    startDate: defaultStartDate, 
    endDate: defaultEndDate 
  });
  const dispatch = useDispatch();

  const { data: attendanceLogsData, loading: logsLoading, isFetching: logsFetching } = useSelector(
    (state) => state.attendanceLogs
  );

  const [isRefreshing, setIsRefreshing] = useState(false); // Local state for refresh spinner

  // Memoize today and yesterday dates to prevent re-creation on every render
  const today = useMemo(() => {
    const d = new Date();
    d.setHours(0, 0, 0, 0);
    return d;
  }, []);

  const yesterday = useMemo(() => {
    const d = new Date();
    d.setDate(d.getDate() - 1);
    d.setHours(0, 0, 0, 0); // Set to start of day for accurate comparison
    return d;
  }, []);

  const isSameDay = useCallback((dateStr) => {
    if (!dateStr) return false;
    const d = new Date(dateStr);
    d.setHours(0, 0, 0, 0);
    return d.getTime() === today.getTime();
  }, [today]);

  const isBeforeToday = useCallback((dateStr) => {
    if (!dateStr) return false;
    const d = new Date(dateStr);
    d.setHours(0, 0, 0, 0);
    return d.getTime() < today.getTime();
  }, [today]);

  const sortByName = useCallback((a, b) => {
    const nameA = `${a.firstName || ""} ${a.lastName || ""}`.toLowerCase();
    const nameB = `${b.firstName || ""} ${b.lastName || ""}`.toLowerCase();
    return nameA.localeCompare(nameB);
  }, []);

  // Effect to fetch attendance data when dateRange or projectId changes, or when refreshed
  useEffect(() => {
    const { startDate, endDate } = dateRange;
    dispatch(
      fetchAttendanceData({
        projectId,
        fromDate: startDate,
        toDate: endDate,
      })
    );
    // Reset refreshing state only after the dispatch, assuming fetchAttendanceData
    // will eventually update logsLoading/logsFetching
    const timer = setTimeout(() => { // Give Redux time to update
      setIsRefreshing(false);
    }, 500); // Small delay to show spinner for a bit longer

    return () => clearTimeout(timer);
  }, [dateRange, projectId, dispatch, isRefreshing]);

  const processedData = useMemo(() => {
    let filteredData = showOnlyCheckout
      ? (attendanceLogsData || []).filter((item) => item.checkOutTime === null) // Ensure attendanceLogsData is an array
      : (attendanceLogsData || []); // Ensure attendanceLogsData is an array

    // Apply search query filter
    if (searchQuery) {
      const lowerCaseSearchQuery = searchQuery.toLowerCase();
      filteredData = filteredData.filter((att) => {
        const fullName = [att.firstName, att.middleName, att.lastName]
          .filter(Boolean)
          .join(" ")
          .toLowerCase();

        return (
          att.employeeName?.toLowerCase().includes(lowerCaseSearchQuery) ||
          att.employeeId?.toLowerCase().includes(lowerCaseSearchQuery) ||
          fullName.includes(lowerCaseSearchQuery)
        );
      });
    }

    // Grouping and sorting logic remains mostly the same, ensuring 'filteredData' is used
    const group1 = filteredData
      .filter((d) => d.activity === 1 && isSameDay(d.checkInTime))
      .sort(sortByName);
    const group2 = filteredData
      .filter((d) => d.activity === 4 && isSameDay(d.checkOutTime))
      .sort(sortByName);
    const group3 = filteredData
      .filter((d) => d.activity === 1 && isBeforeToday(d.checkInTime))
      .sort(sortByName);
    const group4 = filteredData.filter(
      (d) => d.activity === 4 && isBeforeToday(d.checkOutTime)
    );
    const group5 = filteredData
      .filter((d) => d.activity === 2 && isBeforeToday(d.checkOutTime))
      .sort(sortByName);
    const group6 = filteredData
      .filter((d) => d.activity === 5)
      .sort(sortByName);

    const sortedList = [
      ...group1,
      ...group2,
      ...group3,
      ...group4,
      ...group5,
      ...group6,
    ];

    // Group by date
    const groupedByDate = sortedList.reduce((acc, item) => {
      // Use checkInTime for activity 1, and checkOutTime for others or if checkInTime is null
      const dateString = item.activity === 1 ? item.checkInTime : item.checkOutTime;
      const date = dateString ? moment(dateString).format("YYYY-MM-DD") : null;

      if (date) {
        acc[date] = acc[date] || [];
        acc[date].push(item);
      }
      return acc;
    }, {});

    const sortedDates = Object.keys(groupedByDate).sort(
      (a, b) => new Date(b) - new Date(a)
    );

    // Create the final sorted array
    return sortedDates.flatMap((date) => groupedByDate[date]);
  }, [attendanceLogsData, showOnlyCheckout, searchQuery, isSameDay, isBeforeToday, sortByName]);

  const {
    currentPage,
    totalPages,
    currentItems: paginatedAttendances,
    paginate,
    resetPage,
  } = usePagination(processedData, 20);

  // Effect to reset pagination when search query or showOnlyCheckout changes
  useEffect(() => {
    resetPage();
  }, [searchQuery, showOnlyCheckout, resetPage]);

  // Handler for 'attendance_log' event from eventBus
  // This will now trigger a re-fetch of data
  const handler = useCallback(
    (msg) => {
      // Check if the event is relevant to the current project and date range
      const { startDate, endDate } = dateRange;
      const eventDate = (msg.response.checkInTime || msg.response.checkOutTime)?.substring(0, 10);

      // Only refetch if the event relates to the currently viewed project and date range
      if (
        projectId === msg.projectId &&
        eventDate &&
        eventDate >= startDate && // Ensure eventDate is within the current range
        eventDate <= endDate
      ) {
        // Trigger a re-fetch of attendance data to get the latest state
        dispatch(
          fetchAttendanceData({
            projectId,
            fromDate: startDate,
            toDate: endDate,
          })
        );
      }
    },
    [projectId, dateRange, dispatch]
  );


  useEffect(() => {
    eventBus.on("attendance_log", handler);
    return () => eventBus.off("attendance_log", handler);
  }, [handler]);

  // Handler for 'employee' event from eventBus (already triggers a refetch)
  const employeeHandler = useCallback(
    (msg) => {
      const { startDate, endDate } = dateRange;
      dispatch(
        fetchAttendanceData({
          projectId,
          fromDate: startDate,
          toDate: endDate,
        })
      );
    },
    [projectId, dateRange, dispatch]
  );

  useEffect(() => {
    eventBus.on("employee", employeeHandler);
    return () => eventBus.off("employee", employeeHandler);
  }, [employeeHandler]);

  const handleRefreshClick = () => {
    setIsRefreshing(true); // Set refreshing state to true
    // The useEffect for fetching data will automatically trigger due to isRefreshing dependency
  };

  return (
    <>
      <div
        className="dataTables_length text-start py-2 d-flex justify-content-between"
        id="DataTables_Table_0_length"
      >
        <div className="d-flex align-items-center my-0 ">
          <DateRangePicker
            onRangeChange={setDateRange}
            defaultStartDate={yesterday.toLocaleDateString("en-CA")} // Pass default as string YYYY-MM-DD
          />
          <div className="form-check form-switch text-start m-0 ms-5">
            <input
              type="checkbox"
              className="form-check-input"
              role="switch"
              disabled={logsFetching}
              id="inactiveEmployeesCheckbox"
              checked={showOnlyCheckout}
              onChange={(e) => setshowOnlyCheckout(e.target.checked)}
            />
            <label className="form-check-label ms-0">Show Pending</label>
          </div>
        </div>
        <div className="col-md-2 m-0 text-end">
          <i
            className={`bx bx-refresh cursor-pointer fs-4 ${logsLoading || isRefreshing ? "spin" : ""
              }`}
            title="Refresh"
            onClick={handleRefreshClick}
          />
        </div>
      </div>
      <div
        className="table-responsive text-nowrap"
        style={{ minHeight: "200px", display: 'flex' }}
      >
        {/* Conditional rendering for loading state */}
        {(logsLoading || isRefreshing) ? (
          <div className="d-flex justify-content-center align-items-center text-muted w-100">
            Loading...
          </div>
        ) : processedData && processedData.length > 0 ? (
          <table className="table mb-0">
            <thead>
              <tr>
                <th className="border-top-1" colSpan={2}>
                  Name
                </th>
                <th className="border-top-1">Date</th>
                <th>
                  <i className="bx bxs-down-arrow-alt text-success"></i>{" "}
                  Check-In
                </th>
                <th>
                  <i className="bx bxs-up-arrow-alt text-danger"></i> Check-Out
                </th>
                <th>Action</th>
              </tr>
            </thead>
            <tbody>
              {paginatedAttendances.reduce((acc, attendance, index, arr) => {
                const currentDate = moment(
                  attendance.checkInTime || attendance.checkOutTime
                ).format("YYYY-MM-DD");
                const previousAttendance = arr[index - 1];
                const previousDate = previousAttendance
                  ? moment(
                    previousAttendance.checkInTime ||
                    previousAttendance.checkOutTime
                  ).format("YYYY-MM-DD")
                  : null;

                if (!previousDate || currentDate !== previousDate) {
                  acc.push(
                    <tr
                      key={`header-${currentDate}`}
                      className="table-row-header"
                    >
                      <td colSpan={6} className="text-start">
                        <strong>
                          {moment(currentDate).format("DD-MM-YYYY")}
                        </strong>
                      </td>
                    </tr>
                  );
                }
                acc.push(
                  <tr key={attendance.id || index}>
                    <td colSpan={2}>
                      <div className="d-flex justify-content-start align-items-center">
                        <Avatar
                          firstName={attendance.firstName}
                          lastName={attendance.lastName}
                        />
                        <div className="d-flex flex-column">
                          <a href="#" className="text-heading text-truncate">
                            <span className="fw-normal">
                              {attendance.firstName} {attendance.lastName}
                            </span>
                          </a>
                        </div>
                      </div>
                    </td>
                    <td>
                      {moment(
                        attendance.checkInTime || attendance.checkOutTime
                      ).format("DD-MMM-YYYY")}
                    </td>
                    <td>{convertShortTime(attendance.checkInTime)}</td>
                    <td>
                      {attendance.checkOutTime
                        ? convertShortTime(attendance.checkOutTime)
                        : "--"}
                    </td>
                    <td className="text-center">
                      <RenderAttendanceStatus
                        attendanceData={attendance}
                        handleModalData={handleModalData}
                        Tab={2}
                        currentDate={today.toLocaleDateString("en-CA")}
                      />
                    </td>
                  </tr>
                );
                return acc;
              }, [])}
            </tbody>
          </table>
        ) : (
          <div
            className="d-flex justify-content-center align-items-center text-muted w-100"
            style={{ height: "200px" }} // Added height for better visual during no data
          >
            No employee logs.
          </div>
        )}
      </div>
      {!logsLoading && !isRefreshing && processedData.length > 20 && (
        <nav aria-label="Page ">
          <ul className="pagination pagination-sm justify-content-end py-1">
            <li className={`page-item ${currentPage === 1 ? "disabled" : ""}`}>
              <button
                className="page-link btn-xs"
                onClick={() => paginate(currentPage - 1)}
              >
                &laquo;
              </button>
            </li>
            {Array.from({ length: totalPages }, (_, i) => i + 1).map(
              (pageNumber) => (
                <li
                  key={pageNumber}
                  className={`page-item ${currentPage === pageNumber ? "active" : ""
                    }`}
                >
                  <button
                    className="page-link"
                    onClick={() => paginate(pageNumber)}
                  >
                    {pageNumber}
                  </button>
                </li>
              )
            )}
            <li
              className={`page-item ${currentPage === totalPages ? "disabled" : ""
                }`}
            >
              <button
                className="page-link"
                onClick={() => paginate(currentPage + 1)}
              >
                &raquo;
              </button>
            </li>
          </ul>
        </nav>
      )}
    </>
  );
};

export default AttendanceLog; 