'use client';

import { useCallback, useEffect, useRef, useState, useMemo } from 'react';
import type { ReactNode } from 'react';
import { useRouter } from 'next/navigation';
import type { RowSelectionState, PaginationState } from '@tanstack/react-table';
import { api } from '@/lib/api';
import { useAuth } from '@/components/auth-context';
import { toast } from 'react-toastify';
import { showConfirmDelete } from '@/lib/confirm';
import { DataTable } from '@/components/data-table/DataTable';
import { DataTableActions } from '@/components/data-table/DataTableActions';
import SearchableSelect from '@/components/SearchableSelect';
import dynamic from 'next/dynamic';
import BackToDashboard from '@/components/BackToDashboard';
import { PageLoader } from '@/components/DotLoader';
import { formatDate } from '@/lib/dates';
import { cleanHtmlText } from '@/lib/format';
import JobDetailsModal from '@/components/JobDetailsModal';
import DocViewer from '@/components/DocViewer';
import AgentModal from '@/components/jobs/AgentModal';

// TinyMCE must be client-only — SSR/hydration of the editor breaks the page.
const RichTextEditor = dynamic(() => import('@/components/RichTextEditor'), {
  ssr: false,
  loading: () => (
    <div className="w-full h-[320px] rounded-none border border-slate-200 dark:border-slate-800 bg-slate-50 dark:bg-slate-950 animate-pulse" />
  ),
});

/** Checkbox that supports the "indeterminate" (partial-selection) visual state. */
function SelectCheckbox({
  checked,
  indeterminate = false,
  onChange,
  ariaLabel,
}: {
  checked: boolean;
  indeterminate?: boolean;
  onChange: (e: React.ChangeEvent<HTMLInputElement>) => void;
  ariaLabel: string;
}) {
  const ref = useRef<HTMLInputElement>(null);
  useEffect(() => {
    if (ref.current) ref.current.indeterminate = !checked && indeterminate;
  }, [checked, indeterminate]);
  return (
    <input
      ref={ref}
      type="checkbox"
      aria-label={ariaLabel}
      checked={checked}
      onChange={onChange}
      onClick={(e) => e.stopPropagation()}
      className="w-4 h-4 rounded-none border-slate-300 dark:border-slate-600 accent-indigo-600 cursor-pointer"
    />
  );
}

interface RecruiterBrief {
  id: number;
  email: string;
  full_name: string;
  role: string;
  phone?: string;
  location?: string;
  experience_years?: number;
}

interface Job {
  id: number;
  title: string;
  department?: string;
  location: string;
  experience_band?: string;
  ctc_band?: string;
  notice_period?: string;
  shift?: string;
  must_have_skills?: string;
  good_to_have_skills?: string;
  qualifications?: string;
  working_days?: string;
  num_positions?: number | null;
  certification?: string;
  questions?: (string | { question: string; answer: string })[];
  attachment?: string | null;
  work_details: string;
  status: 'Draft' | 'Published' | 'Closed';
  priority?: 'High' | 'Medium' | 'Low';
  created_by_email: string;
  created_by_name?: string | null;
  client?: number | null;
  client_name?: string | null;
  assigned_recruiters?: RecruiterBrief[];
  postings?: PostingBrief[];
  candidates_count?: number;
  approval_status?: string;
  /** Single canonical status from the backend: draft | pending_approval | published | closed. */
  jd_status?: string;
  /** Publish state of the JD: "draft" until it has been posted to a channel. */
  publication_status?: 'draft' | 'published';
  jd_code?: string;
  hunar_agent_id?: string;
  rejection_reason?: string;
  approved_at?: string | null;
  rejected_at?: string | null;
  approved_by_name?: string | null;
  current_approver_name?: string | null;
  created_at: string;
  updated_at: string;
}

interface PostingBrief {
  id: number;
  channel: string;
  channel_label: string;
  status: 'PENDING' | 'POSTED' | 'FAILED';
  external_url: string;
  error_message: string;
  posted_at: string | null;
}

interface PublishResult {
  channel: string;
  status: string;
  external_url?: string;
  error_message?: string;
}

/** One previewed application URL from /jobs/<id>/publish-preview/. The `url`
 *  carries only a short opaque tracking token — never a readable `?source=`. */
interface PreviewLink {
  channel: string;
  channel_label: string;
  url: string;
  posting_status: string | null;
  is_posted: boolean;
}

interface ClientBrief {
  id: number;
  name: string;
}

// LinkedIn is the only integrated, functional job board, so it is the sole
// option offered in the Post action. Naukri/Career Portal are intentionally
// omitted from the UI until they are actually integrated.
const PUBLISH_CHANNELS = [
  { key: 'LINKEDIN', label: 'LinkedIn', icon: 'fa-brands fa-linkedin', color: 'text-[#0a66c2]' },
  // { key: 'WHATSAPP', label: 'WhatsApp', icon: 'fa-brands fa-whatsapp', color: 'text-emerald-500' },
  // { key: 'SMS', label: 'SMS', icon: 'fa-solid fa-comment-sms', color: 'text-orange-500' },
  // { key: 'TELEGRAM', label: 'Telegram', icon: 'fa-brands fa-telegram', color: 'text-sky-500' },
  // { key: 'CAREER_PORTAL', label: 'Career Page / Direct Link', icon: 'fa-solid fa-globe', color: 'text-indigo-500' },
];

/** Human-friendly label for a recruiter (name, falling back to email). */
const recruiterLabel = (r: RecruiterBrief) => r.full_name?.trim() || r.email;

const renderRequiredLabel = (label: string) => (
  <span className="inline-flex items-center gap-1">
    <span>{label}</span>
    <span className="text-red-500">*</span>
  </span>
);

const TITLE_PATTERN = /^[A-Za-z0-9\s/&(),-]*$/;
const validateJobTitle = (value: string) => {
  if (!value) return '';
  if (!TITLE_PATTERN.test(value)) {
    return 'Only letters, numbers, spaces, hyphen (-), slash (/), ampersand (&), parentheses (), and comma (,) are allowed.';
  }
  return '';
};

const getAttachmentUrl = (rawUrl?: string | null): string => {
  if (!rawUrl) return '';
  if (rawUrl.startsWith('http://') || rawUrl.startsWith('https://') || rawUrl.startsWith('blob:')) return rawUrl;
  const backendBase = (process.env.NEXT_PUBLIC_API_URL || 'http://localhost:8000/api/v1').replace('/api/v1', '');
  if (rawUrl.startsWith('/')) {
    return `${backendBase}${rawUrl}`;
  }
  return `${backendBase}/media/${rawUrl}`;
};

