"use client";

import React, { useEffect, useState, useCallback, useMemo } from "react";
import dynamic from "next/dynamic";
import toast from "react-hot-toast";
import styles from "../../modules/commonstyle/dattabale.module.css";
import {
  AuditScheduleFilters,
  type DatePreset,
  type ClientGroupFilter,
} from "./AuditScheduleFilters";
import { Pagination } from "./Pagination";
import {
  getAuditSchedulesPaginated,
  deleteAuditSchedule,
  updateAuditSchedule,
  getAuditSchedule,
} from "@/lib/api/audit-schedule.api";
import { fetchApi } from "@/lib/api/http";
import { deleteWithConfirm } from "./../../../../components/ConfirmDialog/ConfirmDialog";
import AuditScheduleForm from "./Form/AuditScheduleForm";
import AuditScheduleDetailModal from "./Modals/AuditScheduleDetailModal";
import CancelRowModal from "./Modals/CancelRowModal";
import RescheduleRowModal from "./Modals/RescheduleRowModal";
import BulkCancelModal from "./Modals/BulkCancelModal";
import { mapAuditSchedulesApiResponse } from "@/lib/api/mappers/audit-schedule.mappers";
import type {
  AuditScheduleRow as AuditScheduleRowType,
  AuditSchedule,
  AuditRow,
  ScheduleStatus,
} from "@/lib/api/types/audit-schedule.types";
import { useRouter } from "next/navigation";

const AuditScheduleRowFallback = dynamic(
  () => import("./AuditScheduleRow").then((m) => m.AuditScheduleRow),
  { ssr: false },
);

interface Props {
  refreshFlag?: boolean;
}

// ─── API base (for /modules + /user-permissions) ─────────────────────────
const API_BASE_URL =
  process.env.NEXT_PUBLIC_API_URL || "http://localhost:3007/api";

function useDebounce<T>(value: T, delay: number): T {
  const [debounced, setDebounced] = useState(value);
  useEffect(() => {
    const t = setTimeout(() => setDebounced(value), delay);
    return () => clearTimeout(t);
  }, [value, delay]);
  return debounced;
}

// ─── Delete permission check (mirrors CertificateRow pattern) ────────────
const DELETE_ALLOWED_USER_IDS = [1];
function getCurrentUserId(): number | null {
  if (typeof window === "undefined") return null;
  try {
    const stored = localStorage.getItem("user");
    if (stored) {
      const parsed = JSON.parse(stored);
      const id = parsed?.id ?? parsed?.userId ?? parsed?.user_id;
      if (id != null) return Number(id);
    }
    const token =
      localStorage.getItem("token") ||
      localStorage.getItem("accessToken") ||
      localStorage.getItem("access_token");
    if (token && token.split(".").length === 3) {
      const payload = JSON.parse(atob(token.split(".")[1]));
      const id =
        payload?.id ?? payload?.userId ?? payload?.user_id ?? payload?.sub;
      if (id != null) return Number(id);
    }
  } catch {
    // ignore
  }
  return null;
}

