'use client';

import { useCallback, useEffect, useMemo, useState } from 'react';
import { useParams, useRouter } from 'next/navigation';
import Cookies from 'js-cookie';
import { toast } from 'react-toastify';
import { showSuccess, showError } from '@/lib/confirm';
import { api } from '@/lib/api';
import { fetchEmailTemplates, fillTemplate, type EmailTemplate } from '@/lib/notificationTemplates';
import type { User } from '@/types';
import { useAuth } from '@/components/auth-context';
import AIScreeningCards, { type CardFilter } from '@/components/ai-screening/AIScreeningCards';
import AIScreeningTable from '@/components/ai-screening/AIScreeningTable';
import AddCandidateModal from '@/components/ai-screening/AddCandidateModal';
import TranscriptModal from '@/components/ai-screening/TranscriptModal';
import type { ScreeningDashboard, ScreeningStatusData } from '@/components/ai-screening/types';

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

function canScreen(user: User): boolean {
  const role = (user.role ?? '').toUpperCase();
  return role === 'ADMIN' || role === 'RECRUITER' || role.includes('MANAGER');
}

export default function AIScreeningPage() {
  const router = useRouter();
  const params = useParams<{ id: string }>();
  const jobId = params.id;

  const { user } = useAuth();
  const [jobTitle, setJobTitle] = useState('');
  const [dashboard, setDashboard] = useState<ScreeningDashboard | null>(null);
  const [status, setStatus] = useState<ScreeningStatusData | null>(null);
  const [selected, setSelected] = useState<Set<number>>(new Set());
  const [starting, setStarting] = useState(false);
  const [busyCallId, setBusyCallId] = useState<number | null>(null);
  const [transcriptCall, setTranscriptCall] = useState<number | null>(null);
  const [addOpen, setAddOpen] = useState(false);
  const [cardFilter, setCardFilter] = useState<CardFilter>('all');
  const [error, setError] = useState<string | null>(null);
  const [clientName, setClientName] = useState('');
  const [notifying, setNotifying] = useState(false);
  const [notifType, setNotifType] = useState('Send Email');
  const [templates, setTemplates] = useState<EmailTemplate[]>([]);
  const [templateId, setTemplateId] = useState<number | ''>('');

  useEffect(() => {
    fetchEmailTemplates().then((rows) => {
      setTemplates(rows);
      if (rows.length) setTemplateId(rows[0].id);
    });
  }, []);
  const [notifProgress, setNotifProgress] = useState<{
    action: string; total: number; processed: number;
    sent: number; failed: number; perChannel: Record<string, number>;
  } | null>(null);

  // ── auth guard ──
  useEffect(() => {
    if (!user) return;
    if (!canScreen(user)) {
      toast.error('You do not have permission to run AI screening.');
      router.push('/dashboard');
    }
  }, [user, router]);

  useEffect(() => {
    (api.get(`/jobs/${jobId}/`) as Promise<{ data: { title?: string; client_name?: string } }>)
      .then((res) => {
        setJobTitle(res.data?.title || `JD #${jobId}`);
        setClientName(res.data?.client_name || '');
      })
      .catch(() => setJobTitle(`JD #${jobId}`));
  }, [jobId]);

  // ── data loading + live polling while calls run ──
  const refresh = useCallback(() => {
    Promise.all([
      api.get(`/ai-calls/?job=${jobId}`),
      api.get(`/ai-calls/dashboard/?job=${jobId}`),
    ])
      .then(([st, dash]) => {
        setStatus((st as { data: ScreeningStatusData }).data);
        setDashboard((dash as { data: ScreeningDashboard }).data);
        setError(null);
      })
      .catch((e: unknown) => setError(e instanceof Error ? e.message : 'Failed to load screening data'));
  }, [jobId]);

  useEffect(() => {
    if (!user) return;
    refresh();
    const timer = setInterval(refresh, POLL_MS);
    return () => clearInterval(timer);
  }, [user, refresh]);

  // ── selection ──
  const toggle = (id: number) =>
    setSelected((prev) => {
      const next = new Set(prev);
      if (next.has(id)) next.delete(id); else next.add(id);
      return next;
    });
  const toggleAll = () => {
    // Operates on the currently visible (card-filtered) rows
    const ids = visibleRows.map((r) => r.candidate_id);
    setSelected((prev) => {
      const allOn = ids.length > 0 && ids.every((id) => prev.has(id));
      const next = new Set(prev);
      ids.forEach((id) => (allOn ? next.delete(id) : next.add(id)));
      return next;
    });
  };

  // ── actions ──
  const startScreening = async () => {
    const ids = selectedVisibleCandidates.map((c) => c.candidate_id);
    if (!ids.length) return;
    setStarting(true);
    try {
      const res = (await api.post('/ai-calls/start/', {
        job: Number(jobId),
        candidate_ids: ids,
      })) as { message?: string; data?: { errors?: string[] } };
      toast.success(res.message || 'AI screening started');
      (res.data?.errors ?? []).forEach((e) => toast.warn(e));
      setSelected(new Set());
      refresh();
    } catch (e) {
      toast.error(e instanceof Error ? e.message : 'Could not start screening');
    } finally {
      setStarting(false);
    }
  };

  const retry = async (callId: number) => {
    setBusyCallId(callId);
    try {
      await api.post(`/ai-calls/${callId}/retry/`);
      toast.success('Call requeued');
      refresh();
    } catch (e) {
      toast.error(e instanceof Error ? e.message : 'Retry failed');
    } finally {
      setBusyCallId(null);
    }
  };

  const downloadReport = async (callId: number, name: string) => {
    setBusyCallId(callId);
    try {
      const res = await fetch(`${API_BASE_URL}/ai-calls/${callId}/report/`, {
        headers: { Authorization: `Bearer ${Cookies.get('access_token')}` },
      });
      if (!res.ok) throw new Error(`Report failed (status ${res.status})`);
      const blob = await res.blob();
      const url = URL.createObjectURL(blob);
      const a = document.createElement('a');
      a.href = url;
      a.download = `${name.replace(/\s+/g, '_')}_ai_screening.pdf`;
      a.click();
      URL.revokeObjectURL(url);
    } catch (e) {
      toast.error(e instanceof Error ? e.message : 'Report download failed');
    } finally {
      setBusyCallId(null);
    }
  };

  const rows = status?.rows ?? [];
  const running = status?.running ?? 0;
  const completedCalls = rows.filter((r) => r.call && r.call.status === 'COMPLETED').length;
  const totalCalls = rows.filter((r) => r.call).length;

  // Card-click filter over the table (client-side — the rows are already loaded)
  const CARD_FILTER_LABELS: Record<CardFilter, string> = {
    all: '', running: 'AI calls running', completed: 'completed calls',
    qualified: 'qualified candidates', rejected: 'rejected candidates', scored: 'scored candidates',
  };
  const visibleRows = useMemo(() => {
    switch (cardFilter) {
      case 'running':
        return rows.filter((r) => r.call && ['QUEUED', 'DIALING', 'IN_PROGRESS'].includes(r.call.status));
      case 'completed':
        return rows.filter((r) => r.call?.status === 'COMPLETED');
      case 'qualified':
        return rows.filter((r) => r.call?.recommendation === 'QUALIFIED');
      case 'rejected':
        return rows.filter((r) => r.call?.recommendation === 'NOT_QUALIFIED');
      case 'scored':
        return [...rows.filter((r) => r.call?.score != null)]
          .sort((a, b) => (b.call!.score ?? 0) - (a.call!.score ?? 0));
      default:
        return rows;
    }
  }, [rows, cardFilter]);

  const selectedVisibleCandidates = useMemo(() => {
    return visibleRows.filter((r) => selected.has(r.candidate_id));
  }, [visibleRows, selected]);

  const sendNotificationsDirectly = async (action: string) => {
    if (selectedVisibleCandidates.length === 0) {
      toast.warning('Select at least one candidate first.');
      return;
    }
    const recipients = selectedVisibleCandidates;

    // Use the selected Notification Template if one is chosen; else fall back.
    const tpl = templates.find((t) => t.id === templateId);
    const defaultSubject = tpl?.subject || 'Regarding your application for {job}';
    const defaultMessage = tpl?.body || 'Hi {name},\n\nWe would like to update you about your application for {job} at {company}.\n\nRegards,\nTA-ATS Team';

    const CHANNELS_FOR: Record<string, string[]> = {
      'Send WhatsApp, SMS & Mail': ['EMAIL', 'WHATSAPP', 'SMS'],
      'Send WhatsApp, SMS & Email': ['EMAIL', 'WHATSAPP', 'SMS'],
      'Send WhatsApp': ['WHATSAPP'],
      'Send Mail': ['EMAIL'],
      'Send Email': ['EMAIL'],
      'Send SMS': ['SMS'],
    };

    const channels = CHANNELS_FOR[action] || ['EMAIL'];

    const items = recipients.map((c) => {
      const name = c.name || 'Candidate';
      const company = clientName || 'Indovision';
      const vars = { name, job_title: jobTitle, company, location: (c as any).location || '', mail_link: '' };
      const pSubject = fillTemplate(defaultSubject, vars);
      const pMessage = fillTemplate(defaultMessage, vars);
      return {
        id: c.candidate_id,
        subject: pSubject,
        message: pMessage,
      };
    });

    setNotifying(true);
    let sent = 0, failed = 0;
    const perChannel: Record<string, number> = {};
    setNotifProgress({
      action, total: items.length, processed: 0, sent: 0, failed: 0, perChannel: {},
    });

    try {
      for (let i = 0; i < items.length; i++) {
        const item = items[i];
        setNotifProgress({
          action, total: items.length, processed: i, sent, failed, perChannel: { ...perChannel },
        });
        try {
          const res = (await api.post('/candidates/notify-bulk/', {
            channels,
            items: [item],
            job_id: Number(jobId),
          })) as any;
          const d = res?.data || {};
          sent += d.sent ?? 0;
          failed += d.failed ?? 0;
          (d.summary ?? []).forEach((row: any) => {
            (row.results ?? []).forEach((rr: any) => {
              if (rr.status === 'SENT') perChannel[rr.channel] = (perChannel[rr.channel] || 0) + 1;
            });
          });
        } catch {
          failed += 1;
        }
        setNotifProgress({
          action, total: items.length, processed: i + 1, sent, failed, perChannel: { ...perChannel },
        });
      }
      if (failed === 0) {
        showSuccess('Selected notifications have been sent successfully.', 'Notifications Sent');
      } else {
        showError('One or more notifications could not be sent.', 'Notification Failed');
      }
      setSelected(new Set());
    } catch (err: any) {
      toast.error(err?.message || 'Send failed.');
    } finally {
      setNotifying(false);
    }
  };

  const actionBtn =
    'flex items-center gap-2 px-3.5 py-2 rounded-none text-xs font-semibold bg-white dark:bg-slate-900 border border-slate-200 dark:border-slate-800 text-slate-700 dark:text-slate-300 hover:border-indigo-500/60 hover:text-indigo-600 dark:hover:text-indigo-400 transition disabled:opacity-50 disabled:cursor-not-allowed cursor-pointer';

  if (!user) return null;

  return (
    <>

      <main className="flex-1 p-4 sm:p-8 overflow-y-auto w-full">
        <div className="max-w-7xl w-full mx-auto space-y-5">
          {/* Title + toolbar */}
          <div className="flex flex-col lg:flex-row lg:items-center lg:justify-between gap-3">
            <div>
              <button
                onClick={() => router.push(`/jobs/${jobId}`)}
                className="text-[11px] font-bold text-indigo-600 dark:text-indigo-400 hover:underline cursor-pointer mb-1"
              >
                <i className="fa-solid fa-arrow-left mr-1.5" />
                Back to JD
              </button>
              <h1 className="text-xl font-bold text-slate-900 dark:text-white">AI Screening · {jobTitle}</h1>
              <p className="text-sm text-slate-500 dark:text-slate-400 mt-0.5">
                Import candidates and let the AI agent run outbound screening calls.
              </p>
            </div>
             <div className="flex items-center gap-2 flex-wrap">
              <button onClick={() => setAddOpen(true)} className={actionBtn}>
                <i className="fa-solid fa-user-plus text-sm" />
                Add Candidate
              </button>
              <div className="flex items-center gap-1.5">
                <select
                  value={templateId}
                  onChange={(e) => setTemplateId(e.target.value ? Number(e.target.value) : '')}
                  disabled={notifying}
                  title="Notification template"
                  className="bg-white dark:bg-slate-900 border border-slate-200 dark:border-slate-800 text-slate-800 dark:text-slate-200 font-semibold text-xs px-2.5 py-2 rounded-none focus:outline-none focus:border-indigo-500 transition disabled:opacity-50 cursor-pointer h-[34px] max-w-[180px]"
                >
                  {templates.length === 0 && <option value="">Default template</option>}
                  {templates.map((t) => (
                    <option key={t.id} value={t.id}>{t.name}</option>
                  ))}
                </select>
                <select
                  value={notifType}
                  onChange={(e) => setNotifType(e.target.value)}
                  disabled={notifying}
                  className="bg-white dark:bg-slate-900 border border-slate-200 dark:border-slate-800 text-slate-800 dark:text-slate-200 font-semibold text-xs px-2.5 py-2 rounded-none focus:outline-none focus:border-indigo-500 transition disabled:opacity-50 cursor-pointer h-[34px]"
                >
                  <option value="Send Email">Send Email</option>
                  <option value="Send SMS">Send SMS</option>
                  <option value="Send WhatsApp">Send WhatsApp</option>
                  <option value="Send WhatsApp, SMS & Email">Send WhatsApp, SMS & Email</option>
                </select>
                <button
                  onClick={() => sendNotificationsDirectly(notifType)}
                  disabled={selectedVisibleCandidates.length === 0 || notifying}
                  className="flex items-center gap-2 px-4 py-2 rounded-none text-xs font-bold bg-[#6366f1] hover:bg-[#4f46e5] disabled:opacity-40 disabled:cursor-not-allowed text-white transition cursor-pointer h-[34px]"
                >
                  <i className={`fa-solid ${notifying ? 'fa-spinner fa-spin' : 'fa-paper-plane'} text-sm`} />
                  Send{selectedVisibleCandidates.length > 0 ? ` (${selectedVisibleCandidates.length})` : ''}
                </button>
              </div>
              <button
                onClick={startScreening}
                disabled={selectedVisibleCandidates.length === 0 || starting}
                className="flex items-center gap-2 px-4 py-2 rounded-none text-xs font-bold bg-[#405189] hover:bg-[#364574] text-white transition disabled:opacity-50 disabled:cursor-not-allowed cursor-pointer"
              >
                <i className={`fa-solid ${starting ? 'fa-spinner fa-spin' : 'fa-headset'} text-sm`} />
                Start AI Screening{selectedVisibleCandidates.length > 0 ? ` (${selectedVisibleCandidates.length} Selected)` : ''}
              </button>
            </div>
          </div>

          {/* Live sending progress loader */}
          {notifProgress && (() => {
            const p = notifProgress;
            const pct = p.total ? Math.round((p.processed / p.total) * 100) : 0;
            const isRunning = notifying;
            return (
              <div className="bg-white dark:bg-slate-900 border border-indigo-200 dark:border-indigo-900/50 rounded-none p-4 shadow-sm">
                <div className="flex items-center justify-between mb-1.5">
                  <p className="text-xs font-extrabold text-indigo-700 dark:text-indigo-300">
                    {isRunning
                      ? <><i className="fa-solid fa-spinner fa-spin mr-1.5" />Sending Notifications… ({p.action})</>
                      : <><i className="fa-solid fa-circle-check mr-1.5" />Completed ({p.action})</>}
                  </p>
                  <span className="text-xs font-extrabold text-indigo-700 dark:text-indigo-300">{pct}%</span>
                </div>
                <div className="h-2 w-full bg-slate-100 dark:bg-slate-800 overflow-hidden mb-2">
                  <div className="h-full bg-indigo-500 transition-all duration-300" style={{ width: `${pct}%` }} />
                </div>
                <div className="flex flex-wrap items-center justify-between text-xs font-bold gap-2">
                  <span className="text-slate-600 dark:text-slate-300">
                    {p.processed} / {p.total} candidate{p.total === 1 ? '' : 's'} processed
                    <span className="font-normal text-slate-400"> · {p.sent} sent</span>
                  </span>
                  <div className="flex gap-4 text-[11px]">
                    <span className="text-emerald-600 dark:text-emerald-400">Success: {p.sent}</span>
                    <span className="text-rose-600 dark:text-rose-400">Failed: {p.failed}</span>
                    <span className="text-amber-600 dark:text-amber-400">Remaining: {Math.max(0, p.total - p.processed)}</span>
                  </div>
                </div>
              </div>
            );
          })()}

          {/* Live progress banner */}
          {running > 0 && (
            <div className="bg-white dark:bg-slate-900 border border-indigo-200 dark:border-indigo-900/50 rounded-none p-4 shadow-sm">
              <div className="flex items-center justify-between mb-2">
                <p className="text-xs font-bold text-indigo-700 dark:text-indigo-300">
                  <i className="fa-solid fa-phone-volume fa-beat-fade mr-2" />
                  {running} AI call{running === 1 ? '' : 's'} in progress — statuses update live
                </p>
                <p className="text-[11px] font-semibold text-slate-400">{completedCalls}/{totalCalls} completed</p>
              </div>
              <div className="h-1.5 bg-slate-100 dark:bg-slate-800 rounded-full overflow-hidden">
                <div
                  className="h-full rounded-full bg-indigo-500 transition-all duration-700"
                  style={{ width: `${totalCalls ? Math.round((completedCalls / totalCalls) * 100) : 0}%` }}
                />
              </div>
            </div>
          )}

          {/* Dashboard cards — click one to filter the table to that slice */}
          {dashboard ? (
            <AIScreeningCards data={dashboard} onSelect={setCardFilter} />
          ) : (
            <div className="grid grid-cols-2 sm:grid-cols-3 xl:grid-cols-6 gap-4">
              {[...Array(6)].map((_, i) => (
                <div key={i} className="h-32 bg-slate-100 dark:bg-slate-800 rounded-none animate-pulse" />
              ))}
            </div>
          )}

          {/* Candidates table */}
          {error ? (
            <div className="bg-white dark:bg-slate-900 border border-slate-200 dark:border-slate-800 rounded-none p-10 text-center shadow-sm">
              <i className="fa-solid fa-triangle-exclamation text-3xl text-amber-500 mb-3" />
              <p className="text-sm font-semibold text-slate-700 dark:text-slate-300">Could not load screening data</p>
              <p className="text-xs text-slate-400 dark:text-slate-500 mt-1">{error}</p>
              <button
                onClick={refresh}
                className="mt-4 bg-[#405189] hover:bg-[#364574] text-white px-4 py-2 rounded-none text-sm font-medium transition cursor-pointer"
              >
                <i className="fa-solid fa-rotate-right mr-2" />
                Retry
              </button>
            </div>
          ) : status ? (
            <>
              {cardFilter !== 'all' && (
                <div className="flex items-center gap-2 -mb-2">
                  <span className="inline-flex items-center gap-2 px-3 py-1.5 rounded-full text-[11px] font-bold bg-indigo-50 text-indigo-700 dark:bg-indigo-950/40 dark:text-indigo-300">
                    <i className="fa-solid fa-filter text-[9px]" />
                    Showing {CARD_FILTER_LABELS[cardFilter]} ({visibleRows.length})
                    <button
                      onClick={() => setCardFilter('all')}
                      className="ml-1 hover:text-indigo-900 dark:hover:text-white transition cursor-pointer"
                      title="Clear filter"
                    >
                      <i className="fa-solid fa-xmark" />
                    </button>
                  </span>
                </div>
              )}
              <AIScreeningTable
                rows={visibleRows}
                selected={selected}
                onToggle={toggle}
                onToggleAll={toggleAll}
                busyCallId={busyCallId}
                onTranscript={setTranscriptCall}
                onReport={downloadReport}
                onRetry={retry}
              />
            </>
          ) : (
            <div className="h-72 bg-slate-100 dark:bg-slate-800 rounded-none animate-pulse" />
          )}
        </div>
      </main>

      {transcriptCall !== null && (
        <TranscriptModal callId={transcriptCall} onClose={() => setTranscriptCall(null)} />
      )}



      {addOpen && (
        <AddCandidateModal
          jobId={jobId}
          existingIds={new Set(rows.map((r) => r.candidate_id))}
          onClose={() => setAddOpen(false)}
          onAdded={(ids) => {
            // Pre-tick the new candidates so one click on Start AI Screening calls them
            setSelected((prev) => new Set([...prev, ...ids]));
            refresh();
          }}
        />
      )}
    </>
  );
}