export default function JobsPage() {
  const router = useRouter();
  const { user } = useAuth();
  const [jobs, setJobs] = useState<Job[]>([]);
  const [myApps, setMyApps] = useState<any[]>([]);
  const [applyingJobId, setApplyingJobId] = useState<number | null>(null);
  const [applyPreviewJob, setApplyPreviewJob] = useState<Job | null>(null);
  const [clients, setClients] = useState<ClientBrief[]>([]);

  const [loading, setLoading] = useState(true);
  const [isModalOpen, setIsModalOpen] = useState(false);
  const [postHistoryOpen, setPostHistoryOpen] = useState(false);
  const [viewJob, setViewJob] = useState<Job | null>(null);
  const [agentModalOpen, setAgentModalOpen] = useState(false);
  const [agentJob, setAgentJob] = useState<Job | null>(null);
  const [jobAudit, setJobAudit] = useState<{ id: number; action: string; changes: string; by: string | null; created_at: string }[]>([]);
  const [viewMode, setViewMode] = useState<'card' | 'table'>('table');
  const [rowSelection, setRowSelection] = useState<RowSelectionState>({});

  // Filters State (matching Candidates page layout)
  const [filterOpen, setFilterOpen] = useState(false);
  const [appliedJdName, setAppliedJdName] = useState('');
  const [appliedJdId, setAppliedJdId] = useState('');
  const [appliedSkills, setAppliedSkills] = useState<string[]>([]);
  const [appliedSkillMatchMode, setAppliedSkillMatchMode] = useState<'OR' | 'AND'>('OR');
  // Seeded from `?status=` (e.g. Admin dashboard's "Open JDs" card links to
  // `?status=Published`) so the very first render is already scoped — after
  // that it behaves exactly like picking the status from the dropdown, and
  // the existing "Active Filters" chip bar already shows/clears it.
  const [appliedStatus, setAppliedStatus] = useState<string>(() => {
    if (typeof window === 'undefined') return 'ALL';
    return new URLSearchParams(window.location.search).get('status') || 'ALL';
  });
  // Dashboard drill-down: exact JD ids from `?ids=` (null = no drill-down).
  // Seeded synchronously from the URL so the very first render is already
  // scoped — the list can never briefly show records outside the card's count.
  const [focusIds, setFocusIds] = useState<number[] | null>(() => {
    if (typeof window === 'undefined') return null;
    const raw = new URLSearchParams(window.location.search).get('ids');
    if (raw === null) return null;
    return raw.split(',').map((x) => Number(x.trim())).filter((n) => Number.isFinite(n));
  });
  const [focusLabel, setFocusLabel] = useState<string>(() => {
    if (typeof window === 'undefined') return '';
    return new URLSearchParams(window.location.search).get('label') || '';
  });
  // Dashboard drill-down: `?owner=me` (e.g. the PM dashboard's "Total
  // Requirements" card) narrows the list server-side to JDs created by the
  // current user — same filter the card's count uses, resolved fresh on load.
  const [ownerMe, setOwnerMe] = useState<boolean>(() => {
    if (typeof window === 'undefined') return false;
    return new URLSearchParams(window.location.search).get('owner') === 'me';
  });
  // Dashboard drill-down: `?assigned=me` (Recruiter dashboard's "Assigned/
  // Active/On Hold/Closed JDs" cards) narrows to JDs assigned to the current
  // user, resolved fresh on load.
  const [assignedMe, setAssignedMe] = useState<boolean>(() => {
    if (typeof window === 'undefined') return false;
    return new URLSearchParams(window.location.search).get('assigned') === 'me';
  });
  // Dashboard drill-down: `?pending=1` (TA dashboard's "Pending" card).
  const [pendingOnly, setPendingOnly] = useState<boolean>(() => {
    if (typeof window === 'undefined') return false;
    return new URLSearchParams(window.location.search).get('pending') === '1';
  });
  // Dashboard drill-down: `?created_from=`/`?created_to=` (TA dashboard's
  // period-scoped "Total Requirements" card).
  const [createdFromFilter, setCreatedFromFilter] = useState<string>(() => {
    if (typeof window === 'undefined') return '';
    return new URLSearchParams(window.location.search).get('created_from') || '';
  });
  const [createdToFilter, setCreatedToFilter] = useState<string>(() => {
    if (typeof window === 'undefined') return '';
    return new URLSearchParams(window.location.search).get('created_to') || '';
  });
  // Dashboard drill-down: `?period=` (TA dashboard's period selector, on the
  // "Total Requirements" card) — resolved server-side into the same
  // calendar-aligned created_from/created_to window the card's own count
  // uses (apps.jobs.views.JobDescriptionViewSet.get_queryset).
  const [periodFilter, setPeriodFilter] = useState<string>(() => {
    if (typeof window === 'undefined') return '';
    return new URLSearchParams(window.location.search).get('period') || '';
  });
  // True while any dashboard-card drill-down (other than the plain status
  // filter, which the existing "Active Filters" bar already shows) is active.
  const hasDrillDown = !!(focusIds || ownerMe || assignedMe || pendingOnly || createdFromFilter || createdToFilter || periodFilter);
  const clearDrillDown = () => {
    setFocusIds(null); setFocusLabel(''); setOwnerMe(false); setAssignedMe(false);
    setPendingOnly(false); setCreatedFromFilter(''); setCreatedToFilter(''); setPeriodFilter('');
    router.replace('/jobs');
  };

  // Server-side pagination: the table/cards show ONE page at a time and all
  // filtering happens on the server (see JobDescriptionViewSet._apply_list_filters),
  // so the browser never downloads every JD.
  const [pagination, setPagination] = useState<PaginationState>({ pageIndex: 0, pageSize: 20 });
  const [total, setTotal] = useState(0);

  const [masterSkillOptions, setMasterSkillOptions] = useState<{ value: string; label: string }[]>([]);
  const [masterSkillsLoading, setMasterSkillsLoading] = useState(false);

  const loadMasterSkillOptions = useCallback(async () => {
    setMasterSkillsLoading(true);
    try {
      const res = (await api.get('/public/skills/')) as any;
      const data = res?.data ?? [];
      const list = Array.isArray(data) ? data : data?.results || [];
      const unique = Array.from(new Set(list.map((s: any) => s?.name).filter(Boolean))) as string[];
      setMasterSkillOptions(unique.sort((a, b) => a.localeCompare(b)).map((n) => ({ value: n, label: n })));
    } catch (err) {
      console.error('Failed to load master skills', err);
      setMasterSkillOptions([]);
    } finally {
      setMasterSkillsLoading(false);
    }
  }, []);

  // Recruiter assignment
  const [recruiters, setRecruiters] = useState<RecruiterBrief[]>([]);
  const [assignJob, setAssignJob] = useState<Job | null>(null);
  const [selectedRecruiterIds, setSelectedRecruiterIds] = useState<number[]>([]);
  const [assigning, setAssigning] = useState(false);
  const openAgentModal = (job: Job) => {
    setAgentJob(job);
    setAgentModalOpen(true);
  };

  const [recruiterSearch, setRecruiterSearch] = useState('');
  const [recruiterPage, setRecruiterPage] = useState(1);
  const [recruiterTotal, setRecruiterTotal] = useState(0);
  const [recruiterLoading, setRecruiterLoading] = useState(false);
  const REC_PAGE_SIZE = 10;

  const [recTab, setRecTab] = useState<'select' | 'assigned'>('select');
  const [assignedRecs, setAssignedRecs] = useState<RecruiterBrief[]>([]);
  const [assignedRecPage, setAssignedRecPage] = useState(1);
  const [assignedRecTotal, setAssignedRecTotal] = useState(0);
  const [assignedRecLoading, setAssignedRecLoading] = useState(false);
  const [recAssigning, setRecAssigning] = useState(false);


  // JD approval review modal (approve / reject with reason) + submit popup.
  const [reviewJob, setReviewJob] = useState<Job | null>(null);
  const [reviewReason, setReviewReason] = useState('');
  const [reviewTab, setReviewTab] = useState<'approval' | 'view_jd'>('approval');
  const [submitJob, setSubmitJob] = useState<Job | null>(null);
  const [workflowBusy, setWorkflowBusy] = useState(false);
  const [previewDocModal, setPreviewDocModal] = useState<{ url: string; title: string } | null>(null);

  // "Send for Approval" popup — 3 tabs: Job Details, Select Approver(s), Send History.
  const [submitTab, setSubmitTab] = useState<'details' | 'approvers' | 'history'>('details');
  const [approverList, setApproverList] = useState<
    { id: number; name: string; email: string; department: string; employee_id: string; status: string; role: string }[]
  >([]);
  const [approverSearch, setApproverSearch] = useState('');
  const [selectedApproverIds, setSelectedApproverIds] = useState<number[]>([]);
  const [approversLoading, setApproversLoading] = useState(false);
  const [approvalHistory, setApprovalHistory] = useState<any[]>([]);
  const [historyLoading, setHistoryLoading] = useState(false);

  const loadApprovalHistory = useCallback(async (jobId: number) => {
    setHistoryLoading(true);
    try {
      const res = (await api.get(`/jds/${jobId}/approval-requests/`)) as any;
      const historyList = Array.isArray(res?.data) ? res.data : [];
      setApprovalHistory(historyList);
      return historyList;
    } catch {
      setApprovalHistory([]);
      return [];
    } finally {
      setHistoryLoading(false);
    }
  }, []);

  const openSubmitModal = async (job: Job) => {
    setSubmitJob(job);
    setSubmitTab('details');
    setSelectedApproverIds([]);
    setApproverSearch('');
    setApprovalHistory([]);
    setApproversLoading(true);
    const historyPromise = loadApprovalHistory(job.id);
    try {
      const res = (await api.get('/jds/approvers/')) as any;
      const list = Array.isArray(res?.data) ? res.data : [];
      const mapped = list.map((u: any) => ({
        id: u.id,
        name: u.name || (u.email ? u.email.split('@')[0] : '—'),
        email: u.email || '',
        department: u.department || '',
        employee_id: u.employee_id || '',
        status: u.status || (u.is_active === false ? 'Inactive' : 'Active'),
        role: u.role || '',
      }));
      setApproverList(mapped);

      // Pre-check whoever this JD was previously sent to, but ONLY if they're
      // still a currently eligible/active approver — a stale ID from someone
      // who's since been deactivated or lost the approver role would still
      // get submitted (invisibly, since they no longer show a row/checkbox)
      // and the backend would reject the whole request as "not a valid
      // Hiring Manager / approver".
      const historyList = await historyPromise;
      const eligibleIds = new Set(mapped.map((a: any) => a.id));
      const prevApproverIds = Array.from(
        new Set(historyList.map((h: any) => h.approver_id).filter(Boolean))
      ).filter((id) => eligibleIds.has(id as number)) as number[];
      if (prevApproverIds.length > 0) {
        setSelectedApproverIds(prevApproverIds);
      }
    } catch {
      setApproverList([]);
      toast.error('Could not load hiring managers.');
    } finally {
      setApproversLoading(false);
    }
  };

  const doSubmitApproval = async () => {
    if (!submitJob) return;
    if (selectedApproverIds.length === 0) {
      toast.warn('Select at least one Hiring Manager to send the approval request to.');
      return;
    }
    const count = selectedApproverIds.length;
    // Sending fires a real email to each selected Hiring Manager, so confirm
    // before actually doing it rather than sending on the first click.
    await showConfirmDelete(
      `Send this Job Description for approval to ${count} Hiring Manager${count > 1 ? 's' : ''}? An email will be sent to ${count > 1 ? 'each of them' : 'them'}.`,
      async () => {
        setWorkflowBusy(true);
        try {
          await api.post(`/jds/${submitJob.id}/submit-approval/`, { approver_ids: selectedApproverIds });
          toast.success(`Sent for approval to ${count} approver${count > 1 ? 's' : ''} ✓`);
          setSubmitJob(null);
          loadAll();
        } catch (err: any) {
          toast.error(err.response?.data?.message || err.message || 'Submission failed.');
        } finally {
          setWorkflowBusy(false);
        }
      }
    );
  };

  // Independent loading states so each button only shows ITS OWN spinner.
  // (Both stay disabled during a request to prevent conflicting actions,
  // but only the clicked one shows the processing state.)
  const [isApproving, setIsApproving] = useState(false);
  const [isRejecting, setIsRejecting] = useState(false);
  const reviewBusy = isApproving || isRejecting;

  const doApprove = async () => {
    if (!reviewJob || isApproving || isRejecting) return;   // no duplicate/parallel requests
    setIsApproving(true);
    try {
      await api.post(`/jds/${reviewJob.id}/approve/`, {});
      toast.success('Job description approved ✓');
      setReviewJob(null);
      loadAll();
    } catch (err: any) {
      // 409 = another approver already approved this JD (first-approver-wins).
      // Close and refresh so the page reflects the final approved state.
      if (err.response?.status === 409) {
        toast.info(err.response?.data?.message || 'This Job Description has already been approved.');
        setReviewJob(null);
        loadAll();
      } else {
        // Keep the popup open so the approver can retry or adjust.
        toast.error(err.response?.data?.message || 'Approval failed.');
      }
    } finally {
      setIsApproving(false);
    }
  };

  const doReject = async () => {
    if (!reviewJob || isApproving || isRejecting) return;   // no duplicate/parallel requests
    if (!reviewReason.trim()) {
      toast.warn('Please write why this JD is being rejected.');
      return;
    }
    setIsRejecting(true);
    try {
      await api.post(`/jds/${reviewJob.id}/reject/`, { reason: reviewReason.trim() });
      toast.success('Job description rejected ✓');
      setReviewJob(null);
      loadAll();
    } catch (err: any) {
      // 409 = another approver already approved this JD, so it can no longer be
      // rejected (first-approver-wins). Close and refresh to the final state.
      if (err.response?.status === 409) {
        toast.info(err.response?.data?.message || 'This Job Description has already been approved.');
        setReviewJob(null);
        loadAll();
      } else {
        // Keep the popup open so the approver can retry or adjust.
        toast.error(err.response?.data?.message || 'Rejection failed.');
      }
    } finally {
      setIsRejecting(false);
    }
  };

  // Candidate assignment (multi-select) — per JD
  const [assignCandJob, setAssignCandJob] = useState<Job | null>(null);
  const [candTab, setCandTab] = useState<'select' | 'assigned'>('select');
  const [candList, setCandList] = useState<any[]>([]);
  const [candSearch, setCandSearch] = useState('');
  const [candPage, setCandPage] = useState(1);
  const [candTotal, setCandTotal] = useState(0);
  const [candListLoading, setCandListLoading] = useState(false);
  const [selectedCandIds, setSelectedCandIds] = useState<number[]>([]);
  const [assignedApps, setAssignedApps] = useState<any[]>([]);
  const [assignedPage, setAssignedPage] = useState(1);
  const [assignedTotal, setAssignedTotal] = useState(0);
  const [assignedLoading, setAssignedLoading] = useState(false);
  const [candModalLoading, setCandModalLoading] = useState(false);
  const [candAssigning, setCandAssigning] = useState(false);
  // candidate_id -> JDs ({id, title}) the candidate is already assigned to (any JD)
  const [candJdMap, setCandJdMap] = useState<Record<number, { id: number; title: string }[]>>({});
  const CAND_PAGE_SIZE = 10;

  // API responses are paginated ({count, results}) — unwrap defensively.
  const unwrapList = (res: any): any[] => {
    const d = res?.data?.results ?? res?.data?.data?.results ?? res?.data?.data ?? res?.data ?? res ?? [];
    return Array.isArray(d) ? d : [];
  };
  const unwrapCount = (res: any): number =>
    res?.data?.count ?? res?.data?.data?.count ?? 0;

  // Server-side paginated assigned list for the Assigned Candidates tab.
  const loadAssignedApps = async (jobId: number, page = 1) => {
    setAssignedLoading(true);
    try {
      const res = (await api.get(`/pipeline/applications/?job=${jobId}&page=${page}&page_size=${CAND_PAGE_SIZE}`)) as any;
      setAssignedApps(unwrapList(res));
      setAssignedTotal(unwrapCount(res));
      setAssignedPage(page);
    } finally {
      setAssignedLoading(false);
    }
  };

  // Server-side paginated candidate list for the Select Candidates tab.
  const loadCandidatesPage = async (page: number, search: string, jobId?: number) => {
    setCandListLoading(true);
    try {
      const params = new URLSearchParams({ page: String(page), page_size: String(CAND_PAGE_SIZE) });
      if (search.trim()) params.set('search', search.trim());
      const excludeJdId = jobId ?? assignCandJob?.id;
      if (excludeJdId) params.set('exclude_job', String(excludeJdId));
      const res = (await api.get(`/candidates/?${params.toString()}`)) as any;
      setCandList(unwrapList(res));
      setCandTotal(unwrapCount(res));
      setCandPage(page);
    } catch {
      toast.error('Failed to load candidates');
    } finally {
      setCandListLoading(false);
    }
  };

  // Debounced server-side search — resets to page 1. Skips the run caused by the
  // modal opening (openAssignCandidates already loads page 1).
  const candSearchSkip = useRef(true);
  useEffect(() => {
    if (!assignCandJob) {
      candSearchSkip.current = true;
      return;
    }
    if (candSearchSkip.current) {
      candSearchSkip.current = false;
      return;
    }
    const t = setTimeout(() => loadCandidatesPage(1, candSearch, assignCandJob.id), 400);
    return () => clearTimeout(t);
  }, [candSearch, assignCandJob]);

  const openAssignCandidates = async (job: Job) => {
    setAssignCandJob(job);
    setCandTab('select');
    setSelectedCandIds([]);
    setCandSearch('');
    setCandList([]);
    setCandPage(1);
    setCandTotal(0);
    setAssignedApps([]);
    setAssignedPage(1);
    setAssignedTotal(0);
    setCandModalLoading(true);
    try {
      const [allAppsRes] = await Promise.all([
        api.get('/pipeline/applications/?page_size=500') as any,
        loadAssignedApps(job.id),
        loadCandidatesPage(1, '', job.id),
      ]);
      // Build candidate -> assigned JDs map (across ALL JDs)
      const map: Record<number, { id: number; title: string }[]> = {};
      unwrapList(allAppsRes).forEach((a: any) => {
        if (!map[a.candidate]) map[a.candidate] = [];
        map[a.candidate].push({ id: a.job, title: a.job_title || `JD #${a.job}` });
      });
      setCandJdMap(map);
    } catch {
      toast.error('Failed to load candidates');
    } finally {
      setCandModalLoading(false);
    }
  };

  const handleAssignCandidates = async () => {
    if (!assignCandJob || selectedCandIds.length === 0) return;
    setCandAssigning(true);
    try {
      const res = (await api.post('/pipeline/applications/bulk-assign/', {
        job: assignCandJob.id,
        candidate_ids: selectedCandIds,
      })) as any;
      const created = res?.data?.created ?? [];
      const skipped = res?.data?.skipped ?? [];
      toast.success(
        `${created.length} candidate${created.length === 1 ? '' : 's'} assigned ✓` +
        (skipped.length ? ` (${skipped.length} already assigned)` : '')
      );
      setSelectedCandIds([]);
      // Filter out newly assigned candidates immediately
      if (created.length > 0) {
        setCandList((prev) => prev.filter((c) => !created.includes(c.id)));
      }
      // Bump the row's candidate count without a full refetch
      if (created.length > 0) {
        setJobs((prev) =>
          prev.map((j) =>
            j.id === assignCandJob.id
              ? { ...j, candidates_count: (j.candidates_count ?? 0) + created.length }
              : j
          )
        );
        // Reflect the new assignments in the "In JD?" badges without a refetch
        setCandJdMap((prev) => {
          const next = { ...prev };
          created.forEach((cid: number) => {
            const list = next[cid] ? [...next[cid]] : [];
            if (!list.some((j) => j.id === assignCandJob.id)) {
              list.push({ id: assignCandJob.id, title: assignCandJob.title });
            }
            next[cid] = list;
          });
          return next;
        });
      }
      await Promise.all([
        loadAssignedApps(assignCandJob.id),
        loadCandidatesPage(candPage, candSearch, assignCandJob.id),
      ]);
      setCandTab('assigned');
    } catch (err) {
      toast.error(err instanceof Error ? err.message : 'Assignment failed');
    } finally {
      setCandAssigning(false);
    }
  };

  const handleRemoveCandidate = async (appId: number, candidateId: number) => {
    if (!assignCandJob) return;

    const result = await showConfirmDelete(
      'Remove this candidate from this job pipeline? The stage history and interview details for this job order will be deleted.'
    );
    if (!result.isConfirmed) return;

    try {
      await api.delete(`/pipeline/applications/${appId}/`);
      toast.success('Candidate removed from pipeline');

      // Update jobs list candidate count in the parent table row
      setJobs((prev) =>
        prev.map((j) =>
          j.id === assignCandJob.id
            ? { ...j, candidates_count: Math.max(0, (j.candidates_count ?? 0) - 1) }
            : j
        )
      );

      // Remove from the candJdMap locally so badges update
      setCandJdMap((prev) => {
        const next = { ...prev };
        if (next[candidateId]) {
          next[candidateId] = next[candidateId].filter((j) => j.id !== assignCandJob.id);
        }
        return next;
      });

      // Reload both lists to sync with server
      let nextAssignedPage = assignedPage;
      if (assignedApps.length === 1 && assignedPage > 1) {
        nextAssignedPage = assignedPage - 1;
      }
      await Promise.all([
        loadAssignedApps(assignCandJob.id, nextAssignedPage),
        loadCandidatesPage(candPage, candSearch, assignCandJob.id),
      ]);
    } catch (err) {
      toast.error(err instanceof Error ? err.message : 'Could not remove candidate');
    }
  };

  const candidateColumns = [
    {
      id: 'srNo',
      header: 'S.No.',
      cell: ({ row, table }: any) => {
        const pageIndex = table.getState().pagination.pageIndex;
        const pageSize = table.getState().pagination.pageSize;
        return <span className="font-semibold text-slate-500 dark:text-slate-400">{pageIndex * pageSize + row.index + 1}</span>;
      },
    },
    {
      accessorKey: 'id',
      header: 'Job ID',
      cell: ({ row }: any) => (
        <span className="inline-flex items-center px-2 py-0.5 rounded-none bg-[#405189]/10 text-[#405189] dark:bg-indigo-950/40 dark:text-indigo-300 text-xs font-extrabold">
          {row.original.id}
        </span>
      ),
    },
    {
      accessorKey: 'title',
      header: 'Job Title',
      cell: ({ row }: any) => {
        const job = row.original as Job;
        return (
          <div className="min-w-[220px]">
            <a
              href={`/jobs/${job.id}`}
              onClick={(e) => {
                e.preventDefault();
                setViewJob(job);
              }}
              title="View JD details"
              className="font-extrabold text-[#405189] dark:text-indigo-300 hover:underline text-sm whitespace-nowrap text-left cursor-pointer"
            >
              {job.title}
            </a>
          </div>
        );
      },
    },
    {
      accessorKey: 'location',
      header: 'Location',
      cell: ({ row }: any) => {
        const job = row.original;
        return (
          <span className="text-xs text-indigo-650 dark:text-indigo-400 font-bold flex items-center gap-1.5 min-w-[130px] whitespace-nowrap">
            <i className="fa-solid fa-location-dot"></i> {job.location}
          </span>
        );
      },
    },
    {
      id: 'appliedDate',
      header: 'Applied Date',
      cell: ({ row }: any) => {
        const job = row.original;
        const appliedApp = myApps.find((app: any) => app.job_id === job.id);
        const hasApplied = !!appliedApp;

        if (hasApplied) {
          const appliedDate = appliedApp?.applied_at
            ? new Date(appliedApp.applied_at).toLocaleDateString('en-IN', { day: 'numeric', month: 'short', year: 'numeric' })
            : null;
          return <span className="text-xs text-slate-600 dark:text-slate-300 whitespace-nowrap">{appliedDate || '-'}</span>;
        }
        return <span className="text-xs text-slate-400 dark:text-slate-500">-</span>;
      },
    },
    {
      id: 'appliedStatus',
      header: 'Status',
      cell: ({ row }: any) => {
        const job = row.original;
        const appliedApp = myApps.find((app: any) => app.job_id === job.id);
        const hasApplied = !!appliedApp;
        const isApplying = applyingJobId === job.id;

        if (hasApplied) {
          return (
            <span className="inline-flex items-center px-2.5 py-1 rounded-full text-xs font-bold bg-emerald-50 dark:bg-emerald-950/50 text-emerald-700 dark:text-emerald-400 border border-emerald-250 dark:border-emerald-800">
              <i className="fa-solid fa-circle-check mr-1"></i> Applied
            </span>
          );
        }

        return (
          <button
            onClick={() => setApplyPreviewJob(job)}
            disabled={isApplying}
            className="inline-flex items-center gap-1.5 text-xs font-bold bg-[#405189] hover:bg-[#334267] text-white px-3 py-1.5 rounded-none shadow transition cursor-pointer disabled:opacity-40 disabled:cursor-not-allowed"
          >
            {isApplying ? (
              <>
                <i className="fa-solid fa-spinner fa-spin text-[10px]" />
                <span>Applying...</span>
              </>
            ) : (
              <>
                <i className="fa-solid fa-paper-plane text-[10px]" />
                <span>Apply</span>
              </>
            )}
          </button>
        );
      },
    },
  ];

  const columns = user?.role === 'CANDIDATE' ? candidateColumns : [
    {
      id: 'select',
      enableSorting: false,
      header: ({ table }: any) => (
        <SelectCheckbox
          ariaLabel="Select all jobs"
          checked={table.getIsAllPageRowsSelected()}
          indeterminate={table.getIsSomePageRowsSelected()}
          onChange={table.getToggleAllPageRowsSelectedHandler()}
        />
      ),
      cell: ({ row }: any) =>
        row.getCanSelect() ? (
          <SelectCheckbox
            ariaLabel={`Select ${row.original.title}`}
            checked={row.getIsSelected()}
            onChange={row.getToggleSelectedHandler()}
          />
        ) : (
          // Published/Closed JDs can't be deleted, so no checkbox — avoids
          // "select all → delete" looking like it covers every record.
          <span className="block w-4" title="Published/Closed JDs cannot be deleted" />
        ),
    },
    {
      id: 'srNo',
      header: 'S.No.',
      cell: ({ row, table }: any) => {
        const pageIndex = table.getState().pagination.pageIndex;
        const pageSize = table.getState().pagination.pageSize;
        return <span className="font-semibold text-slate-500 dark:text-slate-400">{pageIndex * pageSize + row.index + 1}</span>;
      },
    },
    {
      accessorKey: 'id',
      header: 'Job ID',
      cell: ({ row }: any) => (
        <span className="inline-flex items-center px-2 py-0.5 rounded-none bg-[#405189]/10 text-[#405189] dark:bg-indigo-950/40 dark:text-indigo-300 text-xs font-extrabold">
          {row.original.id}
        </span>
      ),
    },
    {
      accessorKey: 'title',
      header: 'Job Title',
      cell: ({ row }: any) => {
        const job = row.original as Job;
        return (
          <div className="min-w-[220px]">
            <a
              href={`/jobs/${job.id}`}
              onClick={(e) => {
                e.preventDefault();
                setViewJob(job);
              }}
              title="View JD details"
              className="font-extrabold text-[#405189] dark:text-indigo-300 hover:underline text-sm whitespace-nowrap text-left cursor-pointer"
            >
              {job.title}
            </a>

            <p className="text-[10px] text-slate-400 mt-0.5">Created on {formatDate(job.created_at)}</p>

          </div>
        );
      },
    },
    {
      accessorKey: 'location',
      header: 'Location',
      cell: ({ row }: any) => {
        const job = row.original;
        return (
          <span className="text-xs text-indigo-650 dark:text-indigo-400 font-bold flex items-center gap-1.5 min-w-[130px] whitespace-nowrap">
            <i className="fa-solid fa-location-dot"></i> {job.location}
          </span>
        );
      },
    },
    {
      accessorKey: 'client_name',
      header: 'Client / Division',
      cell: ({ row }: any) => {
        const job = row.original;
        return job.client_name ? (
          <span className="text-xs font-bold text-slate-705 dark:text-slate-350 flex items-center gap-1.5 min-w-[150px] whitespace-nowrap">
            <i className="fa-solid fa-building text-slate-400 text-xs"></i> {job.client_name}
          </span>
        ) : (
          <span className="text-slate-400 font-normal italic inline-block min-w-[150px] whitespace-nowrap">Internal Job</span>
        );
      },
    },
    {
      accessorKey: 'created_by_email',
      header: 'Created By',
      cell: ({ row }: any) => {
        const job = row.original;
        // Show the person's name; hover/touch reveals the email
        return <span title={job.created_by_email} className="text-slate-650 dark:text-slate-400 font-semibold cursor-default inline-block min-w-[150px] whitespace-nowrap">{job.created_by_name || job.created_by_email}</span>;
      },
    },
    {
      accessorKey: 'status',
      header: 'Status',
      cell: ({ row }: any) => {
        const job = row.original as Job;
        // Single canonical status. Prefer the backend `jd_status`; fall back to
        // deriving it from the legacy status/approval_status pair so the badge is
        // correct even against older API responses.
        const appStatus = (job.approval_status || '').toUpperCase();
        const canonical = job.jd_status
          || (job.status === 'Published' ? 'published'
            : job.status === 'Closed' ? 'closed'
              : appStatus === 'PENDING_APPROVAL' ? 'pending_approval'
                : 'draft');

        const STYLES: Record<string, { label: string; style: string }> = {
          published: { label: 'Published', style: 'bg-emerald-50 dark:bg-emerald-950/50 text-emerald-700 dark:text-emerald-400 border-emerald-200 dark:border-emerald-800' },
          pending_approval: { label: 'Pending Approval', style: 'bg-yellow-50 dark:bg-yellow-950/50 text-yellow-700 dark:text-yellow-400 border-yellow-200 dark:border-yellow-800' },
          closed: { label: 'Closed', style: 'bg-slate-100 dark:bg-slate-800 text-slate-600 dark:text-slate-400 border-slate-200 dark:border-slate-700' },
          draft: { label: 'Draft', style: 'bg-amber-50 dark:bg-amber-950/50 text-amber-700 dark:text-amber-400 border-amber-200 dark:border-amber-800' },
        };
        const meta = STYLES[canonical] ?? STYLES.draft;

        return (
          <div className="flex flex-col gap-1">
            <span className="inline-flex items-center gap-1.5 w-max">
              <span className={`text-xs px-2.5 py-1 rounded-full font-bold border ${meta.style}`}>
                {meta.label}
              </span>
              {canonical === 'pending_approval' && (
                <span className="text-[9px] px-1.5 py-0.5 rounded-none font-black uppercase tracking-wider bg-orange-500 text-white animate-pulse" title="Awaiting review">
                  NEW
                </span>
              )}
            </span>
            {/* A rejected JD returns to Draft; keep the reviewer's reason visible
                as feedback (not a second status badge). */}
            {canonical === 'draft' && appStatus === 'REJECTED' && job.rejection_reason && (
              <span className="text-[9px] text-red-500 max-w-[160px] truncate" title={job.rejection_reason}>
                Rejected: "{job.rejection_reason}"
              </span>
            )}
          </div>
        );
      },
    },
    {
      id: 'assigned_recruiters',
      header: 'Assigned Recruiters',
      cell: ({ row }: any) => {
        const job = row.original as Job;
        const assigned = job.assigned_recruiters ?? [];
        return (
          <div className="flex items-center gap-2">
            {!canAssignRecruiters && !canAssignCandidates && (
              <span className="text-[11px] font-bold text-slate-500 dark:text-slate-400">
                Users ({assigned.length}) · Candidates ({job.candidates_count ?? 0})
              </span>
            )}
            <span className="inline-flex items-center gap-1.5">
              {canAssignCandidates && (
                <button
                  onClick={() => openAssignCandidates(job)}
                  disabled={job.status !== 'Published'}
                  title={job.status !== 'Published' ? 'JD must be Published to assign' : 'Assign candidates'}
                  className="inline-flex items-center gap-1.5 text-[11px] font-bold text-emerald-600 dark:text-emerald-400 hover:text-white hover:bg-emerald-600 dark:hover:bg-emerald-600 border border-emerald-200 dark:border-emerald-900/50 rounded-none px-2.5 py-1 transition cursor-pointer whitespace-nowrap disabled:opacity-40 disabled:cursor-not-allowed disabled:hover:bg-transparent disabled:hover:text-emerald-600 dark:disabled:hover:text-emerald-400"
                >
                  <i className="fa-solid fa-user-check text-[10px]" /> Assign Candidates ({job.candidates_count ?? 0})
                </button>
              )}
              {canAssignRecruiters && (
                <button
                  onClick={() => openAssignModal(job)}
                  disabled={job.status !== 'Published'}
                  title={job.status !== 'Published' ? 'JD must be Published to assign' : 'Assign recruiters'}
                  className="inline-flex items-center gap-1.5 text-[11px] font-bold text-indigo-600 dark:text-indigo-400 hover:text-white hover:bg-indigo-600 dark:hover:bg-indigo-600 border border-indigo-200 dark:border-indigo-900/50 rounded-none px-2.5 py-1 transition cursor-pointer whitespace-nowrap disabled:opacity-40 disabled:cursor-not-allowed disabled:hover:bg-transparent disabled:hover:text-indigo-600 dark:disabled:hover:text-indigo-400"
                >
                  <i className="fa-solid fa-user-plus text-[10px]" /> Assign Recruiters ({assigned.length})
                </button>
              )}
            </span>
          </div>
        );
      },
    },
    {
      accessorKey: 'created_at',
      header: 'Created',
      cell: ({ row }: any) => (
        <span className="text-xs text-slate-500 dark:text-slate-400 font-semibold whitespace-nowrap">
          {formatDate(row.original.created_at)}
        </span>
      ),
    },
    {
      accessorKey: 'updated_at',
      header: 'Updated',
      cell: ({ row }: any) => (
        <span className="text-xs text-slate-500 dark:text-slate-400 font-semibold whitespace-nowrap">
          {formatDate(row.original.updated_at)}
        </span>
      ),
    },
    {
      id: 'approval',
      header: () => <div className="text-center whitespace-nowrap">for Approval</div>,
      cell: ({ row }: any) => {
        const job = row.original;
        const uRole = (user?.role ?? '').toUpperCase();
        const isApprover = uRole === 'ADMIN' || uRole === 'HIRING_MANAGER';

        // Workflow buttons STAY visible through the whole approval lifecycle
        // and just disable once their action no longer applies — they never vanish.
        const appStatus = job.approval_status || 'DRAFT';
        const canSubmit = appStatus === 'DRAFT' || appStatus === 'REJECTED';
        const canReview = appStatus !== 'DRAFT';   // pending / approved / rejected → open to view or act
        const submitTitle = canSubmit
          ? 'Send this JD for approval'
          : appStatus === 'PENDING_APPROVAL' ? 'Already submitted for approval'
            : appStatus === 'APPROVED' ? 'Already approved'
              : 'Cannot submit';
        const reviewTitle = canReview ? 'Open review' : 'Not submitted for approval yet';

        return (
          <div className="flex items-center justify-center gap-1.5">
            {/* Send Approve → opens approval popup. Hidden for approvers. */}
            {!isApprover && (
              <button
                onClick={() => openSubmitModal(job)}
                title="Send for approval / View approval details"
                className="inline-flex items-center gap-1.5 text-[11px] font-bold bg-yellow-50 hover:bg-yellow-100 text-yellow-700 dark:bg-yellow-950/40 dark:hover:bg-yellow-900/50 dark:text-yellow-400 border border-yellow-250 dark:border-yellow-900/50 rounded-lg px-2.5 py-1.5 transition cursor-pointer"
              >
                <i className="fa-solid fa-paper-plane text-[10px]" />
                <span className="whitespace-nowrap">Send Approve</span>
              </button>
            )}

            {/* Review → opens the review modal (approve / reject with reason).
                Highlighted while the JD is awaiting review so approvers can
                spot pending items at a glance. */}
            {isApprover && (
              <button
                disabled={!canReview}
                onClick={() => { setReviewReason(job.rejection_reason || ''); setReviewTab('approval'); setReviewJob(job); }}
                title={reviewTitle}
                className={`inline-flex items-center gap-1.5 text-[11px] font-bold rounded-lg px-2.5 py-1.5 transition cursor-pointer disabled:opacity-40 disabled:cursor-not-allowed ${appStatus === 'PENDING_APPROVAL'
                  ? 'bg-orange-500 hover:bg-orange-600 text-white border border-orange-500 shadow-sm shadow-orange-500/30'
                  : appStatus === 'REJECTED'
                    ? 'text-red-500 dark:text-red-400 border border-red-200 dark:border-red-900/50 hover:bg-red-500 hover:text-white'
                    : 'text-indigo-600 dark:text-indigo-400 hover:text-white hover:bg-indigo-600 dark:hover:bg-indigo-600 border border-indigo-200 dark:border-indigo-900/50 disabled:hover:bg-transparent disabled:hover:text-indigo-600 dark:disabled:hover:text-indigo-400'
                  }`}
              >
                <i className="fa-solid fa-gavel text-[10px]" /> Review
              </button>
            )}
          </div>
        );
      },
    },
    {
      id: 'actions',
      header: () => <div className="text-right">Actions</div>,
      cell: ({ row }: any) => {
        const job = row.original;
        return (
          <div className="flex items-center justify-end gap-1.5">
            {/* View — opens the same JD Details popup as clicking the Job Title */}
            <button
              onClick={() => setViewJob(job)}
              title="View JD details"
              className="w-9 h-9 rounded-none flex items-center justify-center bg-slate-50 hover:bg-slate-100 text-slate-600 dark:bg-slate-800/60 dark:hover:bg-slate-700 dark:text-slate-300 transition cursor-pointer"
            >
              <i className="fa-solid fa-eye text-[13px]" />
            </button>
            {/* Pipeline — enabled for Published JDs, disabled otherwise */}
            <button
              onClick={() => { if (job.status === 'Published') router.push(`/jobs/${job.id}/pipeline`); }}
              disabled={job.status !== 'Published'}
              title={job.status === 'Published' ? 'View candidate pipeline' : 'Publish this JD to manage its candidate pipeline'}
              className={`w-9 h-9 rounded-none flex items-center justify-center transition ${job.status === 'Published'
                ? 'bg-emerald-50 hover:bg-emerald-100 text-emerald-600 dark:bg-emerald-950/40 dark:hover:bg-emerald-900/50 dark:text-emerald-400 cursor-pointer'
                : 'bg-slate-50 text-slate-300 dark:bg-slate-800/50 dark:text-slate-600 cursor-not-allowed'
                }`}
            >
              <i className="fa-solid fa-diagram-project text-[13px]" />
            </button>
            {/* Job Post — only Published (approved) JDs can be posted externally */}
            {canJobPost && (
              <button
                onClick={() => openPublishModal(job)}
                disabled={job.status !== 'Published'}
                title={job.status === 'Published'
                  ? 'Preview JD and select platforms to publish'
                  : 'This Job Description must be approved and published before it can be posted to external job portals.'}
                className={`h-9 px-3 rounded-none flex items-center justify-center gap-1.5 text-xs font-bold transition ${job.status === 'Published'
                  ? 'bg-violet-50 hover:bg-violet-100 text-violet-600 dark:bg-violet-950/40 dark:hover:bg-violet-900/50 dark:text-violet-400 cursor-pointer'
                  : 'bg-slate-50 text-slate-300 dark:bg-slate-800/50 dark:text-slate-600 cursor-not-allowed'
                  }`}
              >
                <i className="fa-solid fa-bullhorn text-[13px]" /> Post
              </button>
            )}
            {/* Copy is available for every JD regardless of status */}
            <button
              onClick={() => handleCopy(job)}
              disabled={copyingId === job.id}
              title="Copy JD"
              className="w-9 h-9 rounded-none flex items-center justify-center bg-indigo-50 hover:bg-indigo-100 text-indigo-600 dark:bg-indigo-950/40 dark:hover:bg-indigo-900/50 dark:text-indigo-400 transition cursor-pointer disabled:opacity-40 disabled:cursor-not-allowed"
            >
              {copyingId === job.id ? (
                <i className="fa-solid fa-spinner animate-spin text-[13px]" />
              ) : (
                <i className="fa-solid fa-copy text-[13px]" />
              )}
            </button>
            {/* Agent — create or manage Hunar AI Agent for this JD */}
            <button
              onClick={() => openAgentModal(job)}
              title={job.hunar_agent_id ? 'Manage Hunar AI Agent' : 'Create Hunar AI Agent'}
              className="w-9 h-9 rounded-none flex items-center justify-center bg-[#405189]/10 hover:bg-[#405189]/20 text-[#405189] dark:bg-indigo-950/40 dark:hover:bg-indigo-900/50 dark:text-indigo-300 transition cursor-pointer relative"
            >
              <i className="fa-solid fa-robot text-[13px]" />
              {job.hunar_agent_id && (
                <span className="absolute top-1 right-1 w-2 h-2 rounded-full bg-emerald-500 shadow-sm" title="Active Hunar AI Agent Linked" />
              )}
            </button>
            <DataTableActions
              onEdit={hasChangePermission ? () => openEditModal(job) : undefined}
              editDisabled={job.status === 'Published'}
              editDisabledTitle="This JD is published and cannot be edited"
              onDelete={hasDeletePermission ? () => handleDelete(job.id) : undefined}
              deleteDisabled={job.status !== 'Draft'}
              deleteDisabledTitle="Only Draft JDs can be deleted"
            />
          </div>
        );
      },
    },
  ];

  // Form fields
  const [editingJobId, setEditingJobId] = useState<number | null>(null);
  const [title, setTitle] = useState('');
  const [department, setDepartment] = useState('');
  const [location, setLocation] = useState('');
  const [experienceBand, setExperienceBand] = useState('');
  const [ctcBand, setCtcBand] = useState('');
  const [noticePeriod, setNoticePeriod] = useState('');
  const [shift, setShift] = useState('');
  const [mustHaveSkills, setMustHaveSkills] = useState('');
  const [goodToHaveSkills, setGoodToHaveSkills] = useState('');
  const [qualifications, setQualifications] = useState('');
  const [workingDays, setWorkingDays] = useState('');
  const [numPositions, setNumPositions] = useState('');
  const [certification, setCertification] = useState('');
  const [questions, setQuestions] = useState<{ question: string; answer: string }[]>([]);
  const [activeJobTab, setActiveJobTab] = useState<'details' | 'questions'>('details');
  const [attachment, setAttachment] = useState<File | null>(null);
  const [existingAttachment, setExistingAttachment] = useState<string | null>(null);
  const [parsing, setParsing] = useState(false);
  const [dragOver, setDragOver] = useState(false);
  const [parsingQa, setParsingQa] = useState(false);
  const [qaDragOver, setQaDragOver] = useState(false);
  const [qaFile, setQaFile] = useState<File | null>(null);
  const [workDetails, setWorkDetails] = useState('');
  const [status, setStatus] = useState<'Draft' | 'Published' | 'Closed'>('Draft');
  const [originalStatus, setOriginalStatus] = useState<'Draft' | 'Published' | 'Closed' | null>(null);
  const statusOptions = status === 'Published'
    ? [
      { value: 'Published', label: 'Published' },
      { value: 'Closed', label: 'Closed' },
    ]
    : status === 'Closed'
      ? [
        { value: 'Closed', label: 'Closed' },
      ]
      : [
        { value: 'Draft', label: 'Draft' },
        { value: 'Published', label: 'Published' },
        { value: 'Closed', label: 'Closed' },
      ];
  // JD lifecycle: the Status dropdown stays locked until the JD is approved
  // (approval auto-publishes it). Pre-workflow Published JDs count as approved.
  const [editingApproved, setEditingApproved] = useState(false);
  const [priority, setPriority] = useState<'High' | 'Medium' | 'Low'>('Medium');
  const [clientId, setClientId] = useState<string>('');
  const [submitting, setSubmitting] = useState(false);
  const [formError, setFormError] = useState('');
  const [titleError, setTitleError] = useState('');
  const [copyingId, setCopyingId] = useState<number | null>(null);

  const [publishJob, setPublishJob] = useState<Job | null>(null);
  const [publishStep, setPublishStep] = useState<'preview' | 'confirm' | 'results' | null>(null);
  const [publishChannels, setPublishChannels] = useState<string[]>([]);
  const [publishResults, setPublishResults] = useState<PublishResult[]>([]);
  const [posting, setPosting] = useState(false);
  const [forceRepost, setForceRepost] = useState(false);
  // Read-only pre-publish preview of the application URL per platform.
  const [previewLinks, setPreviewLinks] = useState<PreviewLink[] | null>(null);
  const [previewLoading, setPreviewLoading] = useState(false);
  const [copiedLink, setCopiedLink] = useState<string | null>(null);

  const [asyncClientsLoading, setAsyncClientsLoading] = useState(false);
  const handleClientSearch = async (query: string) => {
    setAsyncClientsLoading(true);
    try {
      const res = await api.get(`/clients/?search=${encodeURIComponent(query)}`) as any;
      const clientsData = res.data;
      if (Array.isArray(clientsData)) {
        setClients(clientsData);
      } else if (clientsData && Array.isArray(clientsData.results)) {
        setClients(clientsData.results);
      } else {
        setClients([]);
      }
    } catch (e) {
      console.error('Failed to search clients', e);
    } finally {
      setAsyncClientsLoading(false);
    }
  };

  const isAdmin = user?.role === 'ADMIN';
  const hasAddPermission = isAdmin || user?.permissions?.includes('jobs.add_jobdescription') || false;
  const hasChangePermission = isAdmin || user?.permissions?.includes('jobs.change_jobdescription') || false;
  const hasDeletePermission = isAdmin || user?.permissions?.includes('jobs.delete_jobdescription') || false;
  // Admins/managers may assign recruiters, plus any role granted the
  // jd-recruiter-assignment permission from Groups & Permissions.
  const canAssignRecruiters = isAdmin || (user?.role ?? '').toUpperCase().includes('MANAGER') || user?.permissions?.includes('jobs.add_jdrecruiterassignment') || false;
  // Check if user can assign candidates: either admin/manager OR has the jdcandidateassignment permission
  const canAssignCandidates = isAdmin || (user?.role ?? '').toUpperCase().includes('MANAGER') || user?.permissions?.includes('jobs.add_jdcandidateassignment') || false;
  // Job Post action — visible to admins/managers and any role granted the job-posting view permission.
  // Mirrors the backend gate on /jobs/{id}/post/ (manager/admin role or the
  // job-posting permission from Groups & Permissions).
  const canJobPost = isAdmin
    || (user?.role ?? '').toUpperCase().includes('MANAGER')
    || user?.permissions?.includes('jobs.view_jobposting')
    || user?.permissions?.includes('jobs.add_jobposting')
    || false;

  // Build the server-side JD query from the current page + applied filters.
  const buildJobQuery = () => {
    const p = new URLSearchParams();
    p.set('page', String(pagination.pageIndex + 1));
    p.set('page_size', String(pagination.pageSize));
    if (appliedJdName.trim()) p.set('jd_name', appliedJdName.trim());
    if (appliedJdId.trim()) p.set('jd_id', appliedJdId.trim());
    if (appliedSkills.length > 0) {
      p.set('skills', appliedSkills.join(','));
      p.set('skill_match', appliedSkillMatchMode);
    }
    if (appliedStatus && appliedStatus !== 'ALL') p.set('status', appliedStatus);
    // Deep-link focus (?ids=…) — show only those JDs (e.g. from a review link).
    if (focusIds && focusIds.length > 0) {
      p.set('ids', focusIds.join(','));
      p.set('page_size', String(Math.max(pagination.pageSize, focusIds.length)));
    }
    // Dashboard drill-down (?owner=me) — JDs created by the current user.
    if (ownerMe) p.set('owner', 'me');
    // Dashboard drill-down (?assigned=me) — JDs assigned to the current user.
    if (assignedMe) p.set('assigned', 'me');
    // Dashboard drill-down (?pending=1) — TA "Pending" card.
    if (pendingOnly) p.set('pending', '1');
    // Dashboard drill-down (?created_from=/&created_to=) — TA period window.
    if (createdFromFilter) p.set('created_from', createdFromFilter);
    if (createdToFilter) p.set('created_to', createdToFilter);
    // Dashboard drill-down (?period=) — TA "Total Requirements" card; resolved
    // server-side into the same window created_from/created_to would encode.
    if (periodFilter) p.set('period', periodFilter);
    return p.toString();
  };

  // Fetch a single page of JDs (current pagination + filters) from the server.
  const loadJobsPage = async () => {
    if (!user) return;
    const hasViewPermission = user.role === 'ADMIN' || user.role === 'CANDIDATE' || user.permissions?.includes('jobs.view_jobdescription');
    if (!hasViewPermission) { setJobs([]); setTotal(0); return; }
    setLoading(true);
    try {
      const res = (await api.get(`/jobs/?${buildJobQuery()}`)) as any;
      const d = res.data;
      if (Array.isArray(d)) {
        setJobs(d);
        setTotal(d.length);
      } else {
        setJobs(d?.results ?? []);
        setTotal(d?.count ?? 0);
      }
    } catch (err) {
      console.error('Failed to load jobs:', err);
      setJobs([]);
      setTotal(0);
    } finally {
      setLoading(false);
    }
  };

  const loadAll = async () => {
    if (!user) return;
    setLoading(true);
    setRowSelection({});
    try {
      const hasViewPermission = user.role === 'ADMIN' || user.role === 'CANDIDATE' || user.permissions?.includes('jobs.view_jobdescription');
      if (hasViewPermission) {
        if (user.role === 'CANDIDATE') {
          try {
            const appsRes = await api.get('/public/my-applications/') as any;
            setMyApps(appsRes.data || []);
          } catch (err) {
            console.error("Failed to load candidate applications:", err);
          }
        }
        // Jobs are fetched one page at a time (server-side pagination + filters)
        // so edit/rename/upload refreshes stay fast instead of re-downloading
        // every JD.
        await loadJobsPage();

        try {
          const clientsRes = await api.get('/clients/?page_size=1000') as any;
          const clientsData = clientsRes.data;
          if (Array.isArray(clientsData)) {
            setClients(clientsData);
          } else if (clientsData && Array.isArray(clientsData.results)) {
            setClients(clientsData.results);
          } else {
            setClients([]);
          }
        } catch (err) {
          console.error("Failed to load clients:", err);
          setClients([]);
        }

        // The recruiter list is loaded per page when the Assign Recruiters
        // modal opens (see loadRecruitersPage) — no upfront fetch needed.
      }
    } finally {
      setLoading(false);
    }
  };

  const appliedSkillsKey = appliedSkills.join('|');
  const didInitialJobLoad = useRef(false);

  // Reset to page 1 whenever a filter changes (the debounced fetch below runs after).
  useEffect(() => {
    setPagination((p) => (p.pageIndex === 0 ? p : { ...p, pageIndex: 0 }));
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [appliedJdName, appliedJdId, appliedSkillsKey, appliedSkillMatchMode, appliedStatus, ownerMe, assignedMe, pendingOnly, createdFromFilter, createdToFilter, periodFilter]);

  // Fetch the visible page when pagination or filters change. The very first
  // load is handled by loadAll(); skip it here to avoid a duplicate request.
  // The drill-down flags/`focusIds` are included so clicking "View All
  // Records" (which clears them) re-fetches the unfiltered list from the
  // server instead of just re-showing whatever page happened to already be
  // loaded.
  useEffect(() => {
    if (!user) return;
    if (!didInitialJobLoad.current) { didInitialJobLoad.current = true; return; }
    const t = setTimeout(() => { loadJobsPage(); }, 250);
    return () => clearTimeout(t);
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [user, pagination.pageIndex, pagination.pageSize, appliedJdName, appliedJdId, appliedSkillsKey, appliedSkillMatchMode, appliedStatus, ownerMe, assignedMe, pendingOnly, createdFromFilter, createdToFilter, periodFilter, focusIds]);

  const handleCandidateApply = async (jobId: number) => {
    setApplyingJobId(jobId);
    try {
      const res = await api.post('/public/apply/', { job_id: jobId }) as any;
      toast.success(res.message || 'Applied successfully!');
      try {
        const appsRes = await api.get('/public/my-applications/') as any;
        setMyApps(appsRes.data || []);
      } catch (err) {
        console.error("Failed to reload candidate applications:", err);
      }
    } catch (err: any) {
      toast.error(err?.data?.message || 'Could not apply to job.');
    } finally {
      setApplyingJobId(null);
    }
  };


  useEffect(() => {
    if (!user) return;
    loadAll();

    const handleWSEvent = (e: Event) => {
      const customEvent = e as CustomEvent;
      const eventName = customEvent.detail?.event;
      if (['jd_submitted', 'jd_pending_approval', 'jd_approved', 'jd_rejected'].includes(eventName)) {
        loadAll();
      }
    };

    window.addEventListener('ws-event', handleWSEvent);
    return () => {
      window.removeEventListener('ws-event', handleWSEvent);
    };
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [user]);


  // Accept both legacy string[] and new {question, answer}[] shapes.
  const normalizeQuestions = (raw: any): { question: string; answer: string }[] => {
    if (!Array.isArray(raw)) return [];
    return raw.map((q) =>
      typeof q === 'string'
        ? { question: q, answer: '' }
        : { question: q?.question ?? '', answer: q?.answer ?? '' }
    );
  };

  useEffect(() => {
    const urlParams = new URLSearchParams(window.location.search);
    const editIdStr = urlParams.get('editJobId');
    const openCreate = urlParams.get('createJob') === 'true';
    const openAssignRecruiter = urlParams.get('assignRecruiter') === 'true';
    const viewIdStr = urlParams.get('viewJobId');
    const reviewToken = urlParams.get('review');

    // JD-approval email "View JD" link: the JD id is encrypted in `review`,
    // so resolve it via the backend before we can find/open the matching job.
    if (reviewToken && jobs.length > 0) {
      api.get(`/jds/resolve-review-token/?token=${encodeURIComponent(reviewToken)}`)
        .then((res: any) => {
          const jobId = res?.data?.id;
          const foundJob = jobs.find((j) => j.id === jobId);
          if (foundJob) {
            setReviewReason(foundJob.rejection_reason || '');
            setReviewTab('approval');
            setReviewJob(foundJob);
          } else {
            toast.error('This Job Description is not available for review.');
          }
        })
        .catch(() => toast.error('This link is invalid or has expired.'))
        .finally(() => router.replace('/jobs'));
      return;
    }

    if (viewIdStr && jobs.length > 0) {
      const viewId = parseInt(viewIdStr, 10);
      const foundJob = jobs.find((j) => j.id === viewId);
      if (foundJob) {
        setViewJob(foundJob);
        router.replace('/jobs');
      }
      return;
    }

    if (editIdStr && jobs.length > 0) {
      const editId = parseInt(editIdStr, 10);
      const foundJob = jobs.find((j) => j.id === editId);
      if (foundJob) {
        openEditModal(foundJob);
        router.replace('/jobs');
      }
      return;
    }

    if (openCreate) {
      openCreateModal();
      router.replace('/jobs');
      return;
    }

    if (openAssignRecruiter && jobs.length > 0) {
      const targetJob = jobs.find((j) => j.status === 'Published') || jobs[0];
      if (targetJob) {
        openAssignModal(targetJob);
      }
      router.replace('/jobs');
    }
  }, [jobs, router]);

  const handleTitleChange = (value: string) => {
    const sanitized = value.replace(/[^A-Za-z0-9\s/&(),-]/g, '');
    const error = validateJobTitle(value);
    setTitle(sanitized);
    setTitleError(error);
  };

  const openCreateModal = () => {
    setEditingJobId(null);
    setFormError('');
    setTitleError('');
    setActiveJobTab('details');
    setTitle('');
    setDepartment('');
    setLocation('');
    setExperienceBand('');
    setCtcBand('');
    setNoticePeriod('');
    setShift('');
    setMustHaveSkills('');
    setGoodToHaveSkills('');
    setQualifications('');
    setWorkingDays('');
    setNumPositions('');
    setCertification('');
    setQuestions([]);
    setAttachment(null);
    setExistingAttachment(null);
    setQaFile(null);
    setWorkDetails('');
    setStatus('Draft');
    setOriginalStatus(null);
    setEditingApproved(false);
    setPriority('Medium');
    setClientId('');
    setIsModalOpen(true);
  };

  const openEditModal = (job: Job) => {
    setEditingJobId(job.id);
    setFormError('');
    setTitleError('');
    setActiveJobTab('details');
    setTitle(job.title);
    setDepartment(job.department ?? '');
    setLocation(job.location);
    setExperienceBand(job.experience_band ?? '');
    setCtcBand(job.ctc_band ?? '');
    setNoticePeriod(job.notice_period ?? '');
    setShift(job.shift ?? '');
    setMustHaveSkills(job.must_have_skills ?? '');
    setGoodToHaveSkills(job.good_to_have_skills ?? '');
    setQualifications(job.qualifications ?? '');
    setWorkingDays(job.working_days ?? '');
    setNumPositions(job.num_positions != null ? String(job.num_positions) : '');
    setCertification(job.certification ?? '');
    setQuestions(normalizeQuestions(job.questions));
    setAttachment(null);
    setExistingAttachment(job.attachment ?? null);
    setQaFile(null);
    setWorkDetails(job.work_details);
    setStatus(job.status);
    setOriginalStatus(job.status);
    setEditingApproved(job.approval_status === 'APPROVED' || job.status === 'Published');
    setPriority(job.priority ?? 'Medium');
    setClientId(job.client ? String(job.client) : '');
    setIsModalOpen(true);
  };

  const openPublishModal = (job: Job) => {
    // Hard gate (mirrors the backend): only approved → Published JDs may be
    // posted to external platforms, no matter how this was triggered.
    if (job.status !== 'Published') {
      toast.warning('This Job Description is not yet published. Please complete the approval process before posting.');
      return;
    }
    const postedChannels = new Set((job.postings ?? []).filter((p) => p.status === 'POSTED').map((p) => p.channel));
    setPublishJob(job);
    setForceRepost(false);
    setPublishResults([]);
    setPublishChannels(PUBLISH_CHANNELS.filter((ch) => !postedChannels.has(ch.key)).map((ch) => ch.key));
    setPublishStep('preview');
    loadPreviewLinks(job);
  };

  /** Read-only preview of the application URL for every platform. The codes are
   *  stable per (JD, platform), so what is shown here is exactly what gets
   *  published. Failure is non-blocking — publishing never depends on it. */
  const loadPreviewLinks = async (job: Job) => {
    setPreviewLinks(null);
    setCopiedLink(null);
    setPreviewLoading(true);
    try {
      const channels = PUBLISH_CHANNELS.map((ch) => ch.key).join(',');
      const res = (await api.get(`/jobs/${job.id}/publish-preview/?channels=${channels}`)) as any;
      setPreviewLinks((res?.data?.links ?? []) as PreviewLink[]);
    } catch {
      setPreviewLinks(null);
    } finally {
      setPreviewLoading(false);
    }
  };

  const copyPreviewLink = async (link: PreviewLink) => {
    try {
      await navigator.clipboard.writeText(link.url);
      setCopiedLink(link.channel);
      setTimeout(() => setCopiedLink((c) => (c === link.channel ? null : c)), 1800);
    } catch {
      toast.info('Copy failed — select the link and copy it manually.');
    }
  };

  const togglePublishChannel = (key: string) => {
    setPublishChannels((prev) => (prev.includes(key) ? prev.filter((k) => k !== key) : [...prev, key]));
  };

  const closePublishModal = () => {
    setPublishStep(null);
    setPublishJob(null);
    setPublishChannels([]);
    setPublishResults([]);
    setPosting(false);
    setForceRepost(false);
    setPreviewLinks(null);
    setPreviewLoading(false);
    setCopiedLink(null);
  };

  const confirmPublish = async () => {
    if (!publishJob) return;
    if (publishChannels.length === 0) {
      toast.warning('Select at least one platform to post to.');
      return;
    }
    setPosting(true);
    try {
      const res = (await api.post(`/jobs/${publishJob.id}/post/`, {
        channels: publishChannels,
        force: forceRepost,
      })) as any;
      const results: PublishResult[] = res?.data?.results ?? [];
      setPublishResults(results);
      setPublishStep('results');
      const ok = results.filter((r) => r.status === 'POSTED').length;
      if (ok) toast.success(`Published to ${ok} channel${ok > 1 ? 's' : ''} ✓`);
      // Flip the header status shown on the results step (Draft → Published).
      if (ok) setPublishJob((j) => (j ? { ...j, publication_status: 'published' } : j));
      await loadAll();
    } catch (err: any) {
      toast.error(err?.message || err?.response?.data?.message || 'Posting failed');
      closePublishModal();
    } finally {
      setPosting(false);
    }
  };

  const API_BASE = process.env.NEXT_PUBLIC_API_URL || 'http://localhost:8000/api/v1';

  const ALLOWED_JD_EXT = ['pdf', 'doc', 'docx', 'txt'];
  const MAX_JD_MB = 10;

  const parseDocument = async (file: File) => {
    // --- Format validation ---
    const ext = (file.name.split('.').pop() || '').toLowerCase();
    if (!ALLOWED_JD_EXT.includes(ext)) {
      toast.error(`Unsupported file type ".${ext || 'unknown'}". Please upload a PDF, DOC, DOCX or TXT file.`);
      return;
    }
    if (file.size === 0) {
      toast.error('This file is empty. Please choose a valid JD document.');
      return;
    }
    if (file.size > MAX_JD_MB * 1024 * 1024) {
      toast.error(`File is too large (${(file.size / 1024 / 1024).toFixed(1)} MB). Maximum allowed is ${MAX_JD_MB} MB.`);
      return;
    }

    setParsing(true);
    try {
      const fd = new FormData();
      fd.append('file', file);
      const json = (await api.upload('/jobs/parse-document/', fd)) as any;
      const d = json.data || {};

      // --- Content validation: is this actually a JD in the standard format? ---
      // The parser ALWAYS returns work_details (full text) and a fallback title
      // (first line), so judge by the labelled fields only. A resume or random
      // document won't have "Department:", "CTC:", "Must have skills:" etc.
      const labelledFields = [
        d.department, d.location, d.experience_band, d.ctc_band,
        d.notice_period, d.shift, d.qualifications,
        d.must_have_skills, d.good_to_have_skills,
      ].filter((v) => v && String(v).trim());

      if (labelledFields.length < 2) {
        // Not a JD — reject outright: no auto-fill, no attach.
        toast.error(
          'This file doesn’t look like a Job Description in the standard format. ' +
          'No JD fields (Department, Location, CTC, Skills…) were found. ' +
          'Please use the "Sample Format" template.'
        );
        return;
      }

      // pre-fill every field the parser found (don't clobber with blanks)
      if (d.title) setTitle(d.title);
      if (d.department) setDepartment(d.department);
      if (d.location) setLocation(d.location);
      if (d.experience_band) setExperienceBand(d.experience_band);
      if (d.ctc_band) setCtcBand(d.ctc_band);
      if (d.notice_period) setNoticePeriod(d.notice_period);
      if (d.shift) setShift(d.shift);
      if (d.qualifications) setQualifications(d.qualifications);
      if (d.working_days) setWorkingDays(d.working_days);
      if (d.num_positions) setNumPositions(String(d.num_positions).replace(/\D/g, ''));
      if (d.certification) setCertification(d.certification);
      if (d.must_have_skills) setMustHaveSkills(d.must_have_skills);
      if (d.good_to_have_skills) setGoodToHaveSkills(d.good_to_have_skills);
      if (Array.isArray(d.questions) && d.questions.length) mergeParsedQuestions(normalizeQuestions(d.questions));
      if (d.work_details) setWorkDetails(d.work_details);

      // Attach only after a successful parse.
      setAttachment(file);
      setExistingAttachment(null);
      toast.success('Document parsed — review the fields and save.');
    } catch (err) {
      toast.error(err instanceof Error ? err.message : 'Could not read this document. Please try another file.');
    } finally {
      setParsing(false);
    }
  };

  // Always-current mirror of `questions` so async parse flows never merge
  // against a stale snapshot.
  const questionsRef = useRef(questions);
  questionsRef.current = questions;

  // Merge parsed questions into the Q&A list: keep everything already there
  // (typed manually or parsed from the other source), append new ones, skip
  // duplicates (case-insensitive on the question text) and blank rows.
  // Returns how many were added vs skipped so callers can word their toast.
  const mergeParsedQuestions = (parsed: { question: string; answer: string }[]) => {
    const kept = questionsRef.current.filter((q) => q.question.trim() || q.answer.trim());
    const seen = new Set(kept.map((q) => q.question.trim().toLowerCase()));
    const merged = [...kept];
    let added = 0;
    let skipped = 0;
    for (const q of parsed) {
      const key = q.question.trim().toLowerCase();
      if (!key) continue;
      if (seen.has(key)) {
        skipped += 1;
        continue;
      }
      merged.push(q);
      seen.add(key);
      added += 1;
    }
    setQuestions(merged);
    return { added, skipped };
  };

  // Upload a filled Q&A template → parse → merge into the questions list.
  const parseQaDocument = async (file: File) => {
    const ext = (file.name.split('.').pop() || '').toLowerCase();
    if (!['pdf', 'docx', 'txt'].includes(ext)) {
      toast.error(`Unsupported file type ".${ext || 'unknown'}". Please upload a PDF, DOCX or TXT file.`);
      return;
    }
    if (file.size === 0) {
      toast.error('This file is empty. Please choose a filled Q&A template.');
      return;
    }
    if (file.size > MAX_JD_MB * 1024 * 1024) {
      toast.error(`File is too large (${(file.size / 1024 / 1024).toFixed(1)} MB). Maximum allowed is ${MAX_JD_MB} MB.`);
      return;
    }
    setParsingQa(true);
    try {
      const fd = new FormData();
      fd.append('file', file);
      const json = (await api.upload('/jobs/parse-questions/', fd)) as any;
      const parsed = normalizeQuestions(json?.data?.questions ?? []);
      if (!parsed.length) {
        toast.warning('No questions found in this file. Use the "Q:" / "A:" format from the sample template.');
        return;
      }
      const { added, skipped } = mergeParsedQuestions(parsed);
      setQaFile(file);
      if (added === 0) {
        toast.warning(`Duplicate questions detected — all ${skipped} question(s) in this file are already in the list.`);
      } else if (skipped > 0) {
        toast.success(`${added} new question(s) added · ${skipped} duplicate(s) skipped.`);
      } else {
        toast.success(`${added} question(s) loaded from the template — review and edit below.`);
      }
    } catch (err) {
      toast.error(err instanceof Error ? err.message : 'Could not parse the Q&A file.');
    } finally {
      setParsingQa(false);
    }
  };

  /** Remove the attached JD and reset the auto-filled fields. */
  const handleRemoveJdFile = async () => {
    const result = await showConfirmDelete('Removing the JD file will also reset the form fields. Continue?');
    if (!result.isConfirmed) return;
    setAttachment(null);
    if (editingJobId) {
      // Edit mode — restore the job's original values.
      const job = jobs.find((j) => j.id === editingJobId);
      if (job) { openEditModal(job); return; }
    }
    // Create mode — back to a blank form.
    setTitle(''); setDepartment(''); setLocation(''); setExperienceBand('');
    setCtcBand(''); setNoticePeriod(''); setShift(''); setMustHaveSkills('');
    setGoodToHaveSkills(''); setQualifications(''); setQuestions([]);
    setWorkDetails(''); setStatus('Draft'); setPriority('Medium'); setClientId('');
    setActiveJobTab('details');
    toast.info('JD file removed — form reset.');
  };

  const handleSubmit = async (e: React.FormEvent) => {
    e.preventDefault();

    const titleValidationMessage = validateJobTitle(title);
    if (titleValidationMessage) {
      setTitleError(titleValidationMessage);
      toast.error(titleValidationMessage);
      return;
    }

    if (!title.trim() || !location.trim() || !workDetails.trim()) {
      toast.warning('Please fill in Title, Location and Work details.');
      return;
    }
    if (!clientId) {
      toast.warning('Please select an Associated Client.');
      return;
    }

    const validQuestions = questions.filter((q) => (q.question || '').trim() && (q.answer || '').trim());
    if (validQuestions.length === 0) {
      const message = 'Please add at least one Question & Answer before submitting the Job Description.';
      toast.warning(message);
      setActiveJobTab('questions');
      return;
    }

    setSubmitting(true);

    try {
      const jobData = {
        title,
        department,
        location,
        experience_band: experienceBand,
        ctc_band: ctcBand,
        notice_period: noticePeriod,
        shift,
        must_have_skills: mustHaveSkills,
        good_to_have_skills: goodToHaveSkills,
        qualifications,
        working_days: workingDays,
        num_positions: numPositions ? parseInt(numPositions, 10) : null,
        certification,
        questions: questions
          .map((q) => ({ question: (q.question || '').trim(), answer: (q.answer || '').trim() }))
          .filter((q) => q.question),
        work_details: workDetails,
        status,
        priority,
        client: clientId ? parseInt(clientId, 10) : null
      };

      let jobId = editingJobId;
      if (editingJobId) {
        await api.put(`/jobs/${editingJobId}/`, jobData);
        toast.success('Job updated successfully ✓');
      } else {
        const created = (await api.post('/jobs/', jobData)) as any;
        jobId = created?.data?.id ?? created?.id ?? null;
        toast.success('Job created successfully ✓');
      }

      // Attach the uploaded document (separate multipart PATCH)
      if (attachment && jobId) {
        const fd = new FormData();
        fd.append('attachment', attachment);
        await api.uploadPatch(`/jobs/${jobId}/`, fd);
      }
      setIsModalOpen(false);
      loadAll();
    } catch (err: any) {
      // Surface field-level errors (e.g. the duplicate-JD check) with their exact message.
      const fieldErrors = err?.data?.errors;
      let msg = err instanceof Error ? err.message : 'Operation failed';
      if (fieldErrors && typeof fieldErrors === 'object') {
        const first = Object.values(fieldErrors)[0];
        msg = Array.isArray(first) ? String(first[0]) : String(first);
      }
      toast.error(msg);
    } finally {
      setSubmitting(false);
    }
  };

  const handleDelete = (jobId: number) => {
    showConfirmDelete('Are you sure you want to delete this job description?', async () => {
      try {
        await api.delete(`/jobs/${jobId}/`);
        toast.success('Job deleted successfully ✓');
        loadAll();
      } catch (err) {
        toast.error(err instanceof Error ? err.message : 'Delete failed');
      }
    });
  };

  const handleCopy = async (job: Job) => {
    const result = await showConfirmDelete(`Do you want to copy the JD "${job.title}"?`);
    if (!result.isConfirmed) return;
    setCopyingId(job.id);
    try {
      await api.post(`/jobs/${job.id}/copy/`, {});
      toast.success('JD copied successfully.');
      await loadAll();
    } catch (err) {
      toast.error(err instanceof Error ? err.message : 'Copy failed');
    } finally {
      setCopyingId(null);
    }
  };

  // Server-side paginated recruiter list for the Assign Recruiters modal.
  const loadRecruitersPage = async (page: number, search: string, jobId?: number) => {
    setRecruiterLoading(true);
    try {
      const params = new URLSearchParams({ page: String(page), page_size: String(REC_PAGE_SIZE) });
      if (search.trim()) params.set('search', search.trim());
      const excludeJdId = jobId ?? assignJob?.id;
      if (excludeJdId) params.set('exclude_job', String(excludeJdId));
      const res = (await api.get(`/jobs/recruiters/?${params.toString()}`)) as any;
      setRecruiters(unwrapList(res));
      setRecruiterTotal(unwrapCount(res));
      setRecruiterPage(page);
    } catch {
      toast.error('Failed to load recruiters');
    } finally {
      setRecruiterLoading(false);
    }
  };

  // Server-side paginated assigned recruiter list for the Assigned Recruiters tab.
  const loadAssignedRecs = async (jobId: number, page = 1) => {
    setAssignedRecLoading(true);
    try {
      const params = new URLSearchParams({ page: String(page), page_size: String(REC_PAGE_SIZE), assigned_job: String(jobId) });
      const res = (await api.get(`/jobs/recruiters/?${params.toString()}`)) as any;
      setAssignedRecs(unwrapList(res));
      setAssignedRecTotal(unwrapCount(res));
      setAssignedRecPage(page);
    } catch {
      toast.error('Failed to load assigned recruiters');
    } finally {
      setAssignedRecLoading(false);
    }
  };

  // Debounced server-side recruiter search — resets to page 1. Skips the run
  // caused by the modal opening (openAssignModal already loads page 1).
  const recSearchSkip = useRef(true);
  useEffect(() => {
    if (!assignJob) {
      recSearchSkip.current = true;
      return;
    }
    if (recSearchSkip.current) {
      recSearchSkip.current = false;
      return;
    }
    const t = setTimeout(() => loadRecruitersPage(1, recruiterSearch, assignJob.id), 400);
    return () => clearTimeout(t);
  }, [recruiterSearch, assignJob]);

  const openAssignModal = async (job: Job) => {
    setAssignJob(job);
    setRecTab('select');
    setSelectedRecruiterIds([]);
    setRecruiterSearch('');
    setRecruiters([]);
    setRecruiterPage(1);
    setRecruiterTotal(0);
    setAssignedRecs([]);
    setAssignedRecPage(1);
    setAssignedRecTotal(0);
    setRecruiterLoading(true);
    try {
      await Promise.all([
        loadAssignedRecs(job.id, 1),
        loadRecruitersPage(1, '', job.id),
      ]);
    } finally {
      setRecruiterLoading(false);
    }
  };

  const handleAssignRecruiters = async () => {
    if (!assignJob || selectedRecruiterIds.length === 0) return;
    setRecAssigning(true);
    try {
      const currentAssignedIds = (assignJob.assigned_recruiters ?? []).map((r) => r.id);
      const newRecruiterIds = Array.from(new Set([...currentAssignedIds, ...selectedRecruiterIds]));
      const res = (await api.post(`/jobs/${assignJob.id}/assign-recruiters/`, {
        recruiter_ids: newRecruiterIds,
      })) as any;
      const updated: RecruiterBrief[] = res?.data ?? [];
      setJobs((prev) =>
        prev.map((j) => (j.id === assignJob.id ? { ...j, assigned_recruiters: updated } : j))
      );
      setAssignJob((prev) => prev ? { ...prev, assigned_recruiters: updated } : null);
      toast.success(`${selectedRecruiterIds.length} recruiter${selectedRecruiterIds.length > 1 ? 's' : ''} assigned ✓`);
      setSelectedRecruiterIds([]);
      await Promise.all([
        loadAssignedRecs(assignJob.id, 1),
        loadRecruitersPage(recruiterPage, recruiterSearch, assignJob.id),
      ]);
      setRecTab('assigned');
    } catch (err) {
      toast.error(err instanceof Error ? err.message : 'Assignment failed');
    } finally {
      setRecAssigning(false);
    }
  };

  const handleUnassignRecruiter = async (recruiterId: number) => {
    if (!assignJob) return;

    const performUnassign = async () => {
      setRecAssigning(true);
      try {
        const currentAssignedIds = (assignJob.assigned_recruiters ?? []).map((r) => r.id);
        const newRecruiterIds = currentAssignedIds.filter((id) => id !== recruiterId);
        const res = (await api.post(`/jobs/${assignJob.id}/assign-recruiters/`, {
          recruiter_ids: newRecruiterIds,
        })) as any;
        const updated: RecruiterBrief[] = res?.data ?? [];
        setJobs((prev) =>
          prev.map((j) => (j.id === assignJob.id ? { ...j, assigned_recruiters: updated } : j))
        );
        setAssignJob((prev) => prev ? { ...prev, assigned_recruiters: updated } : null);
        toast.success('Recruiter unassigned ✓');

        let nextPage = assignedRecPage;
        if (assignedRecs.length === 1 && assignedRecPage > 1) {
          nextPage = assignedRecPage - 1;
        }
        await Promise.all([
          loadAssignedRecs(assignJob.id, nextPage),
          loadRecruitersPage(recruiterPage, recruiterSearch, assignJob.id),
        ]);
      } catch (err) {
        toast.error(err instanceof Error ? err.message : 'Unassignment failed');
      } finally {
        setRecAssigning(false);
      }
    };

    const currentAssignedIds = (assignJob.assigned_recruiters ?? []).map((r) => r.id);
    if (currentAssignedIds.length === 1) {
      showConfirmDelete(
        'Are you sure you want to remove all recruiters assigned to this job description?',
        performUnassign
      );
    } else {
      await performUnassign();
    }
  };

  // Filtered jobs computation
  const filteredJobs = useMemo(() => {
    return jobs.filter((job) => {
      // 0. Dashboard drill-down: `?ids=` pins the list to exactly the records
      //    behind the card's count (same ids the dashboard API counted), so the
      //    number on the card always equals the number of rows shown here.
      if (focusIds && !focusIds.includes(job.id)) return false;

      // 1. JD Name Filter (partial match, case-insensitive)
      if (appliedJdName.trim()) {
        const query = appliedJdName.trim().toLowerCase();
        if (!job.title.toLowerCase().includes(query)) {
          return false;
        }
      }

      // 2. JD ID Filter (partial match, case-insensitive)
      if (appliedJdId.trim()) {
        const query = appliedJdId.trim().toLowerCase();
        const matchId = String(job.id).toLowerCase().includes(query);
        const matchCode = (job.jd_code || '').toLowerCase().includes(query);
        if (!matchId && !matchCode) {
          return false;
        }
      }

      // 3. Skills Filter (multi-select, master data)
      if (appliedSkills.length > 0) {
        const jobSkillsText = `${job.must_have_skills || ''} ${job.good_to_have_skills || ''} ${job.work_details || ''}`.toLowerCase();
        if (appliedSkillMatchMode === 'AND') {
          const allMatch = appliedSkills.every((s) => jobSkillsText.includes(s.toLowerCase()));
          if (!allMatch) return false;
        } else {
          const anyMatch = appliedSkills.some((s) => jobSkillsText.includes(s.toLowerCase()));
          if (!anyMatch) return false;
        }
      }

      // 4. Status Filter
      if (appliedStatus && appliedStatus !== 'ALL') {
        const appStatus = (job.approval_status || '').toUpperCase();
        const canonical = job.jd_status
          || (job.status === 'Published' ? 'published'
            : job.status === 'Closed' ? 'closed'
              : appStatus === 'PENDING_APPROVAL' ? 'pending_approval'
                : 'draft');

        const selectedLower = appliedStatus.toLowerCase();
        if (selectedLower === 'published' && job.status !== 'Published' && canonical !== 'published') {
          return false;
        }
        if (selectedLower === 'closed' && job.status !== 'Closed' && canonical !== 'closed') {
          return false;
        }
        if (selectedLower === 'draft' && job.status !== 'Draft' && canonical !== 'draft') {
          return false;
        }
        if (selectedLower === 'pending approval' && canonical !== 'pending_approval' && appStatus !== 'PENDING_APPROVAL') {
          return false;
        }
      }

      return true;
    });
  }, [jobs, appliedJdName, appliedJdId, appliedSkills, appliedSkillMatchMode, appliedStatus, focusIds]);

  const activeFilterCount =
    (appliedJdName.trim() ? 1 : 0) +
    (appliedJdId.trim() ? 1 : 0) +
    (appliedSkills.length > 0 ? 1 : 0) +
    (appliedStatus && appliedStatus !== 'ALL' ? 1 : 0);

  const clearAllFilters = () => {
    setAppliedJdName('');
    setAppliedJdId('');
    setAppliedSkills([]);
    setAppliedSkillMatchMode('OR');
    setAppliedStatus('ALL');
  };

  // Selected job ids (keys are String(job.id) via getRowId)
  const selectedIds = Object.keys(rowSelection).filter((id) => rowSelection[id]);
  // Backend only allows deleting Draft JDs — filter to those.
  const deletableSelectedIds = selectedIds.filter(
    (id) => jobs.find((j) => String(j.id) === id)?.status === 'Draft'
  );

  const handleBulkDelete = () => {
    if (deletableSelectedIds.length === 0) return;
    showConfirmDelete(
      `Delete ${deletableSelectedIds.length} draft job description(s)? This cannot be undone.`,
      async () => {
        const results = await Promise.allSettled(
          deletableSelectedIds.map((id) => api.delete(`/jobs/${id}/`))
        );
        const ok = results.filter((r) => r.status === 'fulfilled').length;
        const failed = results.length - ok;
        if (ok) toast.success(`${ok} job(s) deleted ✓`);
        if (failed) toast.error(`${failed} job(s) could not be deleted`);
        setRowSelection({});
        loadAll();
      }
    );
  };

  // Compile all postings across all jobs for post history view
  const allPostings = jobs.flatMap((job) =>
    (job.postings ?? []).map((p) => ({
      ...p,
      jobTitle: job.title,
      location: job.location,
    }))
  ).sort((a, b) => {
    const timeA = a.posted_at ? new Date(a.posted_at).getTime() : 0;
    const timeB = b.posted_at ? new Date(b.posted_at).getTime() : 0;
    return timeB - timeA;
  });

  if (!user) return null;

  if (loading) return <PageLoader />;

  if (user && user.role !== 'ADMIN' && user.role !== 'CANDIDATE' && !user.permissions?.includes('jobs.view_jobdescription')) {
    return (
      <main className="flex-1 flex items-center justify-center p-8">
        <div className="max-w-md w-full bg-white dark:bg-slate-900 border border-slate-200 dark:border-slate-800 rounded-none p-8 text-center shadow-xl space-y-6">
          <div className="mx-auto w-16 h-16 bg-rose-50 dark:bg-rose-950/30 border border-rose-100 dark:border-rose-900/50 rounded-none flex items-center justify-center text-rose-500 animate-bounce">
            <i className="fa-solid fa-lock text-3xl"></i>
          </div>
          <div className="space-y-2">
            <h3 className="text-xl font-bold text-slate-800 dark:text-white">Permission Required</h3>
            <p className="text-sm text-slate-500 dark:text-slate-400 leading-relaxed">
              You do not have access to view this page. This resource requires the <code className="px-1.5 py-0.5 rounded-none bg-slate-100 dark:bg-slate-950 border border-slate-200 dark:border-slate-800 text-rose-600 dark:text-rose-400 font-mono text-xs">jobs.view_jobdescription</code> permission.
            </p>
          </div>
          <button
            onClick={() => router.push('/dashboard')}
            className="w-full bg-indigo-600 hover:bg-indigo-500 text-white text-sm font-semibold py-3 rounded-none shadow-lg hover:shadow-indigo-500/20 transition cursor-pointer"
          >
            Go to Dashboard
          </button>
        </div>
      </main>
    );
  }

  return (
    <>
      <main className="flex-1 p-8 overflow-y-auto w-full space-y-6 max-w-7xl mx-auto">
        <BackToDashboard />
        <div className="relative flex flex-col sm:flex-row gap-4 justify-between sm:items-center">
          <div>
            <p className="text-sm text-slate-500 dark:text-slate-400">Create, manage, and publish job listings for candidates.</p>
          </div>
          <div className="flex items-center gap-3">
            <button
              type="button"
              onClick={() => {
                setFilterOpen((o) => !o);
                if (masterSkillOptions.length === 0) {
                  loadMasterSkillOptions();
                }
              }}
              className={`flex items-center gap-2 rounded-none px-4 py-2.5 text-xs font-bold cursor-pointer transition border ${activeFilterCount > 0
                ? 'bg-[#405189]/10 text-[#405189] dark:bg-indigo-950/40 dark:text-indigo-300 border-[#405189]/30 dark:border-indigo-800'
                : 'bg-slate-50 dark:bg-slate-800 hover:bg-slate-100 dark:hover:bg-slate-700 text-slate-700 dark:text-slate-200 border-slate-200/40 dark:border-slate-850'
                }`}
            >
              <i className="fa-solid fa-filter text-xs"></i>
              <span>Filters</span>
              {activeFilterCount > 0 && (
                <span className="inline-flex items-center justify-center min-w-[18px] h-[18px] px-1 rounded-full bg-[#405189] text-white text-[10px] font-extrabold">
                  {activeFilterCount}
                </span>
              )}
              <i className={`fa-solid fa-chevron-down text-[9px] transition-transform ${filterOpen ? 'rotate-180' : ''}`}></i>
            </button>

            {viewMode === 'card' && user?.role !== 'CANDIDATE' && (
              <button
                onClick={() => setViewMode('table')}
                className="bg-slate-105 hover:bg-slate-200 dark:bg-slate-800 dark:hover:bg-slate-700 text-slate-750 dark:text-slate-200 text-xs font-bold px-4 py-2.5 rounded-none shadow transition flex items-center gap-2 cursor-pointer border border-slate-200/40 dark:border-slate-850"
              >
                <i className="fa-solid fa-table"></i> Table View
              </button>
            )}
            {user?.role !== 'CANDIDATE' && (
              <button
                onClick={() => setPostHistoryOpen(true)}
                className="bg-slate-50 hover:bg-slate-100 dark:bg-slate-800 dark:hover:bg-slate-700 text-slate-700 dark:text-slate-200 text-xs font-bold px-4 py-2.5 rounded-none shadow transition flex items-center gap-2 cursor-pointer border border-slate-200/40 dark:border-slate-850"
              >
                <i className="fa-solid fa-clock-rotate-left text-xs"></i> Post History
              </button>
            )}

            {hasAddPermission && (
              <button
                onClick={openCreateModal}
                className="bg-indigo-600 hover:bg-indigo-500 text-white text-sm font-semibold px-5 py-2.5 rounded-none shadow-lg hover:shadow-indigo-500/20 transition flex items-center gap-2 cursor-pointer"
              >
                <i className="fa-solid fa-plus text-xs"></i> Create Job
              </button>
            )}
          </div>

          {/* Candidates-style Expandable Filter Panel */}
          {filterOpen && (
            <>
              {/* click-outside backdrop */}
              <div className="fixed inset-0 z-30" onClick={() => setFilterOpen(false)} />
              <div className="absolute left-0 right-0 top-full mt-2 z-40 bg-white dark:bg-slate-900 border border-slate-200 dark:border-slate-800 rounded-none shadow-xl p-4 space-y-3">
                <div className="flex items-center justify-between border-b border-slate-100 dark:border-slate-800 pb-2.5">
                  <span className="text-xs font-extrabold text-slate-800 dark:text-white flex items-center gap-2">
                    <i className="fa-solid fa-filter text-[#405189] dark:text-indigo-400"></i>
                    Filter Job Descriptions
                  </span>
                  {activeFilterCount > 0 && (
                    <button
                      type="button"
                      onClick={clearAllFilters}
                      className="text-[11px] font-bold text-rose-500 hover:text-rose-600 cursor-pointer flex items-center gap-1"
                    >
                      <i className="fa-solid fa-rotate-left text-[10px]"></i> Clear all
                    </button>
                  )}
                </div>



                <div className="flex flex-col sm:flex-row items-start gap-4">
                  <div className="w-full sm:w-44 shrink-0">
                    <label className="block text-[10px] uppercase font-bold text-slate-400 mb-1">
                      Status
                    </label>
                    <SearchableSelect
                      value={appliedStatus}
                      onChange={(val: any) => setAppliedStatus((val as string) || 'ALL')}
                      className="w-full"
                      placeholder="All Statuses"
                      isClearable={false}
                      options={[
                        { value: 'ALL', label: 'All Statuses' },
                        { value: 'Published', label: 'Published' },
                        { value: 'Closed', label: 'Closed' },
                        { value: 'Draft', label: 'Draft' },
                        { value: 'Pending Approval', label: 'Pending Approval' },
                      ]}
                      controlBgClass="bg-white dark:bg-slate-950"
                    />
                  </div>
                  {/* 1. Job ID Filter (Digits Only, Reduced Width) */}
                  <div className="w-full sm:w-32 shrink-0">
                    <label className="block text-[10px] uppercase font-bold text-slate-400 mb-1">
                      Job ID
                    </label>
                    <input
                      type="text"
                      inputMode="numeric"
                      pattern="[0-9]*"
                      value={appliedJdId}
                      onChange={(e) => setAppliedJdId(e.target.value.replace(/\D/g, ''))}
                      placeholder="Job ID"
                      autoComplete="off"
                      className="w-full bg-white dark:bg-slate-950 border border-slate-200 dark:border-slate-800 rounded-none px-3 py-2 text-xs text-slate-800 dark:text-white placeholder:text-slate-400 focus:outline-none focus:border-[#405189] dark:focus:border-indigo-500 transition"
                    />
                  </div>




                  {/* 2. Job Name Filter (Reduced Width) */}
                  <div className="w-full sm:w-48 shrink-0">
                    <label className="block text-[10px] uppercase font-bold text-slate-400 mb-1">
                      Job Name
                    </label>
                    <input
                      type="text"
                      value={appliedJdName}
                      onChange={(e) => setAppliedJdName(e.target.value)}
                      placeholder="Type job name..."
                      autoComplete="off"
                      className="w-full bg-white dark:bg-slate-950 border border-slate-200 dark:border-slate-800 rounded-none px-3 py-2 text-xs text-slate-800 dark:text-white placeholder:text-slate-400 focus:outline-none focus:border-[#405189] dark:focus:border-indigo-500 transition"
                    />
                  </div>

                  {/* 3. Status Filter */}


                  {/* 4. Key Skills Filter */}
                  <div className="w-full sm:flex-1 min-w-[200px]">
                    <div className="flex items-center justify-between mb-1">

                      <label className="block text-[10px] uppercase font-bold text-slate-400">
                        Key Skills  {appliedSkills.length > 0 ? ` (${appliedSkills.length})` : ''}
                        (
                        <button
                          type="button"
                          onClick={() => setAppliedSkillMatchMode('OR')}
                          className={`px-1.5 py-0.2 font-bold cursor-pointer transition ${appliedSkillMatchMode === 'OR'
                            ? 'bg-[#405189] text-white'
                            : 'bg-slate-100 dark:bg-slate-800 text-slate-500'
                            }`}
                        >
                          OR
                        </button>
                        <button
                          type="button"
                          onClick={() => setAppliedSkillMatchMode('AND')}
                          className={`px-1.5 py-0.2 font-bold cursor-pointer transition ${appliedSkillMatchMode === 'AND'
                            ? 'bg-[#405189] text-white'
                            : 'bg-slate-100 dark:bg-slate-800 text-slate-500'
                            }`}
                        >
                          AND
                        </button>
                        )

                      </label>

                    </div>
                    <SearchableSelect
                      isMulti
                      wrap
                      value={appliedSkills}
                      onChange={(v: any) => setAppliedSkills((v as string[]) || [])}
                      className="w-full"
                      placeholder="Select skills…"
                      loading={masterSkillsLoading}
                      options={masterSkillOptions}
                      noOptionsMessage="No skills found"
                      controlBgClass="bg-white dark:bg-slate-950"
                      isCreatable={false}
                    />
                  </div>
                </div>
              </div>
            </>
          )}
        </div>

        {/* Dashboard drill-down banner — the list is pinned to exactly the
            records behind the card that was clicked (specific ids, or a
            server-side scope like `owner=me`/`assigned=me`/`pending=1`/a
            created-date window). */}
        {hasDrillDown && (
          <div className="flex items-center flex-wrap gap-2 bg-[#405189]/5 border border-[#405189]/25 rounded-none px-4 py-2.5 text-xs">
            <span className="font-bold text-[#405189] dark:text-indigo-300 flex items-center gap-1.5">
              <i className="fa-solid fa-crosshairs"></i>
              {focusLabel ? `${focusLabel}:` : 'Showing:'}
            </span>
            <span className="text-slate-600 dark:text-slate-300 font-semibold">
              {focusIds
                ? <>{filteredJobs.length} of {focusIds.length} record{focusIds.length === 1 ? '' : 's'} from your dashboard</>
                : <>{total} record{total === 1 ? '' : 's'} from your dashboard</>}
            </span>
            <button
              onClick={clearDrillDown}
              className="ml-auto inline-flex items-center gap-1.5 px-2.5 py-1 bg-white dark:bg-slate-900 border border-[#405189]/30 text-[#405189] dark:text-indigo-300 font-bold hover:bg-[#405189] hover:text-white transition cursor-pointer"
            >
              <i className="fa-solid fa-xmark"></i> View All Records
            </button>
          </div>
        )}

        {/* Active Filter Chips Summary Bar */}
        {activeFilterCount > 0 && (
          <div className="flex items-center flex-wrap gap-2 bg-indigo-50/60 dark:bg-indigo-950/30 border border-indigo-200/60 dark:border-indigo-900/50 rounded-none px-4 py-2.5 text-xs">
            <span className="font-bold text-indigo-900 dark:text-indigo-300 flex items-center gap-1.5">
              <i className="fa-solid fa-filter text-indigo-600 dark:text-indigo-400"></i> Active Filters:
            </span>
            {appliedJdName.trim() && (
              <span className="inline-flex items-center gap-1.5 px-2.5 py-1 bg-white dark:bg-slate-900 border border-indigo-200 dark:border-indigo-800 text-indigo-700 dark:text-indigo-300 font-semibold text-xs shadow-xs">
                <span>Name: <b>"{appliedJdName}"</b></span>
                <button onClick={() => setAppliedJdName('')} className="hover:text-rose-500 ml-1 cursor-pointer">
                  <i className="fa-solid fa-xmark"></i>
                </button>
              </span>
            )}
            {appliedJdId.trim() && (
              <span className="inline-flex items-center gap-1.5 px-2.5 py-1 bg-white dark:bg-slate-900 border border-indigo-200 dark:border-indigo-800 text-indigo-700 dark:text-indigo-300 font-semibold text-xs shadow-xs">
                <span>ID: <b>"{appliedJdId}"</b></span>
                <button onClick={() => setAppliedJdId('')} className="hover:text-rose-500 ml-1 cursor-pointer">
                  <i className="fa-solid fa-xmark"></i>
                </button>
              </span>
            )}
            {appliedStatus && appliedStatus !== 'ALL' && (
              <span className="inline-flex items-center gap-1.5 px-2.5 py-1 bg-white dark:bg-slate-900 border border-indigo-200 dark:border-indigo-800 text-indigo-700 dark:text-indigo-300 font-semibold text-xs shadow-xs">
                <span>Status: <b>"{appliedStatus}"</b></span>
                <button onClick={() => setAppliedStatus('ALL')} className="hover:text-rose-500 ml-1 cursor-pointer">
                  <i className="fa-solid fa-xmark"></i>
                </button>
              </span>
            )}
            {appliedSkills.length > 0 && (
              <span className="inline-flex items-center gap-1.5 px-2.5 py-1 bg-white dark:bg-slate-900 border border-indigo-200 dark:border-indigo-800 text-indigo-700 dark:text-indigo-300 font-semibold text-xs shadow-xs">
                <span>Skills ({appliedSkillMatchMode}): <b>{appliedSkills.join(', ')}</b></span>
                <button onClick={() => setAppliedSkills([])} className="hover:text-rose-500 ml-1 cursor-pointer">
                  <i className="fa-solid fa-xmark"></i>
                </button>
              </span>
            )}
            <button
              onClick={clearAllFilters}
              className="ml-auto text-xs font-bold text-rose-600 dark:text-rose-400 hover:underline cursor-pointer flex items-center gap-1"
            >
              <i className="fa-solid fa-rotate-left text-[10px]"></i> Clear All
            </button>
          </div>
        )}

        {/* Bulk selection action bar */}
        {viewMode === 'table' && selectedIds.length > 0 && (
          <div className="flex items-center justify-between gap-3 bg-indigo-50 dark:bg-indigo-950/30 border border-indigo-200 dark:border-indigo-900/50 rounded-none px-4 py-2.5">
            <span className="text-xs font-bold text-indigo-700 dark:text-indigo-300">
              {selectedIds.length} selected
            </span>
            <div className="flex items-center gap-2">
              {hasDeletePermission && (
                <button
                  onClick={handleBulkDelete}
                  disabled={deletableSelectedIds.length === 0}
                  title={deletableSelectedIds.length === 0 ? 'Only Draft jobs can be deleted' : undefined}
                  className="bg-rose-600 hover:bg-rose-500 disabled:opacity-40 disabled:cursor-not-allowed text-white text-xs font-bold px-3 py-1.5 rounded-none transition flex items-center gap-1.5 cursor-pointer"
                >
                  <i className="fa-solid fa-trash"></i> Delete Selected
                  {deletableSelectedIds.length > 0 && ` (${deletableSelectedIds.length})`}
                </button>
              )}
              <button
                onClick={() => setRowSelection({})}
                className="bg-white dark:bg-slate-900 border border-slate-200 dark:border-slate-700 hover:bg-slate-50 dark:hover:bg-slate-800 text-slate-600 dark:text-slate-300 text-xs font-bold px-3 py-1.5 rounded-none transition flex items-center gap-1.5 cursor-pointer"
              >
                <i className="fa-solid fa-xmark"></i> Clear
              </button>
            </div>
          </div>
        )}

        {viewMode === 'table' || user?.role === 'CANDIDATE' ? (
          <DataTable
            columns={columns}
            data={filteredJobs}
            loading={loading}
            pageCount={Math.max(1, Math.ceil(total / pagination.pageSize))}
            controlledPagination={pagination}
            onPaginationChange={setPagination}
            controlledGlobalFilter={appliedJdName}
            onGlobalFilterChange={(v) => setAppliedJdName(v)}
            enableRowSelection={user?.role === 'CANDIDATE' ? false : (row) => row.original.status === 'Draft'}
            rowSelection={rowSelection}
            onRowSelectionChange={setRowSelection}
            getRowId={(job) => String(job.id)}
            searchPlaceholder={user?.role === 'CANDIDATE' ? "Search jobs by title..." : "Search jobs by title..."}
            emptyStateTitle="No Job Descriptions Found"
            emptyStateDescription={user?.role === 'CANDIDATE' ? "Check back later for new job postings." : "Start by publishing your first job listing to the system or adjust your filters."}
            filters={[]}
            renderAdditionalActions={user?.role === 'CANDIDATE' ? undefined : () => (
              <button
                onClick={() => setViewMode('card')}
                className="bg-slate-50 hover:bg-slate-100 dark:bg-slate-950 dark:hover:bg-slate-800 border border-slate-200 dark:border-slate-800 rounded-none px-4 py-2.5 text-xs font-bold transition text-slate-700 dark:text-slate-300 flex items-center gap-1.5 cursor-pointer"
              >
                <i className="fa-solid fa-grip"></i> Card View
              </button>
            )}
          />

        ) : filteredJobs.length === 0 ? (
          <div className="border border-dashed border-slate-300 dark:border-slate-800 rounded-none p-16 text-center text-slate-500 dark:text-slate-400 bg-white dark:bg-slate-900/20">
            <p className="text-lg font-medium mb-1">No job descriptions found</p>
            <p className="text-sm text-slate-400 dark:text-slate-500 mb-6">Start by publishing your first job listing to the system or clear your filters.</p>
            {activeFilterCount > 0 ? (
              <button
                onClick={clearAllFilters}
                className="bg-[#405189] hover:bg-[#334267] text-white text-sm font-semibold px-4 py-2 rounded-none transition cursor-pointer"
              >
                Clear Filters
              </button>
            ) : hasAddPermission ? (
              <button
                onClick={openCreateModal}
                className="bg-slate-800 hover:bg-slate-700 text-white text-sm font-semibold px-4 py-2 rounded-none transition cursor-pointer"
              >
                Create Job
              </button>
            ) : null}
          </div>
        ) : (
          <div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
            {filteredJobs.map((job) => (
              <div
                key={job.id}
                className="bg-white dark:bg-slate-900 border border-slate-200 dark:border-slate-800 rounded-none p-6 flex flex-col justify-between hover:border-slate-300 dark:hover:border-slate-700 hover:shadow-md dark:hover:shadow-xl dark:hover:shadow-slate-950 transition duration-300 relative group"
              >
                <div>
                  <div className="flex justify-between items-start mb-3">
                    <span className="text-xs font-semibold uppercase tracking-wider text-indigo-600 dark:text-indigo-400 flex items-center gap-1">
                      <i className="fa-solid fa-location-dot"></i> {job.location}
                    </span>
                    <span
                      className={`text-xs px-2.5 py-1 rounded-full font-bold border ${job.status === 'Published'
                        ? 'bg-emerald-50 dark:bg-emerald-950/50 text-emerald-700 dark:text-emerald-400 border-emerald-200 dark:border-emerald-800'
                        : job.status === 'Closed'
                          ? 'bg-slate-100 dark:bg-slate-800 text-slate-600 dark:text-slate-400 border-slate-200 dark:border-slate-700'
                          : 'bg-amber-50 dark:bg-amber-950/50 text-amber-700 dark:text-amber-400 border-amber-200 dark:border-amber-800'
                        }`}
                    >
                      {job.status}
                    </span>
                  </div>
                  <h3 className="text-lg font-bold text-slate-800 dark:text-white mb-1 group-hover:text-indigo-600 dark:group-hover:text-indigo-300 transition duration-200">
                    {job.title}
                  </h3>

                  {job.client_name && (
                    <p className="text-xs font-semibold text-indigo-700 dark:text-indigo-400/90 mb-3 bg-indigo-50 dark:bg-indigo-950/20 border border-indigo-100 dark:border-indigo-900/30 px-2.5 py-1 rounded-none w-fit flex items-center gap-1.5">
                      <i className="fa-solid fa-building text-xs"></i> Client: {job.client_name}
                    </p>
                  )}

                  <p className="text-xs text-slate-400 dark:text-slate-500 mb-4">
                    Created by <span title={job.created_by_email} className="cursor-default font-semibold">{job.created_by_name || job.created_by_email}</span> on {formatDate(job.created_at)}
                  </p>

                  <p className="text-sm text-slate-600 dark:text-slate-300 line-clamp-4 mb-6">
                    {cleanHtmlText(job.work_details)}
                  </p>
                </div>

                {(hasChangePermission || hasDeletePermission) && (
                  <div className="flex items-center gap-2 border-t border-slate-100 dark:border-slate-800 pt-4 mt-auto">
                    {hasChangePermission && (
                      <button
                        onClick={() => openEditModal(job)}
                        disabled={job.status === 'Published'}
                        title={job.status === 'Published' ? 'This JD is published and cannot be edited' : undefined}
                        className="flex-1 text-center bg-slate-100 hover:bg-slate-200 dark:bg-slate-800 dark:hover:bg-slate-700 text-slate-700 dark:text-slate-200 text-xs font-bold py-2 rounded-none transition cursor-pointer flex items-center justify-center gap-1.5 disabled:opacity-40 disabled:cursor-not-allowed disabled:hover:bg-slate-100 dark:disabled:hover:bg-slate-800"
                      >
                        <i className="fa-solid fa-pen-to-square"></i> Edit Details
                      </button>
                    )}
                    {hasDeletePermission && (
                      <button
                        onClick={() => handleDelete(job.id)}
                        disabled={job.status !== 'Draft'}
                        className="text-center bg-rose-50 hover:bg-rose-100/70 dark:bg-rose-950/30 dark:hover:bg-rose-900/50 dark:border-rose-900/40 text-rose-600 dark:text-rose-400 border border-rose-200 dark:border-rose-900/40 text-xs font-bold p-2.5 rounded-none transition cursor-pointer disabled:opacity-40 disabled:cursor-not-allowed disabled:hover:bg-rose-50 dark:disabled:hover:bg-rose-950/30"
                        title={job.status !== 'Draft' ? 'Only Draft JDs can be deleted' : 'Delete Job'}
                      >
                        <i className="fa-solid fa-trash"></i>
                      </button>
                    )}
                  </div>
                )}
              </div>
            ))}
          </div>
        )}

        {/* Card-view pagination (table view has its own footer) */}
        {viewMode === 'card' && user?.role !== 'CANDIDATE' && total > pagination.pageSize && (
          <div className="flex items-center justify-between mt-6 text-sm text-slate-600 dark:text-slate-400">
            <span>
              Page {pagination.pageIndex + 1} of {Math.max(1, Math.ceil(total / pagination.pageSize))}
              <span className="text-slate-400 dark:text-slate-500"> · {total} total</span>
            </span>
            <div className="flex items-center gap-2">
              <button
                onClick={() => setPagination((p) => ({ ...p, pageIndex: Math.max(0, p.pageIndex - 1) }))}
                disabled={pagination.pageIndex === 0}
                className="px-3 py-1.5 border border-slate-200 dark:border-slate-800 rounded-none font-semibold disabled:opacity-40 disabled:cursor-not-allowed hover:bg-slate-50 dark:hover:bg-slate-800 cursor-pointer"
              >
                Previous
              </button>
              <button
                onClick={() => setPagination((p) => ({ ...p, pageIndex: Math.min(Math.ceil(total / p.pageSize) - 1, p.pageIndex + 1) }))}
                disabled={pagination.pageIndex >= Math.ceil(total / pagination.pageSize) - 1}
                className="px-3 py-1.5 border border-slate-200 dark:border-slate-800 rounded-none font-semibold disabled:opacity-40 disabled:cursor-not-allowed hover:bg-slate-50 dark:hover:bg-slate-800 cursor-pointer"
              >
                Next
              </button>
            </div>
          </div>
        )}
      </main>

      {/* Post History Modal */}
      {postHistoryOpen && (
        <div className="fixed inset-0 z-50 flex items-center justify-center p-4">
          <div className="fixed inset-0 bg-slate-950/40 dark:bg-slate-950/80 backdrop-blur-sm" onClick={() => setPostHistoryOpen(false)}></div>
          <div className="bg-white dark:bg-slate-900 border border-slate-200 dark:border-slate-800 w-full max-w-4xl rounded-none relative z-10 shadow-2xl animate-in fade-in zoom-in duration-200 text-slate-800 dark:text-slate-100 flex flex-col max-h-[85vh]">

            {/* Header */}
            <div className="flex items-center justify-between gap-3 px-6 pt-5 pb-4 border-b border-slate-100 dark:border-slate-800 shrink-0">
              <div className="flex items-center gap-3 min-w-0">
                <div className="w-10 h-10 rounded-none bg-indigo-50 dark:bg-indigo-950/40 text-indigo-600 dark:text-indigo-400 flex items-center justify-center shrink-0">
                  <i className="fa-solid fa-clock-rotate-left"></i>
                </div>
                <div className="min-w-0">
                  <h3 className="text-base font-bold text-slate-900 dark:text-white leading-tight">
                    Social Media Posting History
                  </h3>
                  <p className="text-xs text-slate-400 truncate">All shared job descriptions posted to channels like LinkedIn, Naukri, and Career Portal.</p>
                </div>
              </div>
              <button onClick={() => setPostHistoryOpen(false)} className="w-8 h-8 rounded-none flex items-center justify-center text-slate-400 hover:text-slate-700 dark:hover:text-white hover:bg-slate-100 dark:hover:bg-slate-800 transition cursor-pointer">
                <i className="fa-solid fa-xmark"></i>
              </button>
            </div>

            {/* Table Area */}
            <div className="px-6 py-4 overflow-y-auto custom-scrollbar flex-1 min-h-0">
              {allPostings.length === 0 ? (
                <div className="py-12 text-center text-slate-400 dark:text-slate-500 text-sm">
                  <i className="fa-solid fa-share-nodes text-3xl mb-3 text-slate-300 dark:text-slate-700 block"></i>
                  No postings have been shared on social media yet.
                </div>
              ) : (
                <div className="border border-slate-200 dark:border-slate-800 rounded-none overflow-hidden">
                  <div className="overflow-x-auto">
                    <table className="w-full text-xs min-w-[700px]">
                      <thead>
                        <tr className="bg-slate-50 dark:bg-slate-950/40 border-b border-slate-200 dark:border-slate-800">
                          <th className="py-2.5 px-4 text-left font-extrabold text-[10px] uppercase tracking-wider text-slate-400">Job Title</th>
                          <th className="py-2.5 px-4 text-left font-extrabold text-[10px] uppercase tracking-wider text-slate-400">Channel</th>
                          <th className="py-2.5 px-4 text-left font-extrabold text-[10px] uppercase tracking-wider text-slate-400">Status</th>
                          <th className="py-2.5 px-4 text-left font-extrabold text-[10px] uppercase tracking-wider text-slate-400">Posted Date</th>
                          <th className="py-2.5 px-4 text-left font-extrabold text-[10px] uppercase tracking-wider text-slate-400">Details / Action</th>
                        </tr>
                      </thead>
                      <tbody className="divide-y divide-slate-100 dark:divide-slate-800">
                        {allPostings.map((p) => {
                          const isSuccess = p.status === 'POSTED';
                          const isFailed = p.status === 'FAILED';
                          return (
                            <tr key={p.id} className="hover:bg-slate-50 dark:hover:bg-slate-850/40 transition">
                              <td className="py-3 px-4 font-bold text-slate-900 dark:text-white">{p.jobTitle}</td>
                              <td className="py-3 px-4 font-semibold text-slate-700 dark:text-slate-300">
                                <span className="flex items-center gap-2">
                                  <i className={
                                    p.channel === 'LINKEDIN' ? 'fa-brands fa-linkedin text-[#0a66c2]' :
                                      p.channel === 'NAUKRI' ? 'fa-solid fa-n text-[#4a90d9]' :
                                        'fa-solid fa-globe text-emerald-600'
                                  }></i>
                                  {p.channel_label}
                                </span>
                              </td>
                              <td className="py-3 px-4">
                                <span className={`inline-flex items-center gap-1.5 px-2 py-0.5 rounded-full text-[10px] font-bold border ${isSuccess ? 'bg-emerald-50 dark:bg-emerald-950/50 text-emerald-700 dark:text-emerald-400 border-emerald-200 dark:border-emerald-800' :
                                  isFailed ? 'bg-rose-50 dark:bg-rose-950/40 text-rose-700 dark:text-rose-300 border-rose-200 dark:border-rose-900/40' :
                                    'bg-amber-50 dark:bg-amber-950/40 text-amber-700 dark:text-amber-300 border-amber-200 dark:border-amber-900/40'
                                  }`}>
                                  <span className={`w-1.5 h-1.5 rounded-full ${isSuccess ? 'bg-emerald-500' : isFailed ? 'bg-rose-500' : 'bg-amber-400'
                                    }`} />
                                  {p.status}
                                </span>
                              </td>
                              <td className="py-3 px-4 text-slate-500 dark:text-slate-400 font-semibold whitespace-nowrap">
                                {p.posted_at ? new Date(p.posted_at).toLocaleString('en-IN', {
                                  day: 'numeric',
                                  month: 'short',
                                  hour: 'numeric',
                                  minute: '2-digit',
                                }) : '—'}
                              </td>
                              <td className="py-3 px-4">
                                {isSuccess && p.external_url ? (
                                  <a
                                    href={p.external_url}
                                    target="_blank"
                                    rel="noreferrer"
                                    className="inline-flex items-center gap-1.5 text-[11px] font-bold text-indigo-600 dark:text-indigo-400 hover:underline"
                                  >
                                    <i className="fa-solid fa-arrow-up-right-from-square text-[9px]" /> Open Post
                                  </a>
                                ) : isFailed && p.error_message ? (
                                  <span className="text-rose-600 dark:text-rose-450 block max-w-[200px] truncate" title={p.error_message}>
                                    {p.error_message}
                                  </span>
                                ) : (
                                  <span className="text-slate-400">—</span>
                                )}
                              </td>
                            </tr>
                          );
                        })}
                      </tbody>
                    </table>
                  </div>
                </div>
              )}
            </div>

            {/* Footer */}
            <div className="flex items-center justify-end px-6 py-4 border-t border-slate-100 dark:border-slate-800 shrink-0">
              <button
                onClick={() => setPostHistoryOpen(false)}
                className="bg-slate-50 dark:bg-slate-950 hover:bg-slate-100 dark:hover:bg-slate-800 border border-slate-200 dark:border-slate-800 rounded-none px-5 py-2.5 text-xs font-semibold transition cursor-pointer"
              >
                Close
              </button>
            </div>
          </div>
        </div>
      )}

      {/* Modal Dialog */}
      {isModalOpen && (
        <div className="fixed inset-0 z-50 flex items-center justify-center p-4">
          <div className="fixed inset-0 bg-slate-950/40 dark:bg-slate-950/80 backdrop-blur-sm" onClick={() => setIsModalOpen(false)}></div>
          <div className="bg-white dark:bg-slate-900 border border-slate-200 dark:border-slate-800 w-full max-w-3xl rounded-none relative z-10 shadow-2xl animate-in fade-in zoom-in duration-200 text-slate-800 dark:text-slate-100 flex flex-col max-h-[90vh]">
            <h3 className="text-xl font-bold text-slate-900 dark:text-white px-6 pt-6 pb-4 shrink-0">
              {editingJobId ? 'Edit Job Description' : 'Create Job Description'}
            </h3>
            <form onSubmit={handleSubmit} className="flex flex-col min-h-0 flex-1">
              {formError && (
                <div className="mx-6 mb-3 flex items-start gap-2.5 rounded-none border border-rose-200 dark:border-rose-900 bg-rose-50 dark:bg-rose-950/30 px-4 py-3 shrink-0">
                  <i className="fa-solid fa-circle-exclamation text-rose-500 mt-0.5"></i>
                  <p className="text-xs font-semibold text-rose-700 dark:text-rose-300 flex-1">{formError}</p>
                  <button type="button" onClick={() => setFormError('')}
                    className="text-rose-400 hover:text-rose-600 cursor-pointer">
                    <i className="fa-solid fa-xmark"></i>
                  </button>
                </div>
              )}
              {/* Tabs */}
              <div className="flex items-center justify-between gap-3 px-6 pb-3 shrink-0 border-b border-slate-100 dark:border-slate-800">
                <div className="flex gap-1.5">
                  {([
                    { id: 'details', label: 'JD Details', icon: 'fa-file-lines' },
                    { id: 'questions', label: `JD Questions & Answers${questions.length ? ` (${questions.length})` : ''}`, icon: 'fa-circle-question' },
                  ] as const).map((tab) => (
                    <button
                      key={tab.id}
                      type="button"
                      onClick={() => setActiveJobTab(tab.id)}
                      className={`flex items-center gap-2 px-4 py-2 rounded-none text-xs font-bold transition cursor-pointer ${activeJobTab === tab.id
                        ? 'bg-indigo-600 text-white shadow-md shadow-indigo-600/15'
                        : 'bg-slate-50 hover:bg-slate-100 dark:bg-slate-950 dark:hover:bg-slate-800 text-slate-600 dark:text-slate-400'
                        }`}
                    >
                      <i className={`fa-solid ${tab.icon}`}></i> {tab.label}
                    </button>
                  ))}
                </div>



                <a href={activeJobTab === 'questions' ? '/templates/JD-QA-Template.docx' : '/templates/JD-Template.docx'} download
                  className="inline-flex items-center gap-1.5 px-3 py-2 rounded-none text-xs font-bold text-[#405189] bg-[#405189]/10 hover:bg-[#405189]/20 border border-[#405189]/30 transition shrink-0">
                  <i className="fa-solid fa-download"></i> {activeJobTab === 'questions' ? 'JD Q&A Template' : 'Sample JD Details Format'}
                </a>
              </div>

              <div className="space-y-4 overflow-y-auto px-6 py-4 flex-1 min-h-0 custom-scrollbar">
                {activeJobTab === 'details' && (
                  <div className="space-y-4">
                    {/* Upload / drag-drop JD to auto-fill */}
                    <div
                      onDragOver={(e) => { e.preventDefault(); setDragOver(true); }}
                      onDragLeave={() => setDragOver(false)}
                      onDrop={(e) => { e.preventDefault(); setDragOver(false); const f = e.dataTransfer.files?.[0]; if (f) parseDocument(f); }}
                      className={`rounded-none border-2 border-dashed px-4 py-5 text-center transition ${dragOver ? 'border-[#405189] bg-[#405189]/5' : 'border-slate-300 dark:border-slate-700 bg-slate-50 dark:bg-slate-950'}`}
                    >
                      <input id="jd-file" type="file" accept=".pdf,.doc,.docx,.txt" className="hidden"
                        onChange={(e) => { const f = e.target.files?.[0]; if (f) parseDocument(f); e.currentTarget.value = ''; }} />
                      {parsing ? (
                        <p className="text-sm text-[#405189] font-medium"><i className="fa-solid fa-spinner fa-spin mr-2"></i>Reading document…</p>
                      ) : attachment ? (
                        <div className="flex items-center justify-center gap-2 text-sm">
                          <i className="fa-solid fa-file-lines text-[#0ab39c]"></i>
                          <span className="font-medium text-[#495057] dark:text-slate-200 truncate max-w-[60%]">{attachment.name}</span>
                          <label htmlFor="jd-file" className="text-xs text-[#405189] hover:underline cursor-pointer">Replace</label>
                          <button type="button" onClick={handleRemoveJdFile} className="text-xs text-rose-500 hover:underline cursor-pointer">Remove</button>
                        </div>
                      ) : existingAttachment ? (
                        <div className="flex items-center justify-center gap-3 text-sm">
                          <button
                            type="button"
                            onClick={() => setPreviewDocModal({ url: existingAttachment, title: title || 'Attached Document' })}
                            className="text-[#405189] hover:underline cursor-pointer inline-flex items-center"
                          >
                            <i className="fa-solid fa-paperclip mr-1"></i>View attached document
                          </button>
                          <label htmlFor="jd-file" className="text-xs text-[#405189] hover:underline cursor-pointer">Replace &amp; re-parse</label>
                        </div>
                      ) : (
                        <>
                          <label htmlFor="jd-file" className="cursor-pointer block">
                            <i className="fa-solid fa-cloud-arrow-up text-2xl text-slate-400"></i>
                            <p className="text-sm font-medium text-[#495057] dark:text-slate-200 mt-1">Drag &amp; drop a JD here, or <span className="text-[#405189]">browse</span></p>
                            <p className="text-xs text-slate-400 mt-0.5">PDF, DOC, DOCX or TXT (max 10 MB) — we&apos;ll auto-fill the form and attach the file</p>
                          </label>
                        </>
                      )}
                    </div>

                    <div>
                      <label className="block text-xs font-bold uppercase tracking-wider text-slate-500 dark:text-slate-400 mb-1">{renderRequiredLabel('Job Title')}</label>
                      <input
                        value={title}
                        placeholder="e.g. Senior Software Engineer"
                        onChange={(e) => handleTitleChange(e.target.value)}
                        className={`w-full bg-slate-50 dark:bg-slate-950 border rounded-none px-4 py-2.5 text-sm focus:outline-none transition text-slate-900 dark:text-white ${titleError ? 'border-rose-300 focus:border-rose-500' : 'border-slate-200 dark:border-slate-800 focus:border-indigo-500'}`}
                      />
                      {titleError && (
                        <p className="mt-1.5 text-[11px] font-medium text-rose-600 dark:text-rose-400">{titleError}</p>
                      )}
                    </div>

                    <div>
                      <label className="block text-xs font-bold uppercase tracking-wider text-slate-500 dark:text-slate-400 mb-1">{renderRequiredLabel('Associated Client')}</label>
                      <SearchableSelect
                        value={clientId}
                        onChange={setClientId}
                        onSearchChange={handleClientSearch}
                        loading={asyncClientsLoading}
                        placeholder="Select Client..."
                        isClearable={false}
                        options={clients.map((c) => ({
                          value: String(c.id),
                          label: `🏢 ${c.name}`,
                        }))}
                      />
                    </div>

                    <div className="grid grid-cols-1 md:grid-cols-2 gap-4">
                      <div>
                        <label className="block text-xs font-bold uppercase tracking-wider text-slate-500 dark:text-slate-400 mb-1">{renderRequiredLabel('Department')}</label>
                        <input value={department} placeholder="e.g. Engineering" onChange={(e) => setDepartment(e.target.value)}
                          className="w-full bg-slate-50 dark:bg-slate-950 border border-slate-200 dark:border-slate-800 focus:border-indigo-500 rounded-none px-4 py-2.5 text-sm focus:outline-none transition text-slate-900 dark:text-white" />
                      </div>
                      <div>
                        <label className="block text-xs font-bold uppercase tracking-wider text-slate-500 dark:text-slate-400 mb-1">{renderRequiredLabel('Location')}</label>
                        <input value={location} placeholder="e.g. Pune (Hybrid)" onChange={(e) => setLocation(e.target.value)}
                          className="w-full bg-slate-50 dark:bg-slate-950 border border-slate-200 dark:border-slate-800 focus:border-indigo-500 rounded-none px-4 py-2.5 text-sm focus:outline-none transition text-slate-900 dark:text-white" />
                      </div>
                    </div>

                    <div className="grid grid-cols-1 md:grid-cols-3 gap-4">
                      <div>
                        <label className="block text-xs font-bold uppercase tracking-wider text-slate-500 dark:text-slate-400 mb-1">{renderRequiredLabel('Experience Band')}</label>
                        <input value={experienceBand} placeholder="e.g. 3-5 years" onChange={(e) => setExperienceBand(e.target.value)}
                          className="w-full bg-slate-50 dark:bg-slate-950 border border-slate-200 dark:border-slate-800 focus:border-indigo-500 rounded-none px-4 py-2.5 text-sm focus:outline-none transition text-slate-900 dark:text-white" />
                      </div>
                      <div>
                        <label className="block text-xs font-bold uppercase tracking-wider text-slate-500 dark:text-slate-400 mb-1">CTC Band</label>
                        <input value={ctcBand} placeholder="e.g. 10-15 LPA" onChange={(e) => setCtcBand(e.target.value)}
                          className="w-full bg-slate-50 dark:bg-slate-950 border border-slate-200 dark:border-slate-800 focus:border-indigo-500 rounded-none px-4 py-2.5 text-sm focus:outline-none transition text-slate-900 dark:text-white" />
                      </div>
                      <div>
                        <label className="block text-xs font-bold uppercase tracking-wider text-slate-500 dark:text-slate-400 mb-1">{renderRequiredLabel('Notice Period')}</label>
                        <input value={noticePeriod} placeholder="e.g. 30 days" onChange={(e) => setNoticePeriod(e.target.value)}
                          className="w-full bg-slate-50 dark:bg-slate-950 border border-slate-200 dark:border-slate-800 focus:border-indigo-500 rounded-none px-4 py-2.5 text-sm focus:outline-none transition text-slate-900 dark:text-white" />
                      </div>
                    </div>

                    <div className="grid grid-cols-1 md:grid-cols-3 gap-4">
                      <div>
                        <label className="block text-xs font-bold uppercase tracking-wider text-slate-500 dark:text-slate-400 mb-1">Shift</label>
                        <SearchableSelect
                          value={shift}
                          onChange={(val) => setShift(val || '')}
                          isClearable={true}
                          placeholder="Select shift..."
                          options={[
                            { value: 'Day', label: 'Day' },
                            { value: 'Night', label: 'Night' },
                            { value: 'Rotational', label: 'Rotational' },
                            { value: 'Flexible', label: 'Flexible' },
                          ]}
                        />
                      </div>
                      <div>
                        <label className="block text-xs font-bold uppercase tracking-wider text-slate-500 dark:text-slate-400 mb-1">{renderRequiredLabel('Priority')}</label>
                        <SearchableSelect
                          value={priority}
                          onChange={(val) => setPriority((val as 'High' | 'Medium' | 'Low') || 'Medium')}
                          isClearable={false}
                          options={[
                            { value: 'High', label: 'High' },
                            { value: 'Medium', label: 'Medium' },
                            { value: 'Low', label: 'Low' },
                          ]}
                        />
                      </div>
                      <div>
                        <label className="block text-xs font-bold uppercase tracking-wider text-slate-500 dark:text-slate-400 mb-1">{renderRequiredLabel('Status')}</label>
                        <div title={!editingApproved ? 'Status can only be changed after the Job Description has been approved.' : undefined}>
                          <SearchableSelect
                            value={status}
                            onChange={(val) => setStatus(val as 'Draft' | 'Published' | 'Closed')}
                            isClearable={false}
                            disabled={!editingApproved}
                            options={statusOptions}
                          />
                        </div>
                        {!editingApproved && (
                          <p className="text-[10px] text-slate-400 mt-1">
                            <i className="fa-solid fa-lock mr-1" />
                            Status can only be changed after the Job Description has been approved.
                          </p>
                        )}
                      </div>
                    </div>

                    <div className="grid grid-cols-1 md:grid-cols-3 gap-4">
                      <div>
                        <label className="block text-xs font-bold uppercase tracking-wider text-slate-500 dark:text-slate-400 mb-1">Working Days</label>
                        <input value={workingDays} placeholder="e.g. 5 days (Mon-Fri)" onChange={(e) => setWorkingDays(e.target.value)}
                          className="w-full bg-slate-50 dark:bg-slate-950 border border-slate-200 dark:border-slate-800 focus:border-indigo-500 rounded-none px-4 py-2.5 text-sm focus:outline-none transition text-slate-900 dark:text-white" />
                      </div>
                      <div>
                        <label className="block text-xs font-bold uppercase tracking-wider text-slate-500 dark:text-slate-400 mb-1">{renderRequiredLabel('No. of Positions')}</label>
                        <input type="number" min="1" value={numPositions} placeholder="e.g. 3" onChange={(e) => setNumPositions(e.target.value)}
                          className="w-full bg-slate-50 dark:bg-slate-950 border border-slate-200 dark:border-slate-800 focus:border-indigo-500 rounded-none px-4 py-2.5 text-sm focus:outline-none transition text-slate-900 dark:text-white" />
                      </div>
                      <div>
                        <label className="block text-xs font-bold uppercase tracking-wider text-slate-500 dark:text-slate-400 mb-1">Certification</label>
                        <input value={certification} placeholder="e.g. AWS Certified Developer" onChange={(e) => setCertification(e.target.value)}
                          className="w-full bg-slate-50 dark:bg-slate-950 border border-slate-200 dark:border-slate-800 focus:border-indigo-500 rounded-none px-4 py-2.5 text-sm focus:outline-none transition text-slate-900 dark:text-white" />
                      </div>
                    </div>

                    <div>
                      <label className="block text-xs font-bold uppercase tracking-wider text-slate-500 dark:text-slate-400 mb-1">Qualifications</label>
                      <input value={qualifications} placeholder="e.g. B.Tech / MCA in Computer Science" onChange={(e) => setQualifications(e.target.value)}
                        className="w-full bg-slate-50 dark:bg-slate-950 border border-slate-200 dark:border-slate-800 focus:border-indigo-500 rounded-none px-4 py-2.5 text-sm focus:outline-none transition text-slate-900 dark:text-white" />
                    </div>

                    <div className="grid grid-cols-1 md:grid-cols-2 gap-4">
                      <div>
                        <label className="block text-xs font-bold uppercase tracking-wider text-slate-500 dark:text-slate-400 mb-1">Must-have Skills</label>
                        <textarea value={mustHaveSkills} rows={3} placeholder="e.g. Python, Django, PostgreSQL" onChange={(e) => setMustHaveSkills(e.target.value)}
                          className="w-full bg-slate-50 dark:bg-slate-950 border border-slate-200 dark:border-slate-800 focus:border-indigo-500 rounded-none px-4 py-2.5 text-sm focus:outline-none transition font-sans text-slate-900 dark:text-white" />
                      </div>
                      <div>
                        <label className="block text-xs font-bold uppercase tracking-wider text-slate-500 dark:text-slate-400 mb-1">Good-to-have Skills</label>
                        <textarea value={goodToHaveSkills} rows={3} placeholder="e.g. Docker, AWS, React" onChange={(e) => setGoodToHaveSkills(e.target.value)}
                          className="w-full bg-slate-50 dark:bg-slate-950 border border-slate-200 dark:border-slate-800 focus:border-indigo-500 rounded-none px-4 py-2.5 text-sm focus:outline-none transition font-sans text-slate-900 dark:text-white" />
                      </div>
                    </div>

                    <div>
                      <label className="block text-xs font-bold uppercase tracking-wider text-slate-500 dark:text-slate-400 mb-1">Work Details & Requirements</label>
                      <RichTextEditor
                        value={workDetails}
                        onChange={setWorkDetails}
                        height={320}
                        placeholder="Provide full description of job duties, key qualifications, skills, and compensation..."
                      />
                    </div>
                  </div>
                )}

                {activeJobTab === 'questions' && (
                  <div className="space-y-4">
                    <div className="flex items-center justify-between gap-3 flex-wrap">
                      <div>
                        <label className="block text-xs font-bold uppercase tracking-wider text-slate-500 dark:text-slate-400">Screening Questions & Answers</label>
                        <p className="text-[11px] text-slate-400 dark:text-slate-500 mt-0.5">Add a question and, optionally, the expected/ideal answer.</p>
                      </div>
                      <button type="button" onClick={() => setQuestions([...questions, { question: '', answer: '' }])}
                        className="flex items-center gap-1.5 text-xs font-semibold text-[#405189] hover:text-[#364574] transition cursor-pointer shrink-0">
                        <i className="fa-solid fa-plus"></i> Add question
                      </button>
                    </div>

                    {/* Upload / drag-drop a filled Q&A template to auto-populate */}
                    <div
                      onDragOver={(e) => { e.preventDefault(); setQaDragOver(true); }}
                      onDragLeave={() => setQaDragOver(false)}
                      onDrop={(e) => { e.preventDefault(); setQaDragOver(false); const f = e.dataTransfer.files?.[0]; if (f) parseQaDocument(f); }}
                      className={`rounded-none border-2 border-dashed px-4 py-4 text-center transition ${qaDragOver ? 'border-[#405189] bg-[#405189]/5' : 'border-slate-300 dark:border-slate-700 bg-slate-50 dark:bg-slate-950'}`}
                    >
                      <input id="jd-qa-file" type="file" accept=".pdf,.docx,.txt" className="hidden"
                        onChange={(e) => { const f = e.target.files?.[0]; if (f) parseQaDocument(f); e.currentTarget.value = ''; }} />
                      {parsingQa ? (
                        <p className="text-sm text-[#405189] font-medium"><i className="fa-solid fa-spinner fa-spin mr-2"></i>Reading Q&amp;A template…</p>
                      ) : qaFile ? (
                        <div className="flex items-center justify-center gap-2 text-sm">
                          <i className="fa-solid fa-file-lines text-[#0ab39c]"></i>
                          <span className="font-medium text-[#495057] dark:text-slate-200 truncate max-w-[60%]">{qaFile.name}</span>
                          <label htmlFor="jd-qa-file" className="text-xs text-[#405189] hover:underline cursor-pointer">Replace</label>
                          <button type="button" onClick={() => setQaFile(null)} className="text-xs text-rose-500 hover:underline cursor-pointer">Remove</button>
                        </div>
                      ) : (
                        <label htmlFor="jd-qa-file" className="cursor-pointer block">
                          <i className="fa-solid fa-cloud-arrow-up text-xl text-slate-400"></i>
                          <p className="text-sm font-medium text-[#495057] dark:text-slate-200 mt-1">Drag &amp; drop a filled Q&amp;A template here, or <span className="text-[#405189]">browse</span></p>
                          <p className="text-xs text-slate-400 mt-0.5">PDF, DOCX or TXT (max 10 MB) — parsed questions are added below and stay fully editable</p>
                        </label>
                      )}
                    </div>

                    {questions.length === 0 && (
                      <div className="rounded-none border border-dashed border-slate-300 dark:border-slate-700 bg-slate-50 dark:bg-slate-950 px-4 py-8 text-center">
                        <i className="fa-solid fa-circle-question text-2xl text-slate-300 dark:text-slate-600"></i>
                        <p className="text-xs text-slate-400 dark:text-slate-500 mt-2">No screening questions yet. Click “Add question” to create one.</p>
                      </div>
                    )}

                    <div className="space-y-3">
                      {questions.map((q, i) => (
                        <div key={i} className="rounded-none border border-slate-200 dark:border-slate-800 bg-slate-50 dark:bg-slate-950/50 p-3">
                          <div className="flex items-center justify-between mb-2">
                            <span className="inline-flex items-center gap-1.5 text-[11px] font-extrabold text-[#405189]">
                              <span className="inline-flex items-center justify-center w-5 h-5 rounded-full bg-[#405189] text-white text-[10px]">{i + 1}</span>
                              Question {i + 1}
                            </span>
                            <button type="button"
                              onClick={() => {
                                const isBlank = !q.question.trim() && !q.answer.trim();
                                if (isBlank) {
                                  setQuestions((prev) => prev.filter((_, k) => k !== i));
                                  return;
                                }
                                showConfirmDelete('Do you want to delete this question?', () =>
                                  setQuestions((prev) => prev.filter((_, k) => k !== i))
                                );
                              }}
                              title="Remove question"
                              className="w-7 h-7 shrink-0 rounded-none flex items-center justify-center text-slate-400 hover:text-rose-600 hover:bg-rose-50 dark:hover:bg-rose-950/30 transition cursor-pointer">
                              <i className="fa-solid fa-trash text-xs"></i>
                            </button>
                          </div>
                          <input
                            value={q.question}
                            placeholder="e.g. How many years of Django experience do you have?"
                            onChange={(e) => setQuestions(questions.map((x, k) => (k === i ? { ...x, question: e.target.value } : x)))}
                            className="w-full bg-white dark:bg-slate-900 border border-slate-200 dark:border-slate-800 focus:border-indigo-500 rounded-none px-3 py-2 text-sm focus:outline-none transition text-slate-900 dark:text-white mb-2"
                          />
                          <label className="block text-[11px] font-extrabold text-[#0ab39c] mb-1">
                            <i className="fa-solid fa-reply fa-rotate-180 mr-1 text-[10px]"></i>Ans
                          </label>
                          <textarea
                            value={q.answer}
                            rows={2}
                            placeholder="Expected / ideal answer (optional)"
                            onChange={(e) => setQuestions(questions.map((x, k) => (k === i ? { ...x, answer: e.target.value } : x)))}
                            className="w-full bg-white dark:bg-slate-900 border border-slate-200 dark:border-slate-800 focus:border-indigo-500 rounded-none px-3 py-2 text-sm focus:outline-none transition font-sans text-slate-900 dark:text-white"
                          />
                        </div>
                      ))}
                    </div>
                  </div>
                )}
              </div>

              <div className="flex justify-end gap-3 px-6 py-4 border-t border-slate-100 dark:border-slate-800 shrink-0">
                <button
                  type="button"
                  onClick={() => setIsModalOpen(false)}
                  className="px-4 py-2 text-sm text-slate-500 hover:text-slate-800 dark:text-slate-400 dark:hover:text-white transition cursor-pointer"
                >
                  Cancel
                </button>
                <button
                  type="submit"
                  disabled={submitting}
                  className="bg-indigo-600 hover:bg-indigo-500 disabled:bg-indigo-400 dark:disabled:bg-indigo-800 text-white text-sm font-semibold px-5 py-2.5 rounded-none shadow-lg transition cursor-pointer"
                >
                  {submitting ? 'Saving...' : editingJobId ? 'Save Changes' : 'Post JD'}
                </button>
              </div>
            </form>
          </div>
        </div>
      )}

      {/* Job Details Popup */}
      {viewJob && (
        <JobDetailsModal
          jobId={viewJob.id}
          jobTitle={viewJob.title}
          isOpen={!!viewJob}
          onClose={() => setViewJob(null)}
          onEdit={hasChangePermission ? () => {
            const job = viewJob;
            setViewJob(null);
            openEditModal(job);
          } : undefined}
        />
      )}

      {/* Job Publish Popup */}
      {publishStep && publishJob && (
        <div className="fixed inset-0 z-50 flex items-center justify-center p-4">
          <div className="fixed inset-0 bg-slate-950/40 dark:bg-slate-950/80 backdrop-blur-sm" onClick={() => !posting && closePublishModal()}></div>
          <div className="bg-white dark:bg-slate-900 border border-slate-200 dark:border-slate-800 w-full max-w-3xl rounded-none relative z-10 shadow-2xl animate-in fade-in zoom-in duration-200 text-slate-800 dark:text-slate-100 flex flex-col max-h-[90vh]">
            <div className="flex items-center justify-between px-6 pt-5 pb-4 border-b border-slate-100 dark:border-slate-800 shrink-0">
              <div className="flex items-center gap-3">
                <div className="w-10 h-10 rounded-none bg-violet-50 dark:bg-violet-950/40 text-violet-600 dark:text-violet-400 flex items-center justify-center">
                  <i className="fa-solid fa-bullhorn"></i>
                </div>
                <div>
                  <h3 className="text-base font-bold text-slate-900 dark:text-white leading-tight">Publish Job Preview</h3>
                  <p className="text-xs text-slate-400">Review the JD and select the platforms to publish to.</p>
                </div>
                {/* Publish status of this JD — Draft until it has actually gone
                    out to a channel, Published afterwards. */}
                {(() => {
                  const pub = publishJob.publication_status
                    ?? (((publishJob.postings ?? []).some((p) => p.status === 'POSTED')) ? 'published' : 'draft');
                  const isPublished = pub === 'published';
                  return (
                    <span
                      title={isPublished
                        ? 'This JD has already been published to at least one platform.'
                        : 'This JD has not been published to any platform yet.'}
                      className={`inline-flex items-center gap-1.5 text-[10px] font-extrabold uppercase tracking-wider border px-2.5 py-1 rounded-none ${isPublished
                        ? 'bg-emerald-50 dark:bg-emerald-950/40 text-emerald-700 dark:text-emerald-400 border-emerald-200 dark:border-emerald-800'
                        : 'bg-amber-50 dark:bg-amber-950/40 text-amber-700 dark:text-amber-400 border-amber-200 dark:border-amber-800'}`}
                    >
                      <i className={`fa-solid ${isPublished ? 'fa-circle-check' : 'fa-pen-ruler'} text-[9px]`} />
                      {isPublished ? 'Published' : 'Draft'}
                    </span>
                  );
                })()}
              </div>
              <button onClick={closePublishModal} disabled={posting}
                className="w-8 h-8 rounded-none flex items-center justify-center text-slate-400 hover:text-slate-700 dark:hover:text-white hover:bg-slate-100 dark:hover:bg-slate-800 transition cursor-pointer disabled:opacity-50">
                <i className="fa-solid fa-xmark"></i>
              </button>
            </div>

            <div className="px-6 py-4 overflow-y-auto custom-scrollbar flex-1 min-h-0">
              {publishStep === 'preview' && (
                <>
                  <p className="text-[10px] uppercase tracking-wider font-extrabold text-slate-400 mb-3">Job Preview</p>
                  <div className="rounded-none overflow-hidden border border-slate-200 dark:border-slate-800">
                    <div className="p-5 bg-violet-950 text-white">
                      <p className="text-xs font-extrabold uppercase tracking-widest text-violet-300">{publishJob.client_name || 'TA-ATS'}</p>
                      <p className="text-2xl font-black mt-2">{publishJob.title}</p>
                      <div className="grid grid-cols-2 gap-3 mt-4 text-sm">
                        {[
                          ['Location', publishJob.location || '—'],
                          ['Experience', publishJob.experience_band || '—'],
                          ['CTC', publishJob.ctc_band || '—'],
                          ['Shift', publishJob.shift || '—'],
                        ].map(([label, value]) => (
                          <p key={label}><span className="opacity-70">{label}:</span> <span className="font-semibold">{value}</span></p>
                        ))}
                      </div>
                    </div>
                    <div className="p-5 bg-slate-50 dark:bg-slate-950/40 text-slate-800 dark:text-slate-100 space-y-4">
                      {publishJob.qualifications && (
                        <div>
                          <p className="text-[10px] uppercase tracking-wider font-extrabold text-slate-400 mb-1">Qualifications</p>
                          <p className="text-sm text-slate-700 dark:text-slate-300 whitespace-pre-line">{publishJob.qualifications}</p>
                        </div>
                      )}
                      <div>
                        <p className="text-[10px] uppercase tracking-wider font-extrabold text-slate-400 mb-1">Job Description</p>
                        <p className="text-sm text-slate-700 dark:text-slate-300 leading-relaxed whitespace-pre-line">
                          {cleanHtmlText(publishJob.work_details)}
                        </p>
                      </div>
                    </div>
                  </div>

                  <div className="mt-5">
                    <p className="text-[10px] uppercase tracking-wider font-extrabold text-slate-400 mb-2">Select Platforms</p>
                    <div className="grid grid-cols-1 sm:grid-cols-2 gap-2">
                      {PUBLISH_CHANNELS.map((ch) => {
                        const alreadyPosted = (publishJob.postings ?? []).some((p) => p.channel === ch.key && p.status === 'POSTED');
                        const checked = publishChannels.includes(ch.key);
                        return (
                          <label key={ch.key}
                            className={`flex items-center gap-3 border rounded-none px-4 py-3 transition ${alreadyPosted
                              ? 'opacity-60 cursor-not-allowed border-slate-200 dark:border-slate-800'
                              : checked
                                ? 'border-violet-400 bg-violet-50/50 dark:bg-violet-950/30 dark:border-violet-600 cursor-pointer'
                                : 'border-slate-200 dark:border-slate-800 hover:border-violet-300 dark:hover:border-violet-700 cursor-pointer'} `}
                          >
                            <input
                              type="checkbox"
                              disabled={alreadyPosted || posting}
                              checked={checked}
                              onChange={() => togglePublishChannel(ch.key)}
                              className="w-4 h-4 rounded-none accent-violet-600 cursor-pointer disabled:cursor-not-allowed"
                            />
                            <i className={`${ch.icon} ${ch.color} text-lg`} />
                            <span className="min-w-0">
                              <span className="block text-xs font-bold text-slate-800 dark:text-slate-100">{ch.label}</span>
                              {alreadyPosted && <span className="block text-[10px] font-semibold text-emerald-600 dark:text-emerald-400">Already Posted</span>}
                            </span>
                          </label>
                        );
                      })}
                    </div>
                  </div>

                  <div className="mt-5">
                    <div className="flex items-center justify-between mb-2">
                      <p className="text-[10px] uppercase tracking-wider font-extrabold text-slate-400">Preview Links</p>
                      <span className="inline-flex items-center gap-1 text-[10px] font-bold text-slate-400">
                        <i className="fa-solid fa-lock text-[9px]" /> Secure source tracking
                      </span>
                    </div>
                    {previewLoading ? (
                      <p className="text-xs text-slate-400 flex items-center gap-2 px-1 py-2">
                        <i className="fa-solid fa-spinner fa-spin" /> Generating application links…
                      </p>
                    ) : !previewLinks ? (
                      <p className="text-xs text-slate-400 px-1 py-2">Preview links are unavailable right now.</p>
                    ) : publishChannels.length === 0 ? (
                      <p className="text-xs text-slate-400 px-1 py-2">Select a platform above to preview its application link.</p>
                    ) : (
                      <div className="space-y-2">
                        {previewLinks
                          .filter((l) => publishChannels.includes(l.channel))
                          .map((l) => {
                            const ch = PUBLISH_CHANNELS.find((c) => c.key === l.channel);
                            return (
                              <div key={l.channel} className="border border-slate-200 dark:border-slate-800 rounded-none px-3 py-2.5">
                                <div className="flex items-center gap-2 mb-1.5">
                                  <i className={`${ch?.icon ?? 'fa-solid fa-globe'} ${ch?.color ?? ''} text-sm`} />
                                  <span className="text-[11px] font-bold text-slate-700 dark:text-slate-200">{l.channel_label}</span>
                                </div>
                                <div className="flex items-center gap-2">
                                  <input
                                    readOnly
                                    value={l.url}
                                    onFocus={(e) => e.currentTarget.select()}
                                    className="flex-1 min-w-0 px-2 py-1.5 text-[11px] font-mono bg-slate-50 dark:bg-slate-950/60 border border-slate-200 dark:border-slate-800 text-slate-600 dark:text-slate-300 focus:outline-none focus:border-violet-400 cursor-text"
                                  />
                                  <button
                                    type="button"
                                    onClick={() => copyPreviewLink(l)}
                                    title="Copy link"
                                    className="shrink-0 h-8 px-2.5 border border-slate-200 dark:border-slate-800 text-slate-500 hover:text-violet-600 hover:border-violet-300 dark:hover:text-violet-400 transition cursor-pointer"
                                  >
                                    <i className={`fa-solid ${copiedLink === l.channel ? 'fa-check text-emerald-600' : 'fa-copy'} text-xs`} />
                                  </button>
                                  <a
                                    href={l.url} target="_blank" rel="noreferrer"
                                    title="Open link"
                                    className="shrink-0 h-8 px-2.5 flex items-center border border-slate-200 dark:border-slate-800 text-slate-500 hover:text-violet-600 hover:border-violet-300 dark:hover:text-violet-400 transition"
                                  >
                                    <i className="fa-solid fa-arrow-up-right-from-square text-xs" />
                                  </a>
                                </div>
                              </div>
                            );
                          })}
                      </div>
                    )}
                  </div>
                </>
              )}

              {publishStep === 'confirm' && (
                <div>
                  <p className="text-sm text-slate-700 dark:text-slate-200">You are about to publish this job description to the selected platforms.</p>
                  <div className="mt-4 space-y-2">
                    {publishChannels.map((key) => {
                      const ch = PUBLISH_CHANNELS.find((c) => c.key === key);
                      return (
                        <div key={key} className="flex items-center gap-2 rounded-none border border-slate-200 dark:border-slate-800 px-4 py-3">
                          <i className={`${ch?.icon ?? 'fa-solid fa-globe'} ${ch?.color ?? ''} text-lg`} />
                          <span className="text-sm font-semibold text-slate-900 dark:text-slate-100">{ch?.label ?? key}</span>
                        </div>
                      );
                    })}
                  </div>
                </div>
              )}

              {publishStep === 'results' && (
                <div className="space-y-3">
                  {(publishResults.length === 0) ? (
                    <p className="text-sm text-slate-500 dark:text-slate-400">No publish results available.</p>
                  ) : publishResults.map((result) => {
                    const ch = PUBLISH_CHANNELS.find((c) => c.key === result.channel);
                    const success = result.status === 'POSTED';
                    return (
                      <div key={result.channel} className={`rounded-none border px-4 py-3 ${success ? 'border-emerald-200 bg-emerald-50/70 dark:bg-emerald-950/20' : 'border-rose-200 bg-rose-50/70 dark:bg-rose-950/20'}`}>
                        <div className="flex items-center justify-between gap-3">
                          <div className="flex items-center gap-2">
                            <i className={`${ch?.icon ?? 'fa-solid fa-globe'} ${ch?.color ?? ''} text-lg`} />
                            <span className="font-bold text-slate-900 dark:text-slate-100">{ch?.label ?? result.channel}</span>
                          </div>
                          <span className={`text-[10px] font-bold uppercase ${success ? 'text-emerald-700' : 'text-rose-600'}`}>
                            {success ? 'Posted' : result.status}
                          </span>
                        </div>
                        {result.error_message && <p className="mt-2 text-xs text-rose-700 dark:text-rose-300">{result.error_message}</p>}
                        {result.external_url && (
                          <a href={result.external_url} target="_blank" rel="noreferrer" className="mt-2 inline-flex items-center gap-1 text-xs text-violet-600 dark:text-violet-300 hover:underline">
                            <i className="fa-solid fa-arrow-up-right-from-square text-[9px]" /> View post
                          </a>
                        )}
                      </div>
                    );
                  })}
                </div>
              )}
            </div>

            <div className="flex justify-end gap-3 px-6 py-4 border-t border-slate-100 dark:border-slate-800 shrink-0">
              {publishStep === 'preview' ? (
                <>
                  <button onClick={closePublishModal} disabled={posting}
                    className="px-4 py-2 text-sm text-slate-500 hover:text-slate-800 dark:text-slate-400 dark:hover:text-white transition cursor-pointer disabled:opacity-50">
                    Cancel
                  </button>
                  <button
                    onClick={() => setPublishStep('confirm')}
                    disabled={publishChannels.length === 0 || posting}
                    className="bg-violet-600 hover:bg-violet-500 disabled:opacity-40 disabled:cursor-not-allowed text-white text-sm font-semibold px-5 py-2.5 rounded-none shadow-lg transition cursor-pointer"
                  >
                    Continue{publishChannels.length > 0 ? ` (${publishChannels.length})` : ''}
                  </button>
                </>
              ) : publishStep === 'confirm' ? (
                <>
                  <button onClick={() => setPublishStep('preview')} disabled={posting}
                    className="px-4 py-2 text-sm text-slate-500 hover:text-slate-800 dark:text-slate-400 dark:hover:text-white transition cursor-pointer disabled:opacity-50">
                    Back
                  </button>
                  <button onClick={confirmPublish} disabled={posting}
                    className="bg-violet-600 hover:bg-violet-500 disabled:opacity-40 disabled:cursor-not-allowed text-white text-sm font-semibold px-5 py-2.5 rounded-none shadow-lg transition cursor-pointer flex items-center gap-2">
                    {posting && <i className="fa-solid fa-spinner fa-spin text-xs" />}
                    Publish
                  </button>
                </>
              ) : (
                <button onClick={closePublishModal}
                  className="bg-violet-600 hover:bg-violet-500 text-white text-sm font-semibold px-5 py-2.5 rounded-none shadow-lg transition cursor-pointer">
                  Done
                </button>
              )}
            </div>
          </div>
        </div>
      )}

      {/* Assign Recruiters Modal */}
      {assignJob && (() => {
        const totalRecPages = Math.max(1, Math.ceil(recruiterTotal / REC_PAGE_SIZE));
        const totalAssignedPages = Math.max(1, Math.ceil(assignedRecTotal / REC_PAGE_SIZE));
        return (
          <div className="fixed inset-0 z-50 flex items-center justify-center p-4">
            <div className="fixed inset-0 bg-slate-950/40 dark:bg-slate-950/80 backdrop-blur-sm" onClick={() => !recAssigning && setAssignJob(null)}></div>
            <div className="bg-white dark:bg-slate-900 border border-slate-200 dark:border-slate-800 w-full max-w-3xl rounded-none relative z-10 shadow-2xl animate-in fade-in zoom-in duration-200 text-slate-800 dark:text-slate-100 p-6 max-h-[90vh] overflow-y-auto custom-scrollbar">
              <div className="flex items-start gap-3 mb-4">
                <div className="w-10 h-10 rounded-none bg-indigo-50 dark:bg-indigo-950/40 text-indigo-600 dark:text-indigo-400 flex items-center justify-center shrink-0">
                  <i className="fa-solid fa-user-plus"></i>
                </div>
                <div className="min-w-0">
                  <h3 className="text-base font-bold text-slate-900 dark:text-white leading-tight">Assign Recruiters</h3>
                  <p className="text-xs text-slate-500 dark:text-slate-400 truncate">
                    <span className="font-extrabold text-[#405189] dark:text-indigo-400">JD #{assignJob.id}</span> — {assignJob.title}
                  </p>
                </div>
              </div>

              {recruiterLoading && recruiters.length === 0 && assignedRecs.length === 0 ? (
                <p className="text-xs text-slate-400 text-center py-10"><i className="fa-solid fa-spinner fa-spin mr-2" />Loading recruiters...</p>
              ) : (
                <>
                  {/* Tabs: Select Recruiters / Assigned Recruiters */}
                  <div className="flex items-center gap-2 mb-4 border-b border-slate-200 dark:border-slate-800 pb-3">
                    <button
                      type="button"
                      onClick={() => setRecTab('select')}
                      className={`flex items-center gap-2 px-4 py-2 rounded-none text-xs font-bold transition cursor-pointer ${recTab === 'select'
                        ? 'bg-indigo-600 text-white shadow-md shadow-indigo-600/15'
                        : 'bg-slate-50 hover:bg-slate-100 dark:bg-slate-950 dark:hover:bg-slate-800 text-slate-600 dark:text-slate-400'
                        }`}>
                      <i className="fa-solid fa-user-plus text-[10px]"></i> Select Recruiters
                    </button>
                    <button
                      type="button"
                      onClick={() => setRecTab('assigned')}
                      className={`flex items-center gap-2 px-4 py-2 rounded-none text-xs font-bold transition cursor-pointer ${recTab === 'assigned'
                        ? 'bg-indigo-600 text-white shadow-md shadow-indigo-600/15'
                        : 'bg-slate-50 hover:bg-slate-100 dark:bg-slate-950 dark:hover:bg-slate-800 text-slate-600 dark:text-slate-400'
                        }`}>
                      <i className="fa-solid fa-user-check text-[10px]"></i> Assigned Recruiters ({assignedRecTotal})
                    </button>
                  </div>

                  {recTab === 'select' && (
                    <>
                      {/* Search Filter */}
                      <div className="relative mb-3">
                        <i className="fa-solid fa-magnifying-glass absolute left-3 top-1/2 -translate-y-1/2 text-slate-400 text-xs" />
                        <input
                          value={recruiterSearch}
                          onChange={(e) => setRecruiterSearch(e.target.value)}
                          placeholder="Search recruiter by name or email..."
                          className="w-full bg-slate-50 dark:bg-slate-950 border border-slate-200 dark:border-slate-800 focus:border-indigo-500 rounded-none pl-9 pr-3 py-2 text-xs focus:outline-none transition text-slate-900 dark:text-white"
                        />
                      </div>

                      {/* Recruiter selection table */}
                      <div className="border border-slate-200 dark:border-slate-800 rounded-none overflow-hidden max-h-64 overflow-y-auto custom-scrollbar">
                        <table className="w-full text-left border-collapse">
                          <thead>
                            <tr className="bg-slate-50 dark:bg-slate-950 text-slate-500 dark:text-slate-400 uppercase tracking-wider text-[10px] font-bold border-b border-slate-200 dark:border-slate-800">
                              <th className="px-4 py-3 text-center w-12">Select</th>
                              <th className="px-4 py-3">Recruiter Name</th>
                              <th className="px-4 py-3">Phone</th>
                              <th className="px-4 py-3">Location</th>
                              <th className="px-4 py-3">Experience</th>
                              <th className="px-4 py-3">Status</th>
                            </tr>
                          </thead>
                          <tbody className="divide-y divide-slate-100 dark:divide-slate-800 text-xs">
                            {!recruiterLoading && recruiters.map((r) => {
                              const checked = selectedRecruiterIds.includes(r.id);
                              const toggle = () => {
                                setSelectedRecruiterIds((prev) =>
                                  checked ? prev.filter((id) => id !== r.id) : [...prev, r.id]
                                );
                              };
                              return (
                                <tr key={r.id} onClick={toggle}
                                  className={`cursor-pointer transition hover:bg-slate-50 dark:hover:bg-slate-800/40 ${checked ? 'bg-indigo-50/40 dark:bg-indigo-950/20' : ''}`}>
                                  <td className="px-4 py-3 text-center" onClick={(e) => e.stopPropagation()}>
                                    <input type="checkbox" checked={checked} onChange={toggle}
                                      className="w-4 h-4 rounded-none border-slate-300 dark:border-slate-600 accent-indigo-600 cursor-pointer" />
                                  </td>
                                  <td className="px-4 py-3">
                                    <div className="flex items-center gap-3">
                                      <span className="w-7 h-7 rounded-full bg-indigo-100 dark:bg-indigo-950/50 text-indigo-600 dark:text-indigo-400 flex items-center justify-center text-[10px] font-extrabold shrink-0 uppercase">
                                        {recruiterLabel(r).slice(0, 2)}
                                      </span>
                                      <div className="min-w-0">
                                        <span className="block font-semibold text-slate-800 dark:text-slate-200 truncate">{recruiterLabel(r)}</span>
                                        <span className="block text-[10px] text-slate-400 truncate">{r.email}</span>
                                      </div>
                                    </div>
                                  </td>
                                  <td className="px-4 py-3 text-slate-600 dark:text-slate-350 font-medium">
                                    {r.phone || <span className="text-slate-400 dark:text-slate-600 italic">Not provided</span>}
                                  </td>
                                  <td className="px-4 py-3 text-slate-600 dark:text-slate-350 font-medium">
                                    {r.location || <span className="text-slate-400 dark:text-slate-600 italic">Not provided</span>}
                                  </td>
                                  <td className="px-4 py-3 text-slate-600 dark:text-slate-350 font-medium">
                                    {typeof r.experience_years === 'number' && r.experience_years > 0 ? (
                                      `${r.experience_years} yr${r.experience_years === 1 ? '' : 's'}`
                                    ) : typeof r.experience_years === 'number' && r.experience_years === 0 ? (
                                      'Fresher'
                                    ) : (
                                      <span className="text-slate-400 dark:text-slate-600 italic">Not provided</span>
                                    )}
                                  </td>
                                  <td className="px-4 py-3">
                                    {checked ? (
                                      <span className="inline-flex items-center gap-1.5 px-2.5 py-0.5 rounded-full text-[10px] font-extrabold bg-indigo-50 dark:bg-indigo-950/40 text-indigo-700 dark:text-indigo-300 border border-indigo-200 dark:border-indigo-850">
                                        <span className="w-1.5 h-1.5 rounded-full bg-indigo-500 animate-pulse" /> Selected
                                      </span>
                                    ) : (
                                      <span className="text-slate-400 dark:text-slate-600 font-bold pl-4">—</span>
                                    )}
                                  </td>
                                </tr>
                              );
                            })}
                          </tbody>
                        </table>
                        {recruiterLoading ? (
                          <p className="text-xs text-slate-400 text-center py-8 bg-white dark:bg-slate-900">
                            <i className="fa-solid fa-spinner fa-spin mr-2" />Loading recruiters...
                          </p>
                        ) : recruiters.length === 0 && (
                          <p className="text-xs text-slate-400 text-center py-8 bg-white dark:bg-slate-900">
                            {recruiterSearch ? `No recruiter matches "${recruiterSearch}"` : 'No active recruiters found'}
                          </p>
                        )}
                      </div>

                      {/* Select Tab Server-side pagination */}
                      <div className="flex items-center justify-between gap-3 mt-2.5 flex-wrap">
                        <p className="text-[11px] text-slate-400 dark:text-slate-500">
                          {recruiterTotal > 0
                            ? `Showing ${(recruiterPage - 1) * REC_PAGE_SIZE + 1}–${Math.min(recruiterPage * REC_PAGE_SIZE, recruiterTotal)} of ${recruiterTotal} recruiter${recruiterTotal === 1 ? '' : 's'}`
                            : 'No recruiters'}
                          {' · '}{selectedRecruiterIds.length} selected
                        </p>
                        <div className="flex items-center gap-2">
                          <button
                            type="button"
                            onClick={() => loadRecruitersPage(recruiterPage - 1, recruiterSearch, assignJob.id)}
                            disabled={recruiterPage <= 1 || recruiterLoading}
                            className="px-2.5 py-1.5 border border-slate-200 dark:border-slate-800 rounded-none text-[11px] font-bold text-slate-600 dark:text-slate-300 hover:bg-slate-50 dark:hover:bg-slate-800 transition cursor-pointer disabled:opacity-40 disabled:cursor-not-allowed">
                            <i className="fa-solid fa-chevron-left text-[9px]"></i> Prev
                          </button>
                          <span className="text-[11px] font-bold text-slate-500 dark:text-slate-400 whitespace-nowrap">
                            Page {recruiterPage} of {totalRecPages}
                          </span>
                          <button
                            type="button"
                            onClick={() => loadRecruitersPage(recruiterPage + 1, recruiterSearch, assignJob.id)}
                            disabled={recruiterPage >= totalRecPages || recruiterLoading}
                            className="px-2.5 py-1.5 border border-slate-200 dark:border-slate-800 rounded-none text-[11px] font-bold text-slate-600 dark:text-slate-300 hover:bg-slate-50 dark:hover:bg-slate-800 transition cursor-pointer disabled:opacity-40 disabled:cursor-not-allowed">
                            Next <i className="fa-solid fa-chevron-right text-[9px]"></i>
                          </button>
                        </div>
                      </div>
                    </>
                  )}

                  {/* Assigned Recruiters Tab */}
                  {recTab === 'assigned' && (
                    <>
                      <div className="border border-slate-200 dark:border-slate-800 rounded-none overflow-hidden max-h-72 overflow-y-auto custom-scrollbar">
                        <table className="w-full text-left border-collapse">
                          <thead>
                            <tr className="bg-slate-50 dark:bg-slate-950 text-slate-500 dark:text-slate-400 uppercase tracking-wider text-[10px] font-bold border-b border-slate-200 dark:border-slate-800">
                              <th className="px-4 py-2.5 w-10">#</th>
                              <th className="px-4 py-2.5">Recruiter</th>
                              <th className="px-4 py-2.5">Phone</th>
                              <th className="px-4 py-2.5">Location</th>
                              <th className="px-4 py-2.5 text-right w-24">Actions</th>
                            </tr>
                          </thead>
                          <tbody className="divide-y divide-slate-100 dark:divide-slate-800 text-xs">
                            {!assignedRecLoading && assignedRecs.map((r: any, idx: number) => (
                              <tr key={r.id}>
                                <td className="px-4 py-2.5 text-slate-400">{(assignedRecPage - 1) * REC_PAGE_SIZE + idx + 1}</td>
                                <td className="px-4 py-2.5">
                                  <div className="flex items-center gap-3">
                                    <span className="w-7 h-7 rounded-full bg-indigo-100 dark:bg-indigo-950/50 text-indigo-600 dark:text-indigo-400 flex items-center justify-center text-[10px] font-extrabold shrink-0 uppercase">
                                      {recruiterLabel(r).slice(0, 2)}
                                    </span>
                                    <div className="min-w-0">
                                      <span className="block font-semibold text-slate-800 dark:text-slate-200 truncate">{recruiterLabel(r)}</span>
                                      <span className="block text-[10px] text-slate-400 truncate">{r.email}</span>
                                    </div>
                                  </div>
                                </td>
                                <td className="px-4 py-2.5 text-slate-650 dark:text-slate-350">{r.phone || '—'}</td>
                                <td className="px-4 py-2.5 text-slate-650 dark:text-slate-350">{r.location || '—'}</td>
                                <td className="px-4 py-2.5 text-right">
                                  <button
                                    type="button"
                                    onClick={() => handleUnassignRecruiter(r.id)}
                                    title="Unassign recruiter"
                                    disabled={recAssigning}
                                    className="inline-flex items-center justify-center w-8 h-8 hover:bg-rose-50 dark:hover:bg-rose-950/30 text-rose-550 hover:text-rose-600 dark:text-rose-400 dark:hover:text-rose-355 transition cursor-pointer disabled:opacity-50"
                                  >
                                    <i className="fa-solid fa-user-minus text-xs" />
                                  </button>
                                </td>
                              </tr>
                            ))}
                          </tbody>
                        </table>
                        {assignedRecLoading ? (
                          <p className="text-xs text-slate-400 text-center py-6 bg-white dark:bg-slate-900">
                            <i className="fa-solid fa-spinner fa-spin mr-2" />Loading assigned recruiters...
                          </p>
                        ) : assignedRecs.length === 0 && (
                          <p className="text-xs text-slate-400 text-center py-6 bg-white dark:bg-slate-900">No recruiters assigned to this JD yet.</p>
                        )}
                      </div>

                      {/* Assigned Tab Server-side pagination */}
                      <div className="flex items-center justify-between gap-3 mt-2.5 flex-wrap">
                        <p className="text-[11px] text-slate-400 dark:text-slate-500">
                          {assignedRecTotal > 0
                            ? `Showing ${(assignedRecPage - 1) * REC_PAGE_SIZE + 1}–${Math.min(assignedRecPage * REC_PAGE_SIZE, assignedRecTotal)} of ${assignedRecTotal} assigned recruiter${assignedRecTotal === 1 ? '' : 's'}`
                            : 'No assigned recruiters'}
                        </p>
                        <div className="flex items-center gap-2">
                          <button
                            type="button"
                            onClick={() => loadAssignedRecs(assignJob.id, assignedRecPage - 1)}
                            disabled={assignedRecPage <= 1 || assignedRecLoading}
                            className="px-2.5 py-1.5 border border-slate-200 dark:border-slate-800 rounded-none text-[11px] font-bold text-slate-600 dark:text-slate-300 hover:bg-slate-50 dark:hover:bg-slate-800 transition cursor-pointer disabled:opacity-40 disabled:cursor-not-allowed">
                            <i className="fa-solid fa-chevron-left text-[9px]"></i> Prev
                          </button>
                          <span className="text-[11px] font-bold text-slate-500 dark:text-slate-400 whitespace-nowrap">
                            Page {assignedRecPage} of {totalAssignedPages}
                          </span>
                          <button
                            type="button"
                            onClick={() => loadAssignedRecs(assignJob.id, assignedRecPage + 1)}
                            disabled={assignedRecPage >= totalAssignedPages || assignedRecLoading}
                            className="px-2.5 py-1.5 border border-slate-200 dark:border-slate-800 rounded-none text-[11px] font-bold text-slate-600 dark:text-slate-300 hover:bg-slate-50 dark:hover:bg-slate-800 transition cursor-pointer disabled:opacity-40 disabled:cursor-not-allowed">
                            Next <i className="fa-solid fa-chevron-right text-[9px]"></i>
                          </button>
                        </div>
                      </div>
                    </>
                  )}

                  <div className="flex justify-end gap-3 mt-6">
                    <button type="button" onClick={() => setAssignJob(null)} disabled={recAssigning}
                      className="px-4 py-2 text-sm text-slate-500 hover:text-slate-800 dark:text-slate-400 dark:hover:text-white transition cursor-pointer disabled:opacity-50">
                      Close
                    </button>
                    {recTab === 'select' && (
                      <button type="button" onClick={handleAssignRecruiters} disabled={recAssigning || selectedRecruiterIds.length === 0}
                        className="bg-indigo-600 hover:bg-indigo-500 text-white text-sm font-semibold px-5 py-2.5 rounded-none shadow-lg transition cursor-pointer disabled:opacity-40 disabled:cursor-not-allowed flex items-center gap-2">
                        {recAssigning && <i className="fa-solid fa-spinner fa-spin text-xs" />}
                        {recAssigning ? 'Assigning...' : `Assign ${selectedRecruiterIds.length || ''} Recruiter${selectedRecruiterIds.length === 1 ? '' : 's'}`}
                      </button>
                    )}
                  </div>
                </>
              )}
            </div>
          </div>
        );
      })()}

      {/* Assign Candidates Modal (multi-select) */}
      {assignCandJob && (() => {
        // Assigned to THIS JD: from the job-filtered list AND the all-JDs map (belt & braces)
        const assignedIds = assignedApps.map((a: any) => a.candidate);
        const isInThisJd = (cid: number) =>
          assignedIds.includes(cid) || (candJdMap[cid] ?? []).some((j) => j.id === assignCandJob.id);
        const candName = (c: any) => c.full_name || `${c.first_name || ''} ${c.last_name || ''}`.trim() || c.email;
        const totalCandPages = Math.max(1, Math.ceil(candTotal / CAND_PAGE_SIZE));
        const totalAssignedPages = Math.max(1, Math.ceil(assignedTotal / CAND_PAGE_SIZE));
        return (
          <div className="fixed inset-0 z-50 flex items-center justify-center p-4">
            <div className="fixed inset-0 bg-slate-950/40 dark:bg-slate-950/80 backdrop-blur-sm" onClick={() => !candAssigning && setAssignCandJob(null)}></div>
            <div className="bg-white dark:bg-slate-900 border border-slate-200 dark:border-slate-800 w-full max-w-3xl rounded-none relative z-10 shadow-2xl animate-in fade-in zoom-in duration-200 text-slate-800 dark:text-slate-100 p-6 max-h-[90vh] overflow-y-auto custom-scrollbar">
              <div className="flex items-start gap-3 mb-4">
                <div className="w-10 h-10 rounded-none bg-emerald-50 dark:bg-emerald-950/40 text-emerald-600 dark:text-emerald-400 flex items-center justify-center shrink-0">
                  <i className="fa-solid fa-user-check"></i>
                </div>
                <div className="min-w-0">
                  <h3 className="text-base font-bold text-slate-900 dark:text-white leading-tight">Assign Candidates</h3>
                  <p className="text-xs text-slate-500 dark:text-slate-400 truncate">
                    <span className="font-extrabold text-[#405189] dark:text-indigo-400">JD #{assignCandJob.id}</span> — {assignCandJob.title}
                  </p>
                </div>
              </div>

              {candModalLoading ? (
                <p className="text-xs text-slate-400 text-center py-10"><i className="fa-solid fa-spinner fa-spin mr-2" />Loading candidates...</p>
              ) : (
                <>
                  {/* Tabs: Select Candidates / Assigned Candidates */}
                  <div className="flex items-center gap-2 mb-4 border-b border-slate-200 dark:border-slate-800 pb-3">
                    <button
                      type="button"
                      onClick={() => setCandTab('select')}
                      className={`flex items-center gap-2 px-4 py-2 rounded-none text-xs font-bold transition cursor-pointer ${candTab === 'select'
                        ? 'bg-emerald-600 text-white shadow-md shadow-emerald-600/15'
                        : 'bg-slate-50 hover:bg-slate-100 dark:bg-slate-950 dark:hover:bg-slate-800 text-slate-600 dark:text-slate-400'
                        }`}>
                      <i className="fa-solid fa-user-plus text-[10px]"></i> Select Candidates
                    </button>
                    <button
                      type="button"
                      onClick={() => setCandTab('assigned')}
                      className={`flex items-center gap-2 px-4 py-2 rounded-none text-xs font-bold transition cursor-pointer ${candTab === 'assigned'
                        ? 'bg-emerald-600 text-white shadow-md shadow-emerald-600/15'
                        : 'bg-slate-50 hover:bg-slate-100 dark:bg-slate-950 dark:hover:bg-slate-800 text-slate-600 dark:text-slate-400'
                        }`}>
                      <i className="fa-solid fa-user-check text-[10px]"></i> Assigned Candidates ({assignedTotal})
                    </button>
                  </div>

                  {candTab === 'select' && (
                    <>
                      <span className="block text-xs text-slate-400 dark:text-slate-500 mb-2 font-medium">All Candidates</span>
                      <div className="relative mb-3">
                        <i className="fa-solid fa-magnifying-glass absolute left-3 top-1/2 -translate-y-1/2 text-slate-400 text-xs" />
                        <input
                          value={candSearch}
                          onChange={(e) => setCandSearch(e.target.value)}
                          placeholder="Search candidate by name, email or phone..."
                          className="w-full bg-slate-50 dark:bg-slate-950 border border-slate-200 dark:border-slate-800 focus:border-emerald-500 rounded-none pl-9 pr-3 py-2 text-xs focus:outline-none transition text-slate-900 dark:text-white"
                        />
                      </div>

                      <div className="border border-slate-200 dark:border-slate-800 rounded-none overflow-hidden max-h-64 overflow-y-auto custom-scrollbar">
                        <table className="w-full text-left border-collapse">
                          <thead>
                            <tr className="bg-slate-50 dark:bg-slate-950 text-slate-500 dark:text-slate-400 uppercase tracking-wider text-[10px] font-bold border-b border-slate-200 dark:border-slate-800">
                              <th className="px-4 py-3 text-center w-12">Select</th>
                              <th className="px-4 py-3">Candidate</th>
                              <th className="px-4 py-3">Phone</th>
                              <th className="px-4 py-3">City</th>
                              <th className="px-4 py-3">In JD?</th>
                              <th className="px-4 py-3">Status</th>
                            </tr>
                          </thead>
                          <tbody className="divide-y divide-slate-100 dark:divide-slate-800 text-xs">
                            {!candListLoading && candList.filter((c: any) => !isInThisJd(c.id)).map((c: any) => {
                              const already = false;
                              const checked = selectedCandIds.includes(c.id);
                              const toggle = () => {
                                if (already) return;
                                setSelectedCandIds((prev) =>
                                  checked ? prev.filter((id) => id !== c.id) : [...prev, c.id]
                                );
                              };
                              return (
                                <tr key={c.id} onClick={toggle}
                                  className={`transition ${already ? 'opacity-60 cursor-not-allowed' : 'cursor-pointer hover:bg-slate-50 dark:hover:bg-slate-800/40'} ${checked ? 'bg-emerald-50/40 dark:bg-emerald-950/20' : ''}`}>
                                  <td className="px-4 py-3 text-center" onClick={(e) => e.stopPropagation()}>
                                    <input type="checkbox" checked={checked || already} disabled={already} onChange={toggle}
                                      className="w-4 h-4 rounded-none border-slate-300 dark:border-slate-600 accent-emerald-600 cursor-pointer disabled:cursor-not-allowed" />
                                  </td>
                                  <td className="px-4 py-3">
                                    <div className="flex items-center gap-3">
                                      <span className="w-7 h-7 rounded-full bg-emerald-100 dark:bg-emerald-950/50 text-emerald-600 dark:text-emerald-400 flex items-center justify-center text-[10px] font-extrabold shrink-0 uppercase">
                                        {candName(c).slice(0, 2)}
                                      </span>
                                      <div className="min-w-0">
                                        <span className="block font-semibold text-slate-800 dark:text-slate-200 truncate">{candName(c)}</span>
                                        <span className="block text-[10px] text-slate-400 truncate">{c.email}</span>
                                      </div>
                                    </div>
                                  </td>
                                  <td className="px-4 py-3 text-slate-600 dark:text-slate-300 font-medium">{c.phone_number || '—'}</td>
                                  <td className="px-4 py-3 text-slate-600 dark:text-slate-300 font-medium">{c.city || '—'}</td>
                                  <td className="px-4 py-3">
                                    {(candJdMap[c.id] ?? []).length > 0 ? (
                                      <span className="relative group/jd inline-flex">
                                        <span className="inline-flex items-center gap-1 px-2 py-0.5 rounded-full text-[10px] font-extrabold bg-emerald-50 dark:bg-emerald-950/40 text-emerald-700 dark:text-emerald-300 border border-emerald-200 dark:border-emerald-800 cursor-default">
                                          <i className="fa-solid fa-circle-check text-[9px]" /> {candJdMap[c.id].length} JD{candJdMap[c.id].length === 1 ? '' : 's'}
                                        </span>
                                        <span className="pointer-events-none absolute left-0 top-full mt-1 z-30 hidden group-hover/jd:block bg-slate-900 dark:bg-slate-800 text-white rounded-none shadow-xl px-3 py-2 min-w-[150px] max-w-[240px]">
                                          <span className="block text-[9px] uppercase tracking-wider font-extrabold text-slate-400 mb-1">Assigned JDs</span>
                                          {candJdMap[c.id].slice(0, 5).map((j, idx) => (
                                            <span key={idx} className={`block text-[11px] font-semibold py-0.5 truncate ${j.id === assignCandJob.id ? 'text-emerald-300' : ''}`}>
                                              • #{j.id} {j.title}{j.id === assignCandJob.id ? ' (this JD)' : ''}
                                            </span>
                                          ))}
                                          {candJdMap[c.id].length > 5 && (
                                            <span className="block text-[10px] text-slate-400 pt-0.5">+{candJdMap[c.id].length - 5} more</span>
                                          )}
                                        </span>
                                      </span>
                                    ) : (
                                      <span className="text-slate-400 dark:text-slate-600 font-bold pl-2">—</span>
                                    )}
                                  </td>
                                  <td className="px-4 py-3">
                                    {already ? (
                                      <span className="inline-flex items-center gap-1.5 px-2.5 py-0.5 rounded-full text-[10px] font-extrabold bg-emerald-50 dark:bg-emerald-950/40 text-emerald-700 dark:text-emerald-300 border border-emerald-200 dark:border-emerald-800">
                                        <span className="w-1.5 h-1.5 rounded-full bg-emerald-500" /> Assigned
                                      </span>
                                    ) : checked ? (
                                      <span className="inline-flex items-center gap-1.5 px-2.5 py-0.5 rounded-full text-[10px] font-extrabold bg-indigo-50 dark:bg-indigo-950/40 text-indigo-700 dark:text-indigo-300 border border-indigo-200 dark:border-indigo-800">
                                        <span className="w-1.5 h-1.5 rounded-full bg-indigo-500 animate-pulse" /> Selected
                                      </span>
                                    ) : (
                                      <span className="text-slate-400 dark:text-slate-600 font-bold pl-4">—</span>
                                    )}
                                  </td>
                                </tr>
                              );
                            })}
                          </tbody>
                        </table>
                        {candListLoading ? (
                          <p className="text-xs text-slate-400 text-center py-8 bg-white dark:bg-slate-900">
                            <i className="fa-solid fa-spinner fa-spin mr-2" />Loading candidates...
                          </p>
                        ) : candList.length === 0 && (
                          <p className="text-xs text-slate-400 text-center py-8 bg-white dark:bg-slate-900">
                            {candSearch ? `No candidate matches "${candSearch}"` : 'No candidates found'}
                          </p>
                        )}
                      </div>

                      {/* Server-side pagination */}
                      <div className="flex items-center justify-between gap-3 mt-2.5 flex-wrap">
                        <p className="text-[11px] text-slate-400 dark:text-slate-500">
                          {candTotal > 0
                            ? `Showing ${(candPage - 1) * CAND_PAGE_SIZE + 1}–${Math.min(candPage * CAND_PAGE_SIZE, candTotal)} of ${candTotal} candidate${candTotal === 1 ? '' : 's'}`
                            : 'No candidates'}
                          {' · '}{selectedCandIds.length} selected
                        </p>
                        <div className="flex items-center gap-2">
                          <button
                            type="button"
                            onClick={() => loadCandidatesPage(candPage - 1, candSearch, assignCandJob.id)}
                            disabled={candPage <= 1 || candListLoading}
                            className="px-2.5 py-1.5 border border-slate-200 dark:border-slate-800 rounded-none text-[11px] font-bold text-slate-600 dark:text-slate-300 hover:bg-slate-50 dark:hover:bg-slate-800 transition cursor-pointer disabled:opacity-40 disabled:cursor-not-allowed">
                            <i className="fa-solid fa-chevron-left text-[9px]"></i> Prev
                          </button>
                          <span className="text-[11px] font-bold text-slate-500 dark:text-slate-400 whitespace-nowrap">
                            Page {candPage} of {totalCandPages}
                          </span>
                          <button
                            type="button"
                            onClick={() => loadCandidatesPage(candPage + 1, candSearch, assignCandJob.id)}
                            disabled={candPage >= totalCandPages || candListLoading}
                            className="px-2.5 py-1.5 border border-slate-200 dark:border-slate-800 rounded-none text-[11px] font-bold text-slate-600 dark:text-slate-300 hover:bg-slate-50 dark:hover:bg-slate-800 transition cursor-pointer disabled:opacity-40 disabled:cursor-not-allowed">
                            Next <i className="fa-solid fa-chevron-right text-[9px]"></i>
                          </button>
                        </div>
                      </div>
                    </>
                  )}

                  {/* Already assigned candidates for this JD */}
                  {candTab === 'assigned' && (
                    <>
                      <div className="border border-slate-200 dark:border-slate-800 rounded-none overflow-hidden max-h-72 overflow-y-auto custom-scrollbar">
                        <table className="w-full text-left border-collapse">
                          <thead>
                            <tr className="bg-slate-50 dark:bg-slate-950 text-slate-500 dark:text-slate-400 uppercase tracking-wider text-[10px] font-bold border-b border-slate-200 dark:border-slate-800">
                              <th className="px-4 py-2.5 w-10">#</th>
                              <th className="px-4 py-2.5">Candidate</th>
                              <th className="px-4 py-2.5">Stage</th>
                              <th className="px-4 py-2.5">Added By</th>
                              <th className="px-4 py-2.5">Added On</th>
                              <th className="px-4 py-2.5 text-right w-36">Actions</th>
                            </tr>
                          </thead>
                          <tbody className="divide-y divide-slate-100 dark:divide-slate-800 text-xs">
                            {!assignedLoading && assignedApps.map((a: any, i: number) => (
                              <tr key={a.id}>
                                <td className="px-4 py-2.5 text-slate-400">{(assignedPage - 1) * CAND_PAGE_SIZE + i + 1}</td>
                                <td className="px-4 py-2.5 font-semibold text-slate-800 dark:text-slate-200">{a.candidate_name || a.candidate}</td>
                                <td className="px-4 py-2.5">
                                  <span className="inline-flex items-center gap-1.5 px-2.5 py-0.5 rounded-full text-[10px] font-extrabold bg-indigo-50 dark:bg-indigo-950/40 text-indigo-700 dark:text-indigo-300 border border-indigo-200 dark:border-indigo-800">
                                    {a.stage_name || '—'}
                                  </span>
                                </td>
                                <td className="px-4 py-2.5 text-slate-500 dark:text-slate-400" title={a.added_by_email || ''}>
                                  {a.self_applied ? 'Candidate (portal)' : (a.added_by_name || '—')}
                                </td>
                                <td className="px-4 py-2.5 text-slate-500 dark:text-slate-400 whitespace-nowrap">{formatDate(a.created_at)}</td>
                                <td className="px-4 py-2.5 text-right">
                                  <div className="inline-flex items-center justify-end gap-1.5">
                                    <button
                                      type="button"
                                      onClick={() => router.push(`/candidates/${a.candidate}`)}
                                      title="Edit candidate profile"
                                      className="inline-flex items-center gap-1 px-2.5 py-1 bg-slate-50 hover:bg-slate-100 border border-slate-200 text-slate-600 dark:bg-slate-950 dark:hover:bg-slate-800 dark:border-slate-800 dark:text-slate-300 rounded-none text-[10px] font-bold transition cursor-pointer"
                                    >
                                      <i className="fa-solid fa-pen-to-square text-[9px]" /> Edit
                                    </button>
                                    <button
                                      type="button"
                                      onClick={() => handleRemoveCandidate(a.id, a.candidate)}
                                      title="Remove candidate from this JD"
                                      className="inline-flex items-center gap-1 px-2.5 py-1 bg-rose-50 dark:bg-rose-950/40 text-rose-600 hover:bg-rose-500 hover:text-white border border-rose-200 dark:border-rose-800/80 rounded-none text-[10px] font-bold transition cursor-pointer"
                                    >
                                      <i className="fa-solid fa-xmark text-[9px]" /> Remove
                                    </button>
                                  </div>
                                </td>
                              </tr>
                            ))}
                          </tbody>
                        </table>
                        {assignedLoading ? (
                          <p className="text-xs text-slate-400 text-center py-6 bg-white dark:bg-slate-900">
                            <i className="fa-solid fa-spinner fa-spin mr-2" />Loading assigned candidates...
                          </p>
                        ) : assignedApps.length === 0 && (
                          <p className="text-xs text-slate-400 text-center py-6 bg-white dark:bg-slate-900">No candidates assigned to this JD yet.</p>
                        )}
                      </div>

                      {/* Server-side pagination */}
                      <div className="flex items-center justify-between gap-3 mt-2.5 flex-wrap">
                        <p className="text-[11px] text-slate-400 dark:text-slate-500">
                          {assignedTotal > 0
                            ? `Showing ${(assignedPage - 1) * CAND_PAGE_SIZE + 1}–${Math.min(assignedPage * CAND_PAGE_SIZE, assignedTotal)} of ${assignedTotal} assigned candidate${assignedTotal === 1 ? '' : 's'}`
                            : 'No assigned candidates'}
                        </p>
                        <div className="flex items-center gap-2">
                          <button
                            type="button"
                            onClick={() => loadAssignedApps(assignCandJob.id, assignedPage - 1)}
                            disabled={assignedPage <= 1 || assignedLoading}
                            className="px-2.5 py-1.5 border border-slate-200 dark:border-slate-800 rounded-none text-[11px] font-bold text-slate-600 dark:text-slate-300 hover:bg-slate-50 dark:hover:bg-slate-800 transition cursor-pointer disabled:opacity-40 disabled:cursor-not-allowed">
                            <i className="fa-solid fa-chevron-left text-[9px]"></i> Prev
                          </button>
                          <span className="text-[11px] font-bold text-slate-500 dark:text-slate-400 whitespace-nowrap">
                            Page {assignedPage} of {totalAssignedPages}
                          </span>
                          <button
                            type="button"
                            onClick={() => loadAssignedApps(assignCandJob.id, assignedPage + 1)}
                            disabled={assignedPage >= totalAssignedPages || assignedLoading}
                            className="px-2.5 py-1.5 border border-slate-200 dark:border-slate-800 rounded-none text-[11px] font-bold text-slate-600 dark:text-slate-300 hover:bg-slate-50 dark:hover:bg-slate-800 transition cursor-pointer disabled:opacity-40 disabled:cursor-not-allowed">
                            Next <i className="fa-solid fa-chevron-right text-[9px]"></i>
                          </button>
                        </div>
                      </div>
                    </>
                  )}

                  <div className="flex justify-end gap-3 mt-6">
                    <button type="button" onClick={() => setAssignCandJob(null)} disabled={candAssigning}
                      className="px-4 py-2 text-sm text-slate-500 hover:text-slate-800 dark:text-slate-400 dark:hover:text-white transition cursor-pointer disabled:opacity-50">
                      Close
                    </button>
                    {candTab === 'select' && (
                      <button type="button" onClick={handleAssignCandidates} disabled={candAssigning || selectedCandIds.length === 0}
                        className="bg-emerald-600 hover:bg-emerald-500 text-white text-sm font-semibold px-5 py-2.5 rounded-none shadow-lg transition cursor-pointer disabled:opacity-40 disabled:cursor-not-allowed flex items-center gap-2">
                        {candAssigning && <i className="fa-solid fa-spinner fa-spin text-xs" />}
                        {candAssigning ? 'Assigning...' : `Assign ${selectedCandIds.length || ''} Candidate${selectedCandIds.length === 1 ? '' : 's'}`}
                      </button>
                    )}
                  </div>
                </>
              )}
            </div>
          </div>
        );
      })()}

      {/* JD Review modal — approve, or reject with a written reason. Also shows
          the outcome once decided (approved note / rejection reason paragraph). */}
      {reviewJob && (() => {
        const status = reviewJob.approval_status || 'DRAFT';
        const pending = status === 'PENDING_APPROVAL';

        const getAttachmentUrl = (rawUrl?: string | null): string => {
          if (!rawUrl) return '';
          if (rawUrl.startsWith('http://') || rawUrl.startsWith('https://') || rawUrl.startsWith('blob:')) return rawUrl;
          const backendBase = (process.env.NEXT_PUBLIC_API_URL || 'http://localhost:8000/api/v1').replace('/api/v1', '');
          if (rawUrl.startsWith('/')) {
            return `${backendBase}${rawUrl}`;
          }
          return `${backendBase}/media/${rawUrl}`;
        };

        return (
          <div className="fixed inset-0 z-[100] flex items-start justify-center bg-slate-950/60 backdrop-blur-sm p-4 overflow-y-auto" onClick={() => !reviewBusy && setReviewJob(null)}>
            <div onClick={(e) => e.stopPropagation()} className="bg-white dark:bg-slate-900 border border-slate-200 dark:border-slate-800 rounded-none shadow-2xl w-full max-w-4xl my-8">
              {/* Header */}
              <div className="flex items-center justify-between gap-3 px-5 py-4 bg-[#405189]">
                <div className="min-w-0">
                  <p className="text-[10px] font-extrabold uppercase tracking-widest text-indigo-200">Review Job Description</p>
                  <h2 className="text-base font-bold text-white truncate">{reviewJob.title}</h2>
                </div>
                <button onClick={() => setReviewJob(null)} disabled={reviewBusy} className="w-8 h-8 flex items-center justify-center text-white/80 hover:text-white hover:bg-white/10 transition cursor-pointer disabled:opacity-50">
                  <i className="fa-solid fa-xmark" />
                </button>
              </div>

              {/* Two Tabs: Approval Status & View JD */}
              <div className="flex border-b border-slate-100 dark:border-slate-800 px-5 bg-slate-50/60 dark:bg-slate-950/30">
                <button
                  type="button"
                  onClick={() => setReviewTab('approval')}
                  className={`flex items-center gap-2 py-3 px-4 text-xs font-bold border-b-2 transition cursor-pointer ${
                    reviewTab === 'approval'
                      ? 'border-[#405189] text-[#405189] dark:border-indigo-400 dark:text-indigo-400 bg-white dark:bg-slate-900'
                      : 'border-transparent text-slate-500 hover:text-slate-700 dark:text-slate-400 dark:hover:text-slate-200'
                  }`}
                >
                  <i className="fa-solid fa-clipboard-check text-sm" />
                  Approval Status
                </button>
                <button
                  type="button"
                  onClick={() => setReviewTab('view_jd')}
                  className={`flex items-center gap-2 py-3 px-4 text-xs font-bold border-b-2 transition cursor-pointer ${
                    reviewTab === 'view_jd'
                      ? 'border-[#405189] text-[#405189] dark:border-indigo-400 dark:text-indigo-400 bg-white dark:bg-slate-900'
                      : 'border-transparent text-slate-500 hover:text-slate-700 dark:text-slate-400 dark:hover:text-slate-200'
                  }`}
                >
                  <i className="fa-solid fa-file-lines text-sm" />
                  View JD
                </button>
              </div>

              <div className="p-5 space-y-4 max-h-[70vh] overflow-y-auto custom-scrollbar">
                {reviewTab === 'approval' ? (
                  <>
                    {/* Current approval state */}
                    <div className="flex items-center gap-2 text-xs">
                      <span className="font-semibold text-slate-500 dark:text-slate-400">Approval status:</span>
                      <span className="inline-flex px-2 py-0.5 rounded-full text-[10px] font-extrabold bg-slate-100 text-slate-700 dark:bg-slate-800 dark:text-slate-300">{status}</span>
                    </div>

                    {/* JD details being reviewed */}
                    <div className="border border-slate-200 dark:border-slate-800 rounded-none">
                      <div className="px-3 py-2 border-b border-slate-100 dark:border-slate-800 bg-slate-50 dark:bg-slate-950/40">
                        <p className="text-[10px] font-extrabold uppercase tracking-wide text-slate-500 dark:text-slate-400">Job Description Details</p>
                      </div>
                      <div className="p-3 grid grid-cols-2 gap-x-4 gap-y-2.5">
                        {([
                          ['Created By', reviewJob.created_by_name || reviewJob.created_by_email],
                          ['Client', reviewJob.client_name],
                          ['Department', reviewJob.department],
                          ['Location', reviewJob.location],
                          ['Experience', reviewJob.experience_band],
                          ['CTC Band', reviewJob.ctc_band],
                          ['Notice Period', reviewJob.notice_period],
                          ['Shift', reviewJob.shift],
                          ['Positions', reviewJob.num_positions != null ? String(reviewJob.num_positions) : ''],
                          ['Priority', reviewJob.priority],
                        ] as [string, string | null | undefined][])
                          .filter(([, v]) => v)
                          .map(([label, v]) => (
                            <div key={label}>
                              <p className="text-[9px] font-extrabold uppercase tracking-wide text-slate-400 dark:text-slate-500">{label}</p>
                              <p className="text-xs font-semibold text-slate-700 dark:text-slate-200">{v}</p>
                            </div>
                          ))}
                      </div>
                      {(reviewJob.must_have_skills || reviewJob.good_to_have_skills || reviewJob.qualifications) && (
                        <div className="px-3 pb-3 space-y-2">
                          {reviewJob.must_have_skills && (
                            <div><p className="text-[9px] font-extrabold uppercase tracking-wide text-slate-400 dark:text-slate-500">Skills</p>
                              <p className="text-xs text-slate-700 dark:text-slate-300">{cleanHtmlText(reviewJob.must_have_skills)}</p></div>
                          )}
                          {reviewJob.good_to_have_skills && (
                            <div><p className="text-[9px] font-extrabold uppercase tracking-wide text-slate-400 dark:text-slate-500">Good-to-have Skills</p>
                              <p className="text-xs text-slate-700 dark:text-slate-300">{cleanHtmlText(reviewJob.good_to_have_skills)}</p></div>
                          )}
                          {reviewJob.qualifications && (
                            <div><p className="text-[9px] font-extrabold uppercase tracking-wide text-slate-400 dark:text-slate-500">Qualifications</p>
                              <p className="text-xs text-slate-700 dark:text-slate-300">{cleanHtmlText(reviewJob.qualifications)}</p></div>
                          )}
                        </div>
                      )}
                      {reviewJob.work_details && (
                        <div className="px-3 pb-3">
                          <p className="text-[9px] font-extrabold uppercase tracking-wide text-slate-400 dark:text-slate-500 mb-1">Description</p>
                          <p className="text-xs text-slate-600 dark:text-slate-300 whitespace-pre-line max-h-32 overflow-y-auto custom-scrollbar">
                            {cleanHtmlText(reviewJob.work_details)}
                          </p>
                        </div>
                      )}
                    </div>

                    {status === 'APPROVED' && (
                      <div className="border-l-2 border-emerald-400 dark:border-emerald-700 bg-emerald-50/60 dark:bg-emerald-950/20 px-3 py-2.5">
                        <p className="text-xs font-bold text-emerald-700 dark:text-emerald-300">
                          <i className="fa-solid fa-circle-check mr-1.5" />
                          {reviewJob.approved_by_name
                            ? `This Job Description has already been approved by ${reviewJob.approved_by_name}`
                            : 'This Job Description has already been approved'}
                          {reviewJob.approved_at ? ` on ${new Date(reviewJob.approved_at).toLocaleString('en-IN', { day: 'numeric', month: 'short', year: 'numeric', hour: 'numeric', minute: '2-digit' })}` : ''}.
                        </p>
                        <p className="text-[11px] text-emerald-600/80 dark:text-emerald-400/80 mt-1">The approval is complete — no further action is required.</p>
                      </div>
                    )}

                    {status === 'REJECTED' && (
                      <div className="border-l-2 border-rose-400 dark:border-rose-700 bg-rose-50/60 dark:bg-rose-950/20 px-3 py-2.5">
                        <p className="text-[10px] font-extrabold uppercase tracking-wide text-rose-500 mb-1">Why it was rejected</p>
                        <p className="text-xs font-medium text-slate-700 dark:text-slate-300 whitespace-pre-line">{reviewJob.rejection_reason || '—'}</p>
                      </div>
                    )}

                    {pending && (
                      <>
                        <p className="text-xs text-slate-600 dark:text-slate-300">This JD is awaiting your decision. Approve it, or write a reason below and reject.</p>
                        <div>
                          <label className="block text-[10px] font-extrabold uppercase tracking-wide text-slate-500 dark:text-slate-400 mb-1">Rejection reason <span className="text-rose-500">(required to reject)</span></label>
                          <textarea
                            value={reviewReason}
                            onChange={(e) => setReviewReason(e.target.value)}
                            rows={4}
                            placeholder="Explain what needs to change…"
                            className="w-full bg-slate-50 dark:bg-slate-950 border border-slate-200 dark:border-slate-800 focus:border-indigo-500 rounded-none px-3 py-2 text-sm text-slate-900 dark:text-white focus:outline-none transition resize-none"
                          />
                        </div>
                      </>
                    )}
                  </>
                ) : (
                  /* Tab 2: View JD Document (View Only) */
                  (() => {
                    const attachmentUrl = getAttachmentUrl(reviewJob.attachment);
                    const fileName = reviewJob.attachment ? reviewJob.attachment.split('/').pop() || 'JD Document' : '';
                    const isPdf = /\.pdf(\?|$)/i.test(attachmentUrl);
                    const isWord = /\.(docx?|rtf)(\?|$)/i.test(attachmentUrl);

                    if (!reviewJob.attachment || !attachmentUrl) {
                      return (
                        <div className="py-12 px-4 flex flex-col items-center justify-center text-center bg-slate-50 dark:bg-slate-950 border border-slate-200 dark:border-slate-800 rounded-none">
                          <div className="w-12 h-12 rounded-full bg-slate-100 dark:bg-slate-800 flex items-center justify-center text-slate-400 mb-3">
                            <i className="fa-solid fa-file-circle-xmark text-xl" />
                          </div>
                          <h4 className="text-sm font-bold text-slate-700 dark:text-slate-200">No Document Uploaded</h4>
                          <p className="text-xs text-slate-500 dark:text-slate-400 mt-1 max-w-sm">
                            No document file was uploaded when creating this Job Description.
                          </p>
                        </div>
                      );
                    }

                    return (
                      <div className="flex flex-col h-[520px] border border-slate-200 dark:border-slate-800 rounded-none bg-slate-50 dark:bg-slate-950 overflow-hidden">
                        <div className="flex items-center justify-between px-4 py-2 bg-slate-100 dark:bg-slate-900 border-b border-slate-200 dark:border-slate-800 text-xs font-semibold text-slate-600 dark:text-slate-300">
                          <span className="flex items-center gap-2 truncate">
                            <i className={`fa-solid ${isPdf ? 'fa-file-pdf text-rose-500' : isWord ? 'fa-file-word text-blue-500' : 'fa-file-lines text-slate-500'}`} />
                            <span className="truncate">{fileName}</span>
                          </span>
                          <span className="text-[10px] uppercase font-bold tracking-wider px-2 py-0.5 rounded bg-slate-200 dark:bg-slate-800 text-slate-600 dark:text-slate-400 shrink-0">
                            View Only
                          </span>
                        </div>
                        <div className="flex-1 w-full h-full relative">
                          <DocViewer
                            url={attachmentUrl}
                            fileName={fileName}
                            fallbackText={cleanHtmlText(reviewJob.work_details)}
                          />
                        </div>
                      </div>
                    );
                  })()
                )}
              </div>

              <div className="flex justify-end gap-2 px-5 py-4 border-t border-slate-100 dark:border-slate-800">
                <button onClick={() => setReviewJob(null)} disabled={reviewBusy} className="px-4 py-2 rounded-none text-sm font-semibold text-slate-500 hover:text-slate-900 dark:text-slate-400 dark:hover:text-white transition cursor-pointer disabled:opacity-50">Close</button>
                {pending && (
                  <>
                    <button onClick={doReject} disabled={reviewBusy} className="inline-flex items-center gap-2 px-4 py-2 rounded-none text-sm font-medium bg-red-600 hover:bg-red-700 text-white transition cursor-pointer disabled:opacity-60">
                      <i className={`fa-solid ${isRejecting ? 'fa-spinner fa-spin' : 'fa-xmark'}`} /> {isRejecting ? 'Rejecting…' : 'Reject'}
                    </button>
                    <button onClick={doApprove} disabled={reviewBusy} className="inline-flex items-center gap-2 px-4 py-2 rounded-none text-sm font-medium bg-emerald-600 hover:bg-emerald-700 text-white transition cursor-pointer disabled:opacity-60">
                      <i className={`fa-solid ${isApproving ? 'fa-spinner fa-spin' : 'fa-check'}`} /> {isApproving ? 'Approving…' : 'Approve'}
                    </button>
                  </>
                )}
              </div>
            </div>
          </div>
        );
      })()}

      {/* Send-for-approval confirmation popup */}
      {submitJob && (
        <div className="fixed inset-0 z-[110] flex items-center justify-center bg-slate-950/60 backdrop-blur-sm p-4" onClick={() => !workflowBusy && setSubmitJob(null)}>
          <div onClick={(e) => e.stopPropagation()} className="bg-white dark:bg-slate-900 border border-slate-200 dark:border-slate-800 rounded-none shadow-2xl w-full max-w-5xl flex flex-col h-[90vh] max-h-[90vh]">
            {/* Header */}
            <div className="flex items-start gap-4 px-6 pt-6 pb-4 border-b border-slate-100 dark:border-slate-800">
              <div className="w-11 h-11 rounded-none bg-yellow-50 dark:bg-yellow-950/40 flex items-center justify-center shrink-0">
                <i className="fa-solid fa-paper-plane text-yellow-600 dark:text-yellow-400" />
              </div>
              <div className="min-w-0">
                <h3 className="text-base font-bold text-slate-900 dark:text-white">Send Job Description for Approval</h3>
                <p className="text-xs text-slate-500 dark:text-slate-400 mt-1">
                  Review the JD, select approver(s), and view previous approval requests.
                </p>
              </div>
            </div>

            {/* Tabs */}
            <div className="flex border-b border-slate-100 dark:border-slate-800 px-6">
              {([
                ['details', 'Job Details', 'fa-file-lines'],
                ['approvers', 'Select Approver(s)', 'fa-user-check'],
                ['history', 'Send History', 'fa-clock-rotate-left'],
              ] as ['details' | 'approvers' | 'history', string, string][]).map(([key, label, icon]) => (
                <button
                  key={key}
                  type="button"
                  onClick={() => setSubmitTab(key)}
                  className={`flex items-center gap-1.5 px-3 py-2.5 text-xs font-bold border-b-2 -mb-px transition cursor-pointer ${submitTab === key
                    ? 'border-[#405189] text-[#405189] dark:border-indigo-400 dark:text-indigo-400'
                    : 'border-transparent text-slate-500 dark:text-slate-400 hover:text-slate-800 dark:hover:text-slate-200'
                    }`}
                >
                  <i className={`fa-solid ${icon} text-[11px]`} />
                  {label}
                  {key === 'history' && approvalHistory.length > 0 && (
                    <span className="ml-1 inline-flex items-center justify-center min-w-[16px] h-4 px-1 rounded-full bg-slate-200 dark:bg-slate-700 text-[9px] font-black text-slate-600 dark:text-slate-300">
                      {approvalHistory.length}
                    </span>
                  )}
                </button>
              ))}
            </div>

            <div className="px-6 py-4 overflow-y-auto custom-scrollbar flex-1 min-h-0 space-y-4">
              {/* Tab 1 — Job Details (read-only). Comprehensive two-column layout
                  of the JD's existing data; missing values fall back to "N/A". */}
              {submitTab === 'details' && (() => {
                const na = (v?: string | number | null) => {
                  const s = v == null ? '' : String(v).trim();
                  return s ? s : 'N/A';
                };
                const fmtDate = (d?: string | null) =>
                  d ? new Date(d).toLocaleDateString('en-IN', { day: 'numeric', month: 'short', year: 'numeric' }) : 'N/A';
                // Hiring Manager(s) the JD was sent to (from the already-loaded Send
                // History) — used by the Approval Information card's "Assigned To".
                const hmNames = Array.from(new Set(approvalHistory.map((h) => h.approver_name).filter(Boolean)));
                const statusLabel = (() => {
                  const s = (submitJob.jd_status || '').toLowerCase();
                  if (s === 'published') return 'Published';
                  if (s === 'pending_approval') return 'Pending Approval';
                  if (s === 'closed') return 'Closed';
                  if (s === 'draft') return 'Draft';
                  return submitJob.status || 'N/A';
                })();
                const jobCode = submitJob.jd_code || `JD-${String(submitJob.id).padStart(4, '0')}`;

                const fmtDateTime = (d?: string | null) =>
                  d ? new Date(d).toLocaleString('en-GB', {
                    day: '2-digit', month: '2-digit', year: 'numeric',
                    hour: '2-digit', minute: '2-digit', hour12: true,
                  }) : 'N/A';

                // Approval state (derived from existing JD fields — no new APIs).
                const appStatus = (submitJob.approval_status || '').toUpperCase();
                const isApproved = appStatus === 'APPROVED' || submitJob.status === 'Published';
                const isRejected = appStatus === 'REJECTED';
                const isPending = appStatus === 'PENDING_APPROVAL';
                const showApprovalCard = isApproved || isRejected || isPending;

                // Assigned To / By come from the already-loaded Send History rows.
                const assignedByNames = Array.from(new Set(approvalHistory.map((h) => h.sent_by).filter(Boolean))) as string[];
                const assignedBy = assignedByNames.length ? assignedByNames.join(', ') : 'N/A';
                const rejectedRow = approvalHistory.find((h) => h.status === 'REJECTED');
                const rejectedBy = rejectedRow?.approver_name || 'N/A';
                const rejectedAt = submitJob.rejected_at || rejectedRow?.acted_at || null;

                const labelCls = 'text-[10px] uppercase tracking-wider font-extrabold text-slate-400 dark:text-slate-500 mb-0.5';
                const valueCls = 'text-xs font-semibold text-slate-800 dark:text-slate-200';
                const Cell = ({ label, value, badge }: { label: string; value: ReactNode; badge?: string }) => (
                  <div>
                    <p className={labelCls}>{label}</p>
                    {badge ? (
                      <span className={`inline-flex px-2 py-0.5 rounded-full text-[10px] font-bold ${badge}`}>{value}</span>
                    ) : (
                      <p className={valueCls}>{value}</p>
                    )}
                  </div>
                );

                // [label, value, fullWidth?]
                const fields: [string, string, boolean?][] = [
                  ['Job ID / Code', jobCode],
                  ['Job Title', na(submitJob.title)],
                  ['Client', submitJob.client_name || 'Internal'],
                  ['Department', na(submitJob.department)],
                  ['Location', na(submitJob.location)],
                  // The JD model has no dedicated work-mode field; `shift` is the
                  // nearest existing value for Work Mode.
                  ['Work Mode', na(submitJob.shift)],
                  ['Number of Openings', submitJob.num_positions != null ? String(submitJob.num_positions) : 'N/A'],
                  ['Priority', na(submitJob.priority)],
                  ['Current Status', statusLabel],
                  ['Created By', na(submitJob.created_by_name || submitJob.created_by_email)],
                  ['Created Date', fmtDate(submitJob.created_at)],
                  ['Updated Date', fmtDate(submitJob.updated_at)],
                ];
                return (
                  <div className="space-y-4">
                    {/* 📋 Job Information card — keeps every existing Job Detail field. */}
                    <div className="border border-slate-200 dark:border-slate-800 rounded-none">
                      <div className="px-4 py-2.5 border-b border-slate-100 dark:border-slate-800 bg-slate-50 dark:bg-slate-950/40 flex items-center gap-2">
                        <p className="text-[11px] font-extrabold uppercase tracking-wide text-slate-500 dark:text-slate-400">Job Information</p>
                      </div>
                      <div className="p-4 grid grid-cols-1 sm:grid-cols-2 gap-x-6 gap-y-3.5">
                        {fields.map(([label, value, full]) => (
                          <div key={label} className={full ? 'sm:col-span-2' : ''}>
                            <p className={labelCls}>{label}</p>
                            <p
                              className={`${valueCls} ${full ? 'break-words whitespace-pre-line' : 'truncate'}`}
                              title={value}
                            >
                              {value}
                            </p>
                          </div>
                        ))}
                      </div>
                    </div>

                    {/* 👥 Approval Information card — shown once the JD enters the
                        approval workflow (pending / approved / rejected). Uses only
                        existing project data. */}
                    {showApprovalCard && (
                      <div className="border border-slate-200 dark:border-slate-800 rounded-none">
                        <div className="px-4 py-2.5 border-b border-slate-100 dark:border-slate-800 bg-slate-50 dark:bg-slate-950/40 flex items-center gap-2">
                          <p className="text-[11px] font-extrabold uppercase tracking-wide text-slate-500 dark:text-slate-400">Approval Information</p>
                        </div>
                        <div className="p-4 grid grid-cols-1 sm:grid-cols-2 gap-x-6 gap-y-3.5">
                          {/* Assigned Hiring Manager(s) — shown as a chip list. */}
                          <div className="sm:col-span-2">
                            <p className={labelCls}>Assigned To (Hiring Manager{hmNames.length > 1 ? 's' : ''})</p>
                            {hmNames.length ? (
                              <div className="flex flex-wrap gap-1.5 mt-1">
                                {hmNames.map((n) => (
                                  <span key={n} className="inline-flex items-center gap-1 px-2 py-0.5 rounded-full text-[10px] font-bold bg-indigo-50 text-indigo-700 dark:bg-indigo-950/40 dark:text-indigo-300">
                                    <i className="fa-solid fa-user text-[8px]" />{n}
                                  </span>
                                ))}
                              </div>
                            ) : (
                              <p className={valueCls}>{na(submitJob.current_approver_name)}</p>
                            )}
                          </div>

                          <Cell label="Assigned By" value={assignedBy} />

                          {isApproved && (
                            <>
                              <Cell label="Approved By" value={na(submitJob.approved_by_name)} />
                              <Cell label="Approved Date & Time" value={fmtDateTime(submitJob.approved_at)} />
                              <Cell label="Approval Status" value="Approved" badge="bg-emerald-50 text-emerald-700 dark:bg-emerald-950/40 dark:text-emerald-300" />
                              <Cell label="Current Workflow Status" value={statusLabel} />
                            </>
                          )}

                          {isPending && (
                            <>
                              <Cell label="Approval Status" value="Pending Approval" badge="bg-amber-50 text-amber-700 dark:bg-amber-950/40 dark:text-amber-300" />
                              <Cell label="Current Workflow Status" value={statusLabel} />
                            </>
                          )}

                          {isRejected && (
                            <>
                              <Cell label="Rejected By" value={rejectedBy} />
                              <Cell label="Rejected Date & Time" value={fmtDateTime(rejectedAt)} />
                              <Cell label="Rejection Status" value="Rejected" badge="bg-rose-50 text-rose-700 dark:bg-rose-950/40 dark:text-rose-300" />
                              <Cell label="Current Workflow Status" value={statusLabel} />
                              {submitJob.rejection_reason && (
                                <div className="sm:col-span-2">
                                  <p className={labelCls}>Rejection Reason</p>
                                  <p className={`${valueCls} break-words whitespace-pre-line`}>{submitJob.rejection_reason}</p>
                                </div>
                              )}
                            </>
                          )}
                        </div>
                      </div>
                    )}
                  </div>
                );
              })()}

              {/* Tab 2 — Select Approver(s) — scrollable, searchable multi-select data table */}
              {submitTab === 'approvers' && (() => {
                // "HIRING_MANAGER" → "Hiring Manager" — no raw underscored role codes in the UI.
                const formatRole = (role: string) =>
                  role
                    .toLowerCase()
                    .split('_')
                    .filter(Boolean)
                    .map((w) => w.charAt(0).toUpperCase() + w.slice(1))
                    .join(' ') || '—';
                // Hiring managers this JD has already been sent to (from the
                // Send History tab's data for the same JD) — drives the
                // "Approval Status" column below.
                const sentApproverIds = new Set(
                  approvalHistory.map((h: any) => h.approver_id).filter(Boolean)
                );
                const q = approverSearch.trim().toLowerCase();
                const filtered = q
                  ? approverList.filter((a) =>
                    a.name.toLowerCase().includes(q) ||
                    a.email.toLowerCase().includes(q) ||
                    a.department.toLowerCase().includes(q) ||
                    a.employee_id.toLowerCase().includes(q))
                  : approverList;
                const allFilteredSelected = filtered.length > 0 && filtered.every((a) => selectedApproverIds.includes(a.id));
                const someFilteredSelected = filtered.some((a) => selectedApproverIds.includes(a.id));
                const toggleRow = (id: number) =>
                  setSelectedApproverIds((prev) => (prev.includes(id) ? prev.filter((x) => x !== id) : [...prev, id]));
                const toggleAll = () =>
                  setSelectedApproverIds((prev) => {
                    const ids = new Set(filtered.map((a) => a.id));
                    if (allFilteredSelected) return prev.filter((id) => !ids.has(id));
                    const merged = new Set(prev);
                    filtered.forEach((a) => merged.add(a.id));
                    return Array.from(merged);
                  });
                return (
                  <div className="flex flex-col h-full min-h-0">
                    <p className="text-[10px] uppercase tracking-wider font-extrabold text-slate-400 mb-2">Select Approver(s)</p>

                    {/* Search box — filters by name / email / department / employee ID */}
                    <div className="relative mb-3">
                      <i className="fa-solid fa-magnifying-glass absolute left-3 top-1/2 -translate-y-1/2 text-slate-400 text-xs" />
                      <input
                        value={approverSearch}
                        onChange={(e) => setApproverSearch(e.target.value)}
                        placeholder="Search by name, email, department or employee ID…"
                        className="w-full bg-slate-50 dark:bg-slate-950 border border-slate-200 dark:border-slate-800 focus:border-[#405189] rounded-none pl-9 pr-3 py-2 text-xs focus:outline-none transition text-slate-900 dark:text-white"
                      />
                    </div>

                    {approversLoading ? (
                      <div className="h-40 bg-slate-100 dark:bg-slate-800 rounded-none animate-pulse" />
                    ) : approverList.length === 0 ? (
                      <p className="text-[11px] text-amber-600 dark:text-amber-400 mt-1.5">
                        <i className="fa-solid fa-circle-info mr-1" />
                        No eligible approvers found — a Hiring Manager, or any user granted the JD-approval permission.
                      </p>
                    ) : (
                      <>
                        {/* Scrollable table with a fixed (sticky) header — fills the popup's available height */}
                        <div className="border border-slate-200 dark:border-slate-800 rounded-none flex-1 min-h-0 max-h-[60vh] overflow-auto custom-scrollbar">
                          <table className="w-full min-w-[560px] text-left border-collapse text-xs">
                            <thead className="sticky top-0 z-10">
                              <tr className="bg-slate-50 dark:bg-slate-950 text-slate-500 dark:text-slate-400 uppercase tracking-wider text-[10px] font-extrabold border-b border-slate-200 dark:border-slate-800">
                                <th className="px-3 py-2.5 text-center w-10">
                                  <input
                                    type="checkbox"
                                    aria-label="Select all hiring managers"
                                    checked={allFilteredSelected}
                                    ref={(el) => { if (el) el.indeterminate = someFilteredSelected && !allFilteredSelected; }}
                                    onChange={toggleAll}
                                    className="w-4 h-4 rounded-none border-slate-300 dark:border-slate-600 accent-[#405189] cursor-pointer"
                                  />
                                </th>
                                <th className="px-3 py-2.5 whitespace-nowrap">Employee ID</th>
                                <th className="px-3 py-2.5 whitespace-nowrap">Hiring Manager</th>
                                <th className="px-3 py-2.5 whitespace-nowrap">Role</th>
                                <th className="px-3 py-2.5 whitespace-nowrap">Email</th>
                                <th className="px-3 py-2.5 whitespace-nowrap">Approval Status</th>
                              </tr>
                            </thead>
                            <tbody className="divide-y divide-slate-100 dark:divide-slate-800">
                              {filtered.length === 0 ? (
                                <tr>
                                  <td colSpan={6} className="px-3 py-8 text-center text-slate-400 dark:text-slate-500">
                                    No hiring managers match “{approverSearch}”.
                                  </td>
                                </tr>
                              ) : filtered.map((a) => {
                                const checked = selectedApproverIds.includes(a.id);
                                const mailSent = sentApproverIds.has(a.id);
                                return (
                                  <tr
                                    key={a.id}
                                    onClick={() => toggleRow(a.id)}
                                    className={`cursor-pointer transition ${checked ? 'bg-indigo-50/60 dark:bg-indigo-950/30' : 'hover:bg-slate-50 dark:hover:bg-slate-800/40'}`}
                                  >
                                    <td className="px-3 py-2.5 text-center" onClick={(e) => e.stopPropagation()}>
                                      <input
                                        type="checkbox"
                                        aria-label={`Select ${a.name}`}
                                        checked={checked}
                                        onChange={() => toggleRow(a.id)}
                                        className="w-4 h-4 rounded-none border-slate-300 dark:border-slate-600 accent-[#405189] cursor-pointer"
                                      />
                                    </td>
                                    <td className="px-3 py-2.5 text-slate-600 dark:text-slate-300 whitespace-nowrap">{a.employee_id || '—'}</td>
                                    <td className="px-3 py-2.5 font-semibold text-slate-800 dark:text-slate-200 whitespace-nowrap">{a.name}</td>
                                    <td className="px-3 py-2.5 text-slate-600 dark:text-slate-300 whitespace-nowrap">{formatRole(a.role)}</td>
                                    <td className="px-3 py-2.5 text-slate-500 dark:text-slate-400 whitespace-nowrap">{a.email || '—'}</td>
                                    <td className="px-3 py-2.5 whitespace-nowrap">
                                      <span className={`inline-flex px-2 py-0.5 rounded-full text-[10px] font-bold ${mailSent
                                        ? 'bg-emerald-50 text-emerald-700 dark:bg-emerald-950/40 dark:text-emerald-300'
                                        : 'bg-slate-100 text-slate-500 dark:bg-slate-800 dark:text-slate-400'}`}>
                                        {mailSent ? 'Mail Sent' : 'Not Sent'}
                                      </span>
                                    </td>
                                  </tr>
                                );
                              })}
                            </tbody>
                          </table>
                        </div>

                        {/* Selection summary */}
                        <p className="text-[11px] text-slate-400 mt-2">
                          {selectedApproverIds.length > 0
                            ? `${selectedApproverIds.length} Hiring Manager${selectedApproverIds.length > 1 ? 's' : ''} selected — each will receive the approval request.`
                            : 'No Hiring Managers selected yet.'}
                        </p>
                      </>
                    )}
                  </div>
                );
              })()}

              {/* Tab 3 — Send History */}
              {submitTab === 'history' && (
                <div>
                  {historyLoading ? (
                    <div className="h-24 bg-slate-100 dark:bg-slate-800 rounded-none animate-pulse" />
                  ) : approvalHistory.length === 0 ? (
                    <p className="text-xs text-slate-400 dark:text-slate-500 text-center py-8">
                      No approval requests have been sent for this JD yet.
                    </p>
                  ) : (
                    <div className="overflow-x-auto border border-slate-200 dark:border-slate-800 rounded-none">
                      <table className="w-full min-w-[640px] text-xs">
                        <thead className="bg-slate-50 dark:bg-slate-950 border-b border-slate-200 dark:border-slate-800">
                          <tr>
                            {['Hiring Manager', 'Email', 'Sent By', 'Sent Date & Time', 'Status', 'Action Date & Time'].map((h) => (
                              <th key={h} className="text-left px-3 py-2 text-[10px] font-extrabold uppercase tracking-wider text-slate-400 whitespace-nowrap">{h}</th>
                            ))}
                          </tr>
                        </thead>
                        <tbody className="divide-y divide-slate-100 dark:divide-slate-800">
                          {(() => {
                            // Whichever row actually has status APPROVED is the Hiring
                            // Manager who approved the JD (first-approver-wins) — every
                            // other request for the same JD was auto-closed, so name them
                            // instead of a generic "Already Approved".
                            const approvedByName = approvalHistory.find((h: any) => h.status === 'APPROVED')?.approver_name || '';
                            return approvalHistory.map((h) => {
                              const badge = h.status === 'APPROVED'
                                ? 'bg-emerald-50 text-emerald-700 dark:bg-emerald-950/40 dark:text-emerald-300'
                                : h.status === 'REJECTED'
                                  ? 'bg-rose-50 text-rose-700 dark:bg-rose-950/40 dark:text-rose-300'
                                  : h.status === 'AUTO_CLOSED'
                                    ? 'bg-slate-100 text-slate-600 dark:bg-slate-800 dark:text-slate-300'
                                    : 'bg-amber-50 text-amber-700 dark:bg-amber-950/40 dark:text-amber-300';
                              const statusLabel = h.status === 'PENDING' ? 'Pending'
                                : h.status === 'APPROVED' ? 'Approved'
                                  : h.status === 'REJECTED' ? 'Rejected'
                                    : h.status === 'AUTO_CLOSED'
                                      ? (approvedByName ? `Approved by ${approvedByName}` : 'Already Approved')
                                      : h.status;
                              return (
                                <tr key={h.id} className="hover:bg-slate-50 dark:hover:bg-slate-800/40">
                                  <td className="px-3 py-2 font-semibold text-slate-800 dark:text-slate-200 whitespace-nowrap">{h.approver_name || '—'}</td>
                                  <td className="px-3 py-2 text-slate-500 dark:text-slate-400 whitespace-nowrap">{h.approver_email || '—'}</td>
                                  <td className="px-3 py-2 text-slate-500 dark:text-slate-400 whitespace-nowrap">{h.sent_by || '—'}</td>
                                  <td className="px-3 py-2 text-slate-500 dark:text-slate-400 whitespace-nowrap">{h.sent_at ? new Date(h.sent_at).toLocaleString() : '—'}</td>
                                  <td className="px-3 py-2">
                                    <span className={`inline-flex px-2 py-0.5 rounded-full text-[10px] font-bold ${badge}`}>
                                      {statusLabel}
                                    </span>
                                  </td>
                                  <td className="px-3 py-2 text-slate-500 dark:text-slate-400 whitespace-nowrap">{h.acted_at ? new Date(h.acted_at).toLocaleString() : '—'}</td>
                                </tr>
                              );
                            });
                          })()}
                        </tbody>
                      </table>
                    </div>
                  )}
                </div>
              )}
            </div>

            {/* Footer */}
            <div className="flex justify-end gap-3 px-6 py-4 border-t border-slate-100 dark:border-slate-800">
              <button onClick={() => setSubmitJob(null)} disabled={workflowBusy} className="px-4 py-2 rounded-none text-sm font-semibold text-slate-500 hover:text-slate-900 dark:text-slate-400 dark:hover:text-white transition cursor-pointer disabled:opacity-50">Cancel</button>
              <button
                onClick={doSubmitApproval}
                disabled={workflowBusy || selectedApproverIds.length === 0}
                title={selectedApproverIds.length === 0 ? 'Select at least one Hiring Manager' : undefined}
                className="inline-flex items-center gap-2 bg-[#405189] hover:bg-[#364574] text-white px-5 py-2 rounded-none text-sm font-medium transition cursor-pointer disabled:opacity-50 disabled:cursor-not-allowed"
              >
                <i className={`fa-solid ${workflowBusy ? 'fa-spinner fa-spin' : 'fa-paper-plane'}`} /> Send
              </button>
            </div>
          </div>
        </div>
      )}

      {/* ---- Candidate: JD Preview & Apply Confirmation Modal ---- */}
      {applyPreviewJob && (
        <div
          className="fixed inset-0 z-[120] flex items-center justify-center bg-slate-950/70 backdrop-blur-sm p-4"
          onClick={() => !applyingJobId && setApplyPreviewJob(null)}
        >
          <div
            onClick={(e) => e.stopPropagation()}
            className="bg-white dark:bg-slate-900 border border-slate-200 dark:border-slate-800 rounded-none shadow-2xl w-full max-w-2xl max-h-[90vh] flex flex-col"
          >
            {/* Header */}
            <div className="flex items-start justify-between gap-4 px-6 py-4 border-b border-slate-100 dark:border-slate-800">
              <div>
                <h2 className="text-base font-black text-slate-800 dark:text-white">{applyPreviewJob.title}</h2>
                <p className="text-xs text-slate-500 dark:text-slate-400 mt-0.5">
                  {applyPreviewJob.client_name || 'Indovision'}{applyPreviewJob.department ? ` · ${applyPreviewJob.department}` : ''}
                </p>
              </div>
              <button
                onClick={() => setApplyPreviewJob(null)}
                className="text-slate-400 hover:text-slate-700 dark:hover:text-white transition text-lg mt-0.5 shrink-0"
              >
                <i className="fa-solid fa-xmark" />
              </button>
            </div>

            {/* Body — scrollable */}
            <div className="flex-1 overflow-y-auto px-6 py-4 space-y-4">
              {/* Quick facts */}
              <div className="grid grid-cols-2 sm:grid-cols-3 gap-3">
                {[
                  { icon: 'fa-location-dot', label: 'Location', val: applyPreviewJob.location },
                  { icon: 'fa-briefcase', label: 'Experience', val: applyPreviewJob.experience_band },
                  { icon: 'fa-indian-rupee-sign', label: 'CTC', val: applyPreviewJob.ctc_band },
                  { icon: 'fa-clock', label: 'Shift', val: applyPreviewJob.shift },
                  { icon: 'fa-hourglass-half', label: 'Notice Period', val: applyPreviewJob.notice_period },
                  { icon: 'fa-calendar-days', label: 'Working Days', val: applyPreviewJob.working_days },
                ].filter((f) => f.val).map((f) => (
                  <div key={f.label} className="bg-slate-50 dark:bg-slate-800/60 border border-slate-100 dark:border-slate-700 px-3 py-2">
                    <p className="text-[10px] font-bold uppercase tracking-wide text-slate-400 dark:text-slate-500 mb-0.5">{f.label}</p>
                    <p className="text-xs font-semibold text-slate-700 dark:text-slate-200 flex items-center gap-1.5">
                      <i className={`fa-solid ${f.icon} text-[#405189] dark:text-indigo-400`} />{f.val}
                    </p>
                  </div>
                ))}
              </div>

              {/* Must-have skills */}
              {applyPreviewJob.must_have_skills && (
                <div>
                  <p className="text-[11px] font-extrabold uppercase tracking-wide text-slate-500 dark:text-slate-400 mb-1.5">Required Skills</p>
                  <div className="flex flex-wrap gap-1.5">
                    {applyPreviewJob.must_have_skills.split(',').filter((s) => s.trim()).map((s, i) => (
                      <span key={i} className="text-[11px] px-2 py-0.5 bg-[#405189]/10 text-[#405189] dark:bg-indigo-950/40 dark:text-indigo-300 border border-[#405189]/20">{s.trim()}</span>
                    ))}
                  </div>
                </div>
              )}

              {/* Work details */}
              {applyPreviewJob.work_details && (
                <div>
                  <p className="text-[11px] font-extrabold uppercase tracking-wide text-slate-500 dark:text-slate-400 mb-1.5">Job Description</p>
                  <div
                    className="prose prose-sm max-w-none text-slate-700 dark:text-slate-300 text-xs leading-relaxed border border-slate-100 dark:border-slate-700 bg-slate-50 dark:bg-slate-800/40 p-3"
                    dangerouslySetInnerHTML={{ __html: applyPreviewJob.work_details }}
                  />
                </div>
              )}
            </div>

            {/* Footer — confirm apply */}
            <div className="px-6 py-4 border-t border-slate-100 dark:border-slate-800 bg-slate-50 dark:bg-slate-900 flex items-center justify-between gap-4">
              <p className="text-xs text-slate-500 dark:text-slate-400">
                <i className="fa-solid fa-circle-info mr-1 text-[#405189]" />
                By applying you confirm your profile is accurate and up-to-date.
              </p>
              <div className="flex items-center gap-2 shrink-0">
                <button
                  onClick={() => setApplyPreviewJob(null)}
                  disabled={applyingJobId === applyPreviewJob.id}
                  className="px-4 py-2 text-xs font-bold text-slate-500 hover:text-slate-800 dark:text-slate-400 dark:hover:text-white transition disabled:opacity-50"
                >
                  Cancel
                </button>
                <button
                  onClick={async () => {
                    const job = applyPreviewJob;
                    await handleCandidateApply(job.id);
                    setApplyPreviewJob(null);
                  }}
                  disabled={applyingJobId === applyPreviewJob.id}
                  className="inline-flex items-center gap-1.5 bg-[#405189] hover:bg-[#334267] text-white text-xs font-bold px-5 py-2 rounded-none shadow transition disabled:opacity-50 cursor-pointer"
                >
                  {applyingJobId === applyPreviewJob.id ? (
                    <><i className="fa-solid fa-spinner fa-spin" /> Applying…</>
                  ) : (
                    <><i className="fa-solid fa-paper-plane" /> Confirm &amp; Apply</>
                  )}
                </button>
              </div>
            </div>
          </div>
        </div>
      )}

      {/* View Attached Document Modal Popup (View Only) */}
      {previewDocModal && (
        <div className="fixed inset-0 z-[120] flex items-center justify-center bg-slate-950/60 backdrop-blur-sm p-4 animate-in fade-in duration-200" onClick={() => setPreviewDocModal(null)}>
          <div onClick={(e) => e.stopPropagation()} className="bg-white dark:bg-slate-900 border border-slate-200 dark:border-slate-800 rounded-none shadow-2xl w-full max-w-4xl h-[85vh] flex flex-col">
            <div className="flex items-center justify-between gap-3 px-5 py-3.5 bg-[#405189] text-white">
              <div className="min-w-0 flex items-center gap-2">
                <i className="fa-solid fa-file-lines text-indigo-200" />
                <h3 className="text-sm font-bold truncate">{previewDocModal.title}</h3>
              </div>
              <button
                type="button"
                onClick={() => setPreviewDocModal(null)}
                className="w-7 h-7 flex items-center justify-center text-white/80 hover:text-white hover:bg-white/10 transition cursor-pointer"
              >
                <i className="fa-solid fa-xmark text-sm" />
              </button>
            </div>

            <div className="flex-1 min-h-0 relative bg-slate-50 dark:bg-slate-950">
              <DocViewer
                url={getAttachmentUrl(previewDocModal.url)}
                fileName={previewDocModal.title}
                fallbackText={workDetails ? workDetails.replace(/<[^>]*>/g, ' ').replace(/\s+/g, ' ').trim() : ''}
              />
            </div>
          </div>
        </div>
      )}

      {/* Hunar AI Agent Modal Popup */}
      <AgentModal
        job={agentJob}
        isOpen={agentModalOpen}
        onClose={() => setAgentModalOpen(false)}
        onAgentLinked={(jobId, agentId) => {
          setJobs((prev) =>
            prev.map((j) => (j.id === jobId ? { ...j, hunar_agent_id: agentId } : j))
          );
        }}
      />
    </>

  );
}
