import { useEffect, useState, useRef } from "react";
import BASE_URL from "@backend/server/config";
import axiosInstance from "../../utils/axiosInstance";
import Swal from "sweetalert2";
import {
  Card,
  CardContent,
  Typography,
  Checkbox,
  Divider,
  FormControl,
  InputLabel,
  Select,
  MenuItem,
  Button,
} from "@mui/material";
import {
  Trash2,
  Search,
  LayoutGrid,
  Clock3,
  CheckCircle2,
  XCircle,
} from "lucide-react";
import StatusSummary from "../../admin_Late_request/components/commons/statusSummaryLateAtt";
import AttendanceRequestActions from "../../admin_Late_request/components/commons/requestActionButton";
import { useSession } from "../../../context/SessionContext";
import usePermissions from "../../../users/hooks/usePermissions";
import { usePendingCounts } from "../../../context/PendingCountsContext";
import { exportRequestsXLSX } from "../../../utils/exportRequestsXLSX";

const OvertimeRequest = () => {
  const { user } = useSession();
  const { permissions, loading: permLoading } = usePermissions(user?.username);
  const [overtimeRequests, setOvertimeRequests] = useState([]);
  const [loading, setLoading] = useState(true);
  const [statusFilter, setStatusFilter] = useState("Pending");
  const [sortAscending, setSortAscending] = useState(true);
  const [selectedRequests, setSelectedRequests] = useState(new Set());
  const [searchQuery, setSearchQuery] = useState("");
  const [selectedBulkStatus, setSelectedBulkStatus] = useState("pending");
  const [isApplyingBulk, setIsApplyingBulk] = useState(false);
  const [viewArchived, setViewArchived] = useState(false);
  const [currentPage, setCurrentPage] = useState(1);
  const itemsPerPage = 12;
  const REQUESTS_UPDATED_EVENT = "requests:updated";

  const { counts } = usePendingCounts();
  const prevOvertimePending = useRef(counts?.overtimePending);

  useEffect(() => {
    setCurrentPage(1);
  }, [viewArchived, searchQuery, statusFilter]);

  useEffect(() => {
    if (counts && prevOvertimePending.current !== undefined) {
      if (counts.overtimePending !== prevOvertimePending.current) {
        fetchOvertimeRequests();
      }
    }
    prevOvertimePending.current = counts?.overtimePending;
  }, [counts?.overtimePending]);

  const fetchOvertimeRequests = async () => {
    setLoading(true);
    try {
      const endpoint = viewArchived ? "get_archived_overtime" : "overtime_request";
      const response = await axiosInstance.get(`${BASE_URL}/api/overtime/${endpoint}`);
      const data = response.data;
      if (data.success) {
        setOvertimeRequests(data.data);
      } else {
        console.error("Failed to fetch overtime requests");
        setOvertimeRequests([]);
      }
    } catch (error) {
      console.error("Error fetching overtime requests:", error);
      setOvertimeRequests([]);
    } finally {
      setLoading(false);
    }
  };

  useEffect(() => {
    fetchOvertimeRequests();
  }, [viewArchived]);

  const handleExportArchive = async () => {
    try {
      const response = await axiosInstance.get(
        `${BASE_URL}/api/overtime/export_overtime_archive`,
        { responseType: "text" }
      );
      await exportRequestsXLSX(response.data, "archived_overtime_requests.xlsx", "Archived Overtime Requests");
    } catch (err) {
      console.error(err);
      Swal.fire({ icon: "error", title: "Export Failed" });
    }
  };

  const handleExportActive = async () => {
    try {
      const response = await axiosInstance.get(
        `${BASE_URL}/api/overtime/export_active_overtime`,
        { responseType: "text" }
      );
      await exportRequestsXLSX(response.data, "active_overtime_requests.xlsx", "Active Overtime Requests");
    } catch (err) {
      console.error(err);
      Swal.fire({ icon: "error", title: "Export Failed" });
    }
  };

  const updateStatus = async (
    id,
    newStatus,
    { silent = false, skipRefresh = false } = {},
  ) => {
    try {
      const formData = new URLSearchParams({
        id,
        status: newStatus,
        approved_by: newStatus === "Approved" ? "Admin" : "Not approved yet",
      });
      const response = await axiosInstance.post(
        `${BASE_URL}/api/overtime/edit_overtime_request`,
        formData.toString(),
        { headers: { "Content-Type": "application/x-www-form-urlencoded" } },
      );
      const data = response.data;
      if (data.success) {
        if (!silent) {
          Swal.fire({
            icon: "success",
            title: "Status updated successfully!",
            showConfirmButton: false,
            timer: 1500,
          });
        }
        if (!skipRefresh) {
          fetchOvertimeRequests();
        }
        window.dispatchEvent(new CustomEvent(REQUESTS_UPDATED_EVENT));
      } else {
        if (!silent) {
          Swal.fire({
            icon: "error",
            title: "Failed to update status",
            text: data.message,
          });
        }
        return { success: false, message: data.message };
      }
      return { success: true };
    } catch (error) {
      console.error("Error updating status:", error);
      if (!silent) {
        Swal.fire({
          icon: "error",
          title: "Error updating status",
          text: "An unexpected error occurred!",
        });
      }
      return { success: false, message: error?.message || "Unexpected error" };
    }
  };

  const applyBulkStatus = async () => {
    if (selectedRequests.size === 0) {
      Swal.fire({
        icon: "warning",
        title: "No selection",
        text: "Select requests first",
        timer: 1500,
        showConfirmButton: false,
      });
      return;
    }

    setIsApplyingBulk(true);
    try {
      const ids = Array.from(selectedRequests);
      // Single bulk request instead of N individual requests
      const response = await axiosInstance.post(
        `${BASE_URL}/api/overtime/bulk_update_overtime_status`,
        { request_ids: ids, status: selectedBulkStatus },
      );
      const data = response.data;

      if (data.failed > 0) {
        Swal.fire("Partial update", `${data.updated} updated, ${data.failed} failed.`, "warning");
      } else {
        Swal.fire({ icon: "success", title: "Updated", showConfirmButton: false, timer: 1500 });
      }

      setSelectedRequests(new Set());
      await fetchOvertimeRequests();
      window.dispatchEvent(new CustomEvent(REQUESTS_UPDATED_EVENT));
    } catch (error) {
      Swal.fire({
        icon: "error",
        title: "Error",
        text: error?.message || "Failed to update selected requests.",
      });
    } finally {
      setIsApplyingBulk(false);
    }
  };

  const filteredAndSortedRequests = () => {
    const normalizedQuery = searchQuery.trim().toLowerCase();

    const matchesSearch = (req) => {
      if (!normalizedQuery) return true;

      const requestDate = new Date(req.date_requested);
      const isoDate = isNaN(requestDate)
        ? ""
        : requestDate.toISOString().split("T")[0];
      const displayDate = isNaN(requestDate)
        ? ""
        : requestDate.toLocaleDateString("en-US", {
          year: "numeric",
          month: "long",
          day: "numeric",
        });

      const safeQuery = normalizedQuery.replace(/\s+/g, " ").trim();
      const queryWords = safeQuery ? safeQuery.split(" ") : [];

      const haystack = [
        req.employee_name,
        req.employee_id,
        req.request_id,
        req.attendance_id,
        req.date_requested,
        isoDate,
        displayDate,
      ]
        .filter(Boolean)
        .join(" ")
        .toLowerCase()
        .replace(/\s+/g, " ");

      return queryWords.length === 0 || queryWords.every(word => haystack.includes(word));
    };

    return overtimeRequests
      .filter((req) =>
        statusFilter === "All" ? true : req.status === statusFilter,
      )
      .filter(matchesSearch)
      .sort((a, b) =>
        sortAscending
          ? new Date(a.date_requested) - new Date(b.date_requested)
          : new Date(b.date_requested) - new Date(a.date_requested),
      );
  };

  const visibleRequests = filteredAndSortedRequests();
  const paginatedRequests = viewArchived
    ? visibleRequests.slice((currentPage - 1) * itemsPerPage, currentPage * itemsPerPage)
    : visibleRequests;

  const handleSelectAll = (e) => {
    if (e.target.checked) {
      setSelectedRequests(new Set(paginatedRequests.map((r) => r.request_id)));
    } else {
      setSelectedRequests(new Set());
    }
  };

  const handleSelectRequest = (id) => {
    const updated = new Set(selectedRequests);
    updated.has(id) ? updated.delete(id) : updated.add(id);
    setSelectedRequests(updated);
  };

  const handleDeleteSelected = async () => {
    const confirmed = await Swal.fire({
      title: "Are you sure?",
      text: "This will delete all selected requests!",
      icon: "warning",
      showCancelButton: true,
      confirmButtonText: "Yes, delete them!",
    });
    if (confirmed.isConfirmed) {
      try {
        const ids = Array.from(selectedRequests);
        // Single bulk request instead of N individual DELETE requests
        const response = await axiosInstance.post(
          `${BASE_URL}/api/overtime/bulk_delete_overtime_requests`,
          { request_ids: ids },
        );
        const data = response.data;
        if (data.success) {
          Swal.fire({
            icon: "success",
            title: `${data.deleted} request(s) deleted!`,
            showConfirmButton: false,
            timer: 1500,
          });
        } else {
          Swal.fire({ icon: "error", title: "Error", text: "Failed to delete requests: " + data.message });
        }
      } catch (error) {
        console.error(error);
        Swal.fire({ icon: "error", title: "Error deleting requests" });
      } finally {
        setSelectedRequests(new Set());
        fetchOvertimeRequests();
        window.dispatchEvent(new CustomEvent(REQUESTS_UPDATED_EVENT));
      }
    }
  };

  const countRequestsByStatus = () => {
    const counts = { Pending: 0, Approved: 0, Rejected: 0 };
    overtimeRequests.forEach((r) => {
      if (r.status in counts) counts[r.status]++;
    });
    return counts;
  };

  const requestCounts = countRequestsByStatus();

  if (loading) return <div>Loading...</div>;

  return (
    <div className="flex flex-col w-full h-full px-4 py-8 my-1">
      <div className="flex justify-end items-center mb-4 space-x-4">
        <button
          onClick={() => setViewArchived(!viewArchived)}
          className="shrink-0 whitespace-nowrap inline-flex items-center gap-1.5 px-3 py-2 rounded-lg text-sm font-semibold bg-slate-50 text-slate-700 border border-slate-200 hover:bg-slate-600 hover:text-white hover:border-slate-600 transition-all duration-200 shadow-sm"
        >
          {viewArchived ? "Back to Active Requests" : "View Archived Requests"}
        </button>
        <button
          onClick={viewArchived ? handleExportArchive : handleExportActive}
          className="shrink-0 whitespace-nowrap inline-flex items-center gap-1.5 px-3 py-2 rounded-lg text-sm font-semibold bg-emerald-50 text-emerald-700 border border-emerald-200 hover:bg-emerald-600 hover:text-white hover:border-emerald-600 transition-all duration-200 shadow-sm disabled:opacity-50 disabled:cursor-default"
        >
          {viewArchived ? "Export Audit Log" : "Export Active Logs"}
        </button>
      </div>

      <StatusSummary
        counts={{ ...requestCounts, Total: Object.values(requestCounts).reduce((a, b) => a + b, 0) }}
        activeStatus={statusFilter}
        onSelectStatus={setStatusFilter}
        isArchived={viewArchived}
      />

      <AttendanceRequestActions
        onSelectAll={handleSelectAll}
        isAllSelected={
          paginatedRequests.length > 0 &&
          selectedRequests.size === paginatedRequests.length
        }
        isPartiallySelected={
          selectedRequests.size > 0 &&
          selectedRequests.size < paginatedRequests.length
        }
        onDeleteSelected={handleDeleteSelected}
        isDeleteDisabled={selectedRequests.size === 0}
        sortAscending={sortAscending}
        onToggleSort={setSortAscending}
        selectedBulkStatus={selectedBulkStatus}
        onBulkStatusChange={setSelectedBulkStatus}
        onApplyBulkStatus={applyBulkStatus}
        isApplyDisabled={selectedRequests.size === 0 || isApplyingBulk}
        searchQuery={searchQuery}
        onSearchQueryChange={setSearchQuery}
        isArchived={viewArchived}
      />


      <div className="max-h-[62vh] overflow-y-auto pr-1">
        <div className="flex flex-wrap gap-4 justify-center sm:justify-start">
          {visibleRequests.length === 0 ? (
            <div className="w-full text-center italic text-gray-500">
              No overtime requests found for{" "}
              <span className="font-semibold">{statusFilter}</span>
              {searchQuery.trim() ? (
                <>
                  {" "}
                  matching{" "}
                  <span className="font-semibold">
                    &quot;{searchQuery.trim()}&quot;
                  </span>
                </>
              ) : null}
              .
            </div>
          ) : (
            paginatedRequests.map((r) => (
              <Card
                key={r.request_id}
                sx={{
                  width: 335,
                  backgroundColor:
                    r.status === "Approved"
                      ? "#e9f7ef"
                      : r.status === "Rejected"
                        ? "#fdecea"
                        : "#fffde7",
                }}
              >
                <CardContent className="p-3">
                  <div className="flex items-center mb-2">
                    {!viewArchived && (
                      <Checkbox
                        checked={selectedRequests.has(r.request_id)}
                        onChange={() => handleSelectRequest(r.request_id)}
                        size="small"
                      />
                    )}
                    <strong>{r.employee_name}</strong>
                    <span
                      className={`ml-2 w-3 h-3 rounded-full ${r.status === "Approved"
                        ? "bg-green-500"
                        : r.status === "Rejected"
                          ? "bg-red-500"
                          : "bg-yellow-500"
                        }`}
                    />
                  </div>

                  <Typography variant="body2" color="text.secondary">
                    ID: <strong>{r.employee_id}</strong>
                  </Typography>
                  <Typography
                    variant="body2"
                    color="text.secondary"
                    className="wrap-break-word whitespace-pre-wrap"
                  >
                    Reason: <strong>{r.reason || "No reason provided"}</strong>
                  </Typography>

                  <Divider sx={{ my: 1 }} />

                  <Typography variant="body2" color="text.secondary">
                    Request Date:{" "}
                    <strong>
                      {new Date(r.date_requested).toLocaleDateString("en-US", {
                        year: "numeric",
                        month: "long",
                        day: "numeric",
                      })}
                    </strong>
                  </Typography>

                  <Typography variant="body2" color="text.secondary">
                    Time start:{" "}
                    <strong>
                      {new Date(
                        `1970-01-01T${r.time_start}`,
                      ).toLocaleTimeString([], {
                        hour: "numeric",
                        minute: "2-digit",
                      })}{" "}
                      | Time end:{" "}
                      {new Date(`1970-01-01T${r.end_time}`).toLocaleTimeString(
                        [],
                        { hour: "numeric", minute: "2-digit" },
                      )}
                    </strong>
                  </Typography>

                  <Typography variant="body2" color="text.secondary">
                    OT Credit Days:{" "}
                    <strong>
                      {r.overtime_credit ?? r.hours_requested} |{" "}
                      {r.minutes_requested ?? 0} min
                    </strong>
                  </Typography>

                  <Typography variant="body2" color="text.secondary">
                    OT Amount:{" "}
                    <strong>
                      PHP{" "}
                      {Number(r.overtime_amount ?? 0).toLocaleString("en-PH", {
                        minimumFractionDigits: 2,
                        maximumFractionDigits: 2,
                      })}
                    </strong>
                  </Typography>

                  {/* Status control moved to top toolbar (bulk apply). */}
                </CardContent>
              </Card>
            ))
          )}
        </div>

        {viewArchived && Math.ceil(visibleRequests.length / itemsPerPage) > 1 && (
          <div className="flex justify-center items-center space-x-2 mt-8 mb-4">
            <button
              onClick={() => setCurrentPage((prev) => Math.max(prev - 1, 1))}
              disabled={currentPage === 1}
              className={`px-3 py-1 rounded border ${currentPage === 1 ? "text-gray-400 border-gray-200 cursor-default" : "text-blue-600 border-blue-600 hover:bg-blue-50"}`}
            >
              Previous
            </button>
            <span className="text-gray-700 px-4 py-1">
              Page {currentPage} of {Math.ceil(visibleRequests.length / itemsPerPage)}
            </span>
            <button
              onClick={() => setCurrentPage((prev) => Math.min(prev + 1, Math.ceil(visibleRequests.length / itemsPerPage)))}
              disabled={currentPage === Math.ceil(visibleRequests.length / itemsPerPage)}
              className={`px-3 py-1 rounded border ${currentPage === Math.ceil(visibleRequests.length / itemsPerPage) ? "text-gray-400 border-gray-200 cursor-default" : "text-blue-600 border-blue-600 hover:bg-blue-50"}`}
            >
              Next
            </button>
          </div>
        )}
      </div>
    </div>
  );
};

export default OvertimeRequest;