export default function AuditScheduleTable({ refreshFlag }: Props) {
  const router = useRouter();

  // ── Data ────────────────────────────────────────────────────────────────
  const [data, setData] = useState<AuditScheduleRowType[]>([]);
  const [total, setTotal] = useState(0);
  const [lastPage, setLastPage] = useState(1);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState<string | null>(null);

  const [selectedRows, setSelectedRows] = useState<number[]>([]);

  // ── Pagination ──────────────────────────────────────────────────────────
  const [currentPage, setCurrentPage] = useState(1);
  const [itemsPerPage, setItemsPerPage] = useState(10);

  // ── Filters ─────────────────────────────────────────────────────────────
  const [searchTerm, setSearchTerm] = useState("");
  const [statusFilter, setStatusFilter] = useState<ScheduleStatus | "all">(
    "all",
  );
  const [clientGroupFilter, setClientGroupFilter] =
    useState<ClientGroupFilter>("all");
  const [datePreset, setDatePreset] = useState<DatePreset>("all");
  const [customDateFrom, setCustomDateFrom] = useState("");
  const [customDateTo, setCustomDateTo] = useState("");

  const debouncedSearch = useDebounce(searchTerm, 400);

  // ── Modals state ────────────────────────────────────────────────────────
  const [isCreateOpen, setIsCreateOpen] = useState(false);
  const [editingId, setEditingId] = useState<number | null>(null);
  const [detailScheduleId, setDetailScheduleId] = useState<number | null>(null);
  const [detailRefreshFlag, setDetailRefreshFlag] = useState(0);

  // ✅ inline accordion expand state
  //   expandedIds        → which schedule rows are currently expanded
  //   expandedSchedules  → the full AuditSchedule (with rows) per expanded id
  //   expandedLoadingIds → which of those are still loading
  // 🛠 FIX: was a single expandedId/expandedSchedule pair (only one row could
  // be open at a time). Converted to sets/maps so a search can auto-expand
  // every matching schedule at once — see fetchPage below.
  const [expandedIds, setExpandedIds] = useState<Set<number>>(new Set());
  const [expandedSchedules, setExpandedSchedules] = useState<
    Record<number, AuditSchedule>
  >({});
  const [expandedLoadingIds, setExpandedLoadingIds] = useState<Set<number>>(
    new Set(),
  );

  // ✅ NEW — Dynamic permission system (same pattern as InquiryTable)
  //   moduleConfig     → the `modules` row for slug 'audit-schedules'
  //                      (carries button_config + column_config + id)
  //   userPermissions  → the current user's permission objects
  //   permissionsReady → both fetches finished
  const [moduleConfig, setModuleConfig] = useState<any>(null);
  const [userPermissions, setUserPermissions] = useState<any[]>([]);
  const [permissionsReady, setPermissionsReady] = useState(false);

  // Cancel/Reschedule targets (opened from inside the Detail modal)
  const [cancelTarget, setCancelTarget] = useState<{
    auditRow: AuditRow;
    scheduleTitle: string;
    coordinator?: AuditSchedule["coordinator"]; // ← added
  } | null>(null);
  const [rescheduleTarget, setRescheduleTarget] = useState<{
    auditRow: AuditRow;
    currentScheduleDate: string;
    coordinator?: AuditSchedule["coordinator"]; // ← added
  } | null>(null);

  // Bulk cancel (opened from schedule row)
  const [bulkCancelTarget, setBulkCancelTarget] =
    useState<AuditScheduleRowType | null>(null);

  const [showAnalytics, setShowAnalytics] = useState(false);

  const currentUserId = getCurrentUserId();
  const canDelete =
    currentUserId !== null && DELETE_ALLOWED_USER_IDS.includes(currentUserId);

  // ✅ NEW — Load module config (button_config) for slug 'audit-schedules'.
  // Same approach as InquiryTable.fetchModuleConfig().
  const fetchModuleConfig = useCallback(async (): Promise<void> => {
    try {
      const response = await fetchApi<any>(`${API_BASE_URL}/modules`);
      const list = Array.isArray(response)
        ? response
        : response?.data
          ? Array.isArray(response.data)
            ? response.data
            : [response.data]
          : [response];
      const mod = list.find(
        (m: any) =>
          m.slug === "audit-schedules" || m.name === "audit-schedules",
      );
      if (mod) setModuleConfig(mod);
    } catch {
      // silent — falls through to permittedActions default
    }
  }, []);

  // ✅ NEW — Load the current user's permissions.
  // Same approach as InquiryTable.fetchUserPermissions().
  const fetchUserPermissions = useCallback(async (): Promise<void> => {
    try {
      let userId: any = null;
      if (typeof window !== "undefined") {
        try {
          const s = localStorage.getItem("user");
          if (s) {
            const p = JSON.parse(s);
            userId = p?.id || p?.userId || p?.user_id;
          }
        } catch {}
        if (!userId) {
          try {
            const t =
              localStorage.getItem("token") ||
              localStorage.getItem("access_token");
            if (t) {
              const p = JSON.parse(atob(t.split(".")[1]));
              userId = p?.id || p?.userId || p?.sub;
            }
          } catch {}
        }
      }
      if (!userId) {
        setUserPermissions([]);
        return;
      }
      const res = await fetchApi<any>(
        `${API_BASE_URL}/user-permissions/user/${userId}`,
      );
      const list = Array.isArray(res)
        ? res
        : res?.data
          ? Array.isArray(res.data)
            ? res.data
            : [res.data]
          : (res?.permissions ?? []);
      setUserPermissions(list);
    } catch {
      setUserPermissions([]);
    }
  }, []);

  // ✅ NEW — Set of action keys the user is permitted to use on this module.
  // Mirrors InquiryTable.permittedActions. When module config fails to load,
  // we fail OPEN (return a permissive default) so the table never breaks for
  // admins — the backend userCan() check is the real lock.
  const permittedActions = useMemo((): Set<string> => {
    if (!moduleConfig) {
      // Fallback: no module config — allow common actions (admins/super-admin)
      return new Set([
        "view",
        "edit",
        "delete",
        "create",
        "publish",
        "cancel",
        "reschedule",
        "bulk-cancel",
      ]);
    }
    const a = new Set<string>();
    for (const up of userPermissions) {
      const action = up.permission?.action ?? up.action;
      const moduleId =
        up.permission?.module?.id ??
        up.permission?.module_id ??
        up.module?.id ??
        up.module_id;
      if (!action) continue;
      if (moduleId === moduleConfig.id) {
        a.add(action);
      }
    }
    // view is implicit — if the page loaded, the user can view
    a.add("view");
    return a;
  }, [moduleConfig, userPermissions]);

  // ── Date preset → date_from / date_to ───────────────────────────────────
  const datePresetToRange = useCallback(
    (preset: DatePreset): { date_from?: string; date_to?: string } => {
      const today = new Date();
      const toISO = (d: Date) => d.toISOString().split("T")[0];

      if (preset === "today") {
        return { date_from: toISO(today), date_to: toISO(today) };
      }
      if (preset === "this_week") {
        const day = today.getDay();
        const monday = new Date(today);
        monday.setDate(today.getDate() - (day === 0 ? 6 : day - 1));
        const sunday = new Date(monday);
        sunday.setDate(monday.getDate() + 6);
        return { date_from: toISO(monday), date_to: toISO(sunday) };
      }
      if (preset === "this_month") {
        const start = new Date(today.getFullYear(), today.getMonth(), 1);
        const end = new Date(today.getFullYear(), today.getMonth() + 1, 0);
        return { date_from: toISO(start), date_to: toISO(end) };
      }
      if (preset === "next_month") {
        const start = new Date(today.getFullYear(), today.getMonth() + 1, 1);
        const end = new Date(today.getFullYear(), today.getMonth() + 2, 0);
        return { date_from: toISO(start), date_to: toISO(end) };
      }
      if (preset === "past") {
        const yesterday = new Date(today);
        yesterday.setDate(today.getDate() - 1);
        return { date_to: toISO(yesterday) };
      }
      // 🆕 Custom range — either typed From/To, or filled in by the
      // Month/Year quick-pick in the filters bar (same two fields).
      if (preset === "custom") {
        return {
          ...(customDateFrom && { date_from: customDateFrom }),
          ...(customDateTo && { date_to: customDateTo }),
        };
      }
      return {};
    },
    [customDateFrom, customDateTo],
  );

  // ── Fetch page (NO row hydration — keep list lightweight) ──────────────
  const fetchPage = useCallback(
    (page: number, search: string) => {
      setLoading(true);
      setSelectedRows([]);
      // Collapse any open accordions when the page/filter changes — the
      // previously expanded schedules may no longer be on screen.
      setExpandedIds(new Set());
      setExpandedSchedules({});
      const range = datePresetToRange(datePreset);

      getAuditSchedulesPaginated({
        page,
        limit: itemsPerPage,
        ...(search && { search }),
        ...(statusFilter !== "all" && { status: statusFilter }),
        ...(clientGroupFilter !== "all" && { client_group: clientGroupFilter }),
        ...range,
      })
        .then((res) => {
          const mapped = mapAuditSchedulesApiResponse(res.data);
          setData(mapped);
          setTotal(res.total);
          setLastPage(res.lastPage);

          // 🆕 PERFORMANCE FIX: the backend now embeds each matched
          // schedule's full `rows` directly in the search response (see
          // findAll() in the service). So auto-expand no longer needs to
          // fire a separate GET /audit-schedules/:id per match — that
          // extra round-trip per row was the actual cause of "search takes
          // too long". Just use what already came back.
          if (search.trim()) {
            const ids = mapped.map((r) => r.id);
            setExpandedIds(new Set(ids));
            setExpandedSchedules((prev) => {
              const next = { ...prev };
              for (const raw of res.data as any[]) {
                next[raw.id] = raw; // already has .rows, .coordinator, etc.
              }
              return next;
            });
            // Nothing is loading — clear any stale loading flags.
            setExpandedLoadingIds(new Set());
          }
        })
        .catch((err) => setError(err?.message || "Failed to load"))
        .finally(() => setLoading(false));
    },
    [
      statusFilter,
      clientGroupFilter,
      datePreset,
      itemsPerPage,
      datePresetToRange,
    ],
  );

  // ✅ NEW — Load module config + permissions once on mount.
  useEffect(() => {
    const initPermissions = async () => {
      await Promise.all([fetchModuleConfig(), fetchUserPermissions()]);
      setPermissionsReady(true);
    };
    initPermissions();
  }, [fetchModuleConfig, fetchUserPermissions]);

  // ── Initial / refresh load ──────────────────────────────────────────────
  useEffect(() => {
    setCurrentPage(1);
    fetchPage(1, "");
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [refreshFlag]);

  // ── Page change ─────────────────────────────────────────────────────────
  useEffect(() => {
    fetchPage(currentPage, debouncedSearch);
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [currentPage]);

  // ── Search/filter change → reset to page 1 ──────────────────────────────
  useEffect(() => {
    setCurrentPage(1);
    fetchPage(1, debouncedSearch);
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [
    debouncedSearch,
    statusFilter,
    clientGroupFilter,
    datePreset,
    itemsPerPage,
    customDateFrom,
    customDateTo,
  ]);

  const refresh = () => fetchPage(currentPage, debouncedSearch);

  // Refresh both the list AND every open detail accordion (if any)
  const refreshAll = () => {
    refresh();
    setDetailRefreshFlag((p) => p + 1);
    // ✅ Also re-fetch each expanded accordion's rows so cancel/reschedule
    // done from inside it is reflected immediately.
    expandedIds.forEach((id) => reloadExpanded(id));
  };

  // (re)fetch the full schedule for one expanded accordion row.
  // Uses the SAME getAuditSchedule() API the detail modal uses, so the
  // sub-table data is identical to the modal.
  const reloadExpanded = useCallback((scheduleId: number) => {
    setExpandedLoadingIds((prev) => new Set(prev).add(scheduleId));
    getAuditSchedule(scheduleId)
      .then((sch) =>
        setExpandedSchedules((prev) => ({ ...prev, [scheduleId]: sch })),
      )
      .catch((err) =>
        toast.error(err?.message || "Failed to load audit rows"),
      )
      .finally(() =>
        setExpandedLoadingIds((prev) => {
          const next = new Set(prev);
          next.delete(scheduleId);
          return next;
        }),
      );
  }, []);

  // Toggle the inline accordion for a schedule row. Click an already-open
  // row → collapse just that one. Click another row → open it too (and
  // fetch its rows) — several rows can be expanded at once now, which is
  // what lets search auto-expand every match.
  const handleToggleExpand = useCallback(
    (row: AuditScheduleRowType) => {
      setExpandedIds((prev) => {
        const next = new Set(prev);
        if (next.has(row.id)) {
          next.delete(row.id);
        } else {
          next.add(row.id);
          reloadExpanded(row.id);
        }
        return next;
      });
    },
    [reloadExpanded],
  );

  // ── Action handlers ─────────────────────────────────────────────────────
  const handleDelete = async (row: AuditScheduleRowType) => {
    // ⚠️ Deleting a non-DRAFT schedule also deletes ALL its audit rows
    // (backend cascade) and those auditors were already notified. Show an
    // extra blocking confirm before the normal delete dialog.
    if (row.status !== "DRAFT") {
      const proceed = window.confirm(
        `⚠️ "${row.title}" is ${row.status}, not a draft.\n\n` +
          `Deleting it will ALSO permanently delete every audit row inside ` +
          `it (${row.row_count} audit${row.row_count !== 1 ? "s" : ""}).\n\n` +
          `This cannot be undone. Are you sure you want to continue?`,
      );
      if (!proceed) return;
    }
 
    const { confirmed, error: delErr } = await deleteWithConfirm(
      `Schedule "${row.title}"`,
      () => deleteAuditSchedule(row.id),
      {
        successMessage: "Schedule deleted.",
        errorMessage: "Failed to delete.",
      },
    );
    if (confirmed && !delErr) refresh();
  };

  const handleEdit = (row: AuditScheduleRowType) => {
    setEditingId(row.id);
  };

  // View opens the detail/print modal (matches architecture spec)
  const handleView = (row: AuditScheduleRowType) => {
    setDetailScheduleId(row.id);
  };

  const handlePublish = async (row: AuditScheduleRowType) => {
    if (row.status !== "DRAFT") {
      toast.error("Only DRAFT schedules can be published");
      return;
    }
    if (row.row_count === 0) {
      toast.error("Add at least one audit row before publishing");
      return;
    }
    const confirmed = window.confirm(
      `Publish "${row.title}"?\n\n` +
        `This will send notifications (email + in-app) to:\n` +
        `• Marketing owner of each company\n` +
        `• Lead auditor of each row\n` +
        `• Coordinator: ${row.coordinator_name}\n\n` +
        `Proceed?`,
    );
    if (!confirmed) return;

    try {
      await updateAuditSchedule(row.id, { status: "PUBLISHED" });
      toast.success("Schedule published. Notifications sent to stakeholders.");
      refresh();
    } catch (err: any) {
      toast.error(err?.message || "Failed to publish");
    }
  };

  const handleBulkCancel = (row: AuditScheduleRowType) => {
    setBulkCancelTarget(row);
  };

  const handlePrint = (row: AuditScheduleRowType) => {
    // Open the detail modal — user clicks Print there
    setDetailScheduleId(row.id);
  };

  // These are triggered from inside the Detail modal AND the inline accordion
  const handleCancelAuditRow = (
    schedule: AuditSchedule,
    auditRow: AuditRow,
  ) => {
    setCancelTarget({
      auditRow,
      scheduleTitle: schedule.title,
      coordinator: schedule.coordinator, // ← added
    });
  };

  const handleRescheduleAuditRow = (
    schedule: AuditSchedule,
    auditRow: AuditRow,
  ) => {
    setRescheduleTarget({
      auditRow,
      currentScheduleDate: schedule.schedule_date,
      coordinator: schedule.coordinator, // ← added
    });
  };

  const hasActiveFilters =
    !!searchTerm ||
    statusFilter !== "all" ||
    clientGroupFilter !== "all" ||
    datePreset !== "all" ||
    !!customDateFrom ||
    !!customDateTo;

  const clearAllFilters = () => {
    setSearchTerm("");
    setStatusFilter("all");
    setClientGroupFilter("all");
    setDatePreset("all");
    setCustomDateFrom("");
    setCustomDateTo("");
  };

  // ── Analytics (simple in-page aggregation) ──────────────────────────────
  const analytics = useMemo(() => {
    let draft = 0,
      published = 0,
      inProgress = 0,
      completed = 0,
      cancelled = 0;
    data.forEach((d) => {
      if (d.status === "DRAFT") draft++;
      else if (d.status === "PUBLISHED") published++;
      else if (d.status === "IN_PROGRESS") inProgress++;
      else if (d.status === "COMPLETED") completed++;
      else if (d.status === "CANCELLED") cancelled++;
    });
    return { draft, published, inProgress, completed, cancelled };
  }, [data]);

  if (error) {
    return (
      <div className={styles.errorContainer}>
        <div className={styles.errorIcon}>⚠️</div>
        <h3 className={styles.errorTitle}>Error</h3>
        <p className={styles.errorMessage}>{error}</p>
        <button className={styles.errorButton} onClick={refresh}>
          Retry
        </button>
      </div>
    );
  }

  return (
    <div className={styles.container}>
      {/* Detail/Print modal — opens when user clicks View 👁 */}
      <AuditScheduleDetailModal
        isOpen={!!detailScheduleId}
        scheduleId={detailScheduleId}
        refreshFlag={detailRefreshFlag}
        onClose={() => setDetailScheduleId(null)}
        onCancelRow={handleCancelAuditRow}
        onRescheduleRow={handleRescheduleAuditRow}
      />

      <AuditScheduleForm
        isOpen={!!editingId || isCreateOpen}
        onClose={() => {
          setEditingId(null);
          setIsCreateOpen(false);
        }}
        refreshData={refresh}
        editId={editingId}
      />

      <CancelRowModal
        isOpen={!!cancelTarget}
        onClose={() => setCancelTarget(null)}
        auditRow={cancelTarget?.auditRow ?? null}
        scheduleTitle={cancelTarget?.scheduleTitle}
        coordinator={cancelTarget?.coordinator ?? null} 
        onSuccess={refreshAll}
      />

      <RescheduleRowModal
        isOpen={!!rescheduleTarget}
        onClose={() => setRescheduleTarget(null)}
        auditRow={rescheduleTarget?.auditRow ?? null}
        currentScheduleDate={rescheduleTarget?.currentScheduleDate}
        coordinator={rescheduleTarget?.coordinator ?? null}  
        onSuccess={refreshAll}
      />

      <BulkCancelModal
        isOpen={!!bulkCancelTarget}
        onClose={() => setBulkCancelTarget(null)}
        schedule={bulkCancelTarget}
        onSuccess={refresh}
      />

      {/* Filters */}
      <AuditScheduleFilters
        searchTerm={searchTerm}
        setSearchTerm={setSearchTerm}
        statusFilter={statusFilter}
        setStatusFilter={setStatusFilter}
        clientGroupFilter={clientGroupFilter}
        setClientGroupFilter={setClientGroupFilter}
        datePreset={datePreset}
        setDatePreset={setDatePreset}
        clearFilters={clearAllFilters}
        onRefresh={refresh}
        showAnalytics={showAnalytics}
        onAnalyticsToggle={() => setShowAnalytics((p) => !p)}
        customDateFrom={customDateFrom}
        setCustomDateFrom={setCustomDateFrom}
        customDateTo={customDateTo}
        setCustomDateTo={setCustomDateTo}
      />

      {/* Analytics cards */}
      {showAnalytics && (
        <div
          style={{
            display: "grid",
            gridTemplateColumns: "repeat(auto-fit, minmax(140px, 1fr))",
            gap: 10,
            marginBottom: 12,
          }}
        >
          <KpiCard label="Total" value={total} gradient="#1e40af,#3b82f6" />
          <KpiCard
            label="Draft"
            value={analytics.draft}
            gradient="#475569,#64748b"
          />
          <KpiCard
            label="Published"
            value={analytics.published}
            gradient="#1e40af,#3b82f6"
          />
          <KpiCard
            label="In Progress"
            value={analytics.inProgress}
            gradient="#b45309,#d97706"
          />
          <KpiCard
            label="Completed"
            value={analytics.completed}
            gradient="#166534,#22c55e"
          />
          <KpiCard
            label="Cancelled"
            value={analytics.cancelled}
            gradient="#991b1b,#dc2626"
          />
        </div>
      )}

      {/* Record count line */}
      <div
        style={{
          padding: "10px 16px",
          backgroundColor: "#f0fdfa",
          border: "1px solid #99f6e4",
          borderRadius: 8,
          marginBottom: 12,
          display: "flex",
          alignItems: "center",
          justifyContent: "space-between",
          fontSize: 13,
          color: "#0f766e",
        }}
      >
        <span>
          📊 Showing{" "}
          <strong>
            {data.length > 0 ? (currentPage - 1) * itemsPerPage + 1 : 0}–
            {(currentPage - 1) * itemsPerPage + data.length}
          </strong>{" "}
          of <strong>{total.toLocaleString()}</strong> schedules
          {hasActiveFilters && (
            <span style={{ marginLeft: 8, color: "#9ca3af" }}>(filtered)</span>
          )}
        </span>
        {hasActiveFilters && (
          <button
            onClick={clearAllFilters}
            style={{
              background: "none",
              border: "none",
              color: "#0f766e",
              cursor: "pointer",
              textDecoration: "underline",
              fontSize: 13,
            }}
          >
            Clear filters
          </button>
        )}
      </div>

      {/* Hint banner */}
      {data.length > 0 && (
        <div
          style={{
            padding: "8px 14px",
            background: "#eff6ff",
            border: "1px solid #bfdbfe",
            borderRadius: 8,
            marginBottom: 8,
            display: "flex",
            alignItems: "center",
            gap: 8,
            fontSize: 12,
            color: "#1e40af",
          }}
        >
          💡 <strong>Tip:</strong> Click the{" "}
          <span
            style={{
              display: "inline-block",
              padding: "1px 6px",
              background: "#dbeafe",
              borderRadius: 4,
              fontWeight: 700,
            }}
          >
            audits count
          </span>{" "}
          badge to expand the schedule's audit rows right here — or the{" "}
          <span
            style={{
              display: "inline-block",
              padding: "1px 6px",
              background: "#dbeafe",
              borderRadius: 4,
              fontWeight: 700,
            }}
          >
            👁 View
          </span>{" "}
          icon for the full print/email format.
        </div>
      )}

      {/* Table */}
      <div className={styles.tableWrapper}>
        <table className={styles.table}>
          <thead>
            <tr>
              <th className={styles.checkboxCol}>
                <input
                  type="checkbox"
                  className={styles.checkbox}
                  checked={
                    data.length > 0 &&
                    data.every((r) => selectedRows.includes(r.sno))
                  }
                  onChange={(e) =>
                    setSelectedRows(
                      e.target.checked ? data.map((r) => r.sno) : [],
                    )
                  }
                />
              </th>
              <th className={styles.th}>Date</th>
              <th className={styles.th}>Title</th>
              <th className={styles.th}>Group</th>
              <th className={styles.th}>Rows</th>
              <th className={styles.th}>Coordinator</th>
              <th className={styles.th}>Status</th>
              <th className={styles.actionsCol}>Actions</th>
            </tr>
          </thead>
          <tbody>
            {loading ? (
              <tr>
                <td
                  colSpan={8}
                  style={{
                    textAlign: "center",
                    padding: "60px",
                    color: "#9ca3af",
                  }}
                >
                  <div
                    style={{
                      display: "inline-block",
                      width: 28,
                      height: 28,
                      border: "3px solid #e5e7eb",
                      borderTopColor: "#14b8a6",
                      borderRadius: "50%",
                      animation: "spin 0.7s linear infinite",
                      marginBottom: 10,
                    }}
                  />
                  <p style={{ margin: 0 }}>Loading audit schedules...</p>
                </td>
              </tr>
            ) : data.length > 0 ? (
              data.map((row) => (
                <AuditScheduleRowFallback
                  key={row.sno}
                  row={row}
                  isSelected={selectedRows.includes(row.sno)}
                  handleRowSelect={(id, checked) =>
                    setSelectedRows((p) =>
                      checked ? [...p, id] : p.filter((r) => r !== id),
                    )
                  }
                  onEdit={handleEdit}
                  onDelete={handleDelete}
                  onView={handleView}
                  onPublish={handlePublish}
                  onBulkCancel={handleBulkCancel}
                  onPrint={handlePrint}
                  canDelete={canDelete}
                  /* ✅ inline accordion props — multi-expand aware */
                  isExpanded={expandedIds.has(row.id)}
                  expandedSchedule={expandedSchedules[row.id] ?? null}
                  expandedLoading={expandedLoadingIds.has(row.id)}
                  onToggleExpand={handleToggleExpand}
                  onCancelAuditRow={handleCancelAuditRow}
                  onRescheduleAuditRow={handleRescheduleAuditRow}
                  /* ✅ NEW — permission gating */
                  permittedActions={permittedActions}
                />
              ))
            ) : (
              <tr>
                <td
                  colSpan={8}
                  style={{ textAlign: "center", padding: "60px" }}
                >
                  <div
                    style={{
                      display: "flex",
                      flexDirection: "column",
                      alignItems: "center",
                      gap: 12,
                    }}
                  >
                    <div style={{ fontSize: 36 }}>📅</div>
                    <h3 style={{ margin: 0, color: "#111827" }}>
                      No Audit Schedules Found
                    </h3>
                    <p style={{ color: "#6b7280", margin: 0 }}>
                      {hasActiveFilters
                        ? "No schedules match your filters."
                        : "Get started by creating a new audit schedule."}
                    </p>
                  </div>
                </td>
              </tr>
            )}
          </tbody>
        </table>
      </div>

      <Pagination
        currentPage={currentPage}
        setCurrentPage={setCurrentPage}
        totalPages={lastPage}
        startIndex={(currentPage - 1) * itemsPerPage + 1}
        endIndex={Math.min(currentPage * itemsPerPage, total)}
        sortedDataLength={total}
        itemsPerPage={itemsPerPage}
        setItemsPerPage={(v) => {
          setCurrentPage(1);
          setItemsPerPage(v);
        }}
      />
    </div>
  );
}

// ─── KPI card ────────────────────────────────────────────────────────────
function KpiCard({
  label,
  value,
  gradient,
}: {
  label: string;
  value: number;
  gradient: string;
}) {
  return (
    <div
      style={{
        padding: "12px 16px",
        background: `linear-gradient(135deg, ${gradient.split(",")[0]} 0%, ${gradient.split(",")[1]} 100%)`,
        color: "#fff",
        borderRadius: 10,
        boxShadow: "0 2px 4px rgba(0,0,0,0.08)",
      }}
    >
      <div
        style={{
          fontSize: 10,
          fontWeight: 700,
          letterSpacing: 0.5,
          textTransform: "uppercase",
          opacity: 0.9,
        }}
      >
        {label}
      </div>
      <div style={{ fontSize: 22, fontWeight: 800, marginTop: 4 }}>
        {value.toLocaleString()}
      </div>
    </div>
  );
}