'use client';

import { useCallback, useEffect, useMemo, useState } from 'react';
import Cookies from 'js-cookie';
import { toast } from 'react-toastify';
import type { ColumnDef } from '@tanstack/react-table';
import { api } from '@/lib/api';
import type { User } from '@/types';
import { DataTable } from '@/components/data-table/DataTable';
import type { ToolbarFilterConfig } from '@/components/data-table/DataTableToolbar';
import CandidateReportSummaryCards from './CandidateReportSummaryCards';
import CandidateReportViewer from './CandidateReportViewer';
import GenerateReportModal from './GenerateReportModal';
import type {
  CandidateReportListData,
  CandidateReportRow,
  CandidateReportsSummary,
} from './types';
import { CLASSIFICATIONS } from './types';

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

const CLASSIFICATION_BADGES: Record<string, string> = {
  'Highly Recommended': 'bg-emerald-50 text-emerald-700 dark:bg-emerald-950/40 dark:text-emerald-300',
  'Recommended': 'bg-blue-50 text-blue-700 dark:bg-blue-950/40 dark:text-blue-300',
  'Consider': 'bg-amber-50 text-amber-700 dark:bg-amber-950/40 dark:text-amber-300',
  'Not Recommended': 'bg-rose-50 text-rose-700 dark:bg-rose-950/40 dark:text-rose-300',
};

function scoreColor(score: number) {
  if (score >= 75) return 'text-emerald-600 dark:text-emerald-400';
  if (score >= 50) return 'text-amber-600 dark:text-amber-400';
  return 'text-rose-600 dark:text-rose-400';
}

function SkeletonBlock({ className }: { className: string }) {
  return <div className={`bg-slate-100 dark:bg-slate-800 rounded-none animate-pulse ${className}`} />;
}

function uniqueOptions(rows: CandidateReportRow[], key: keyof CandidateReportRow) {
  const set = new Set<string>();
  rows.forEach((r) => {
    const v = r[key];
    if (typeof v === 'string' && v) set.add(v);
  });
  return [...set].sort().map((v) => ({ label: v, value: v }));
}

export default function CandidateReportsPage({ user }: { user: User }) {
  // Generation is for admins/managers; recruiters are view/download-only
  const canGenerate = user.role === 'ADMIN' || (user.role ?? '').toUpperCase().includes('MANAGER');

  const [rows, setRows] = useState<CandidateReportRow[]>([]);
  const [summary, setSummary] = useState<CandidateReportsSummary | null>(null);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState<string | null>(null);

  const [viewing, setViewing] = useState<number | null>(null);
  const [viewerKey, setViewerKey] = useState(0);
  const [confirming, setConfirming] = useState<CandidateReportRow | null>(null);
  const [busyId, setBusyId] = useState<number | null>(null);

  const load = useCallback(() => {
    setLoading(true);
    setError(null);
    // Load the full set once; the DataTable does search/sort/paginate/export in-browser.
    Promise.all([
      api.get('/reports/candidate-reports/?page=1&page_size=2000&sort=created&order=desc'),
      api.get('/reports/candidate-reports/summary/'),
    ])
      .then(([list, sum]) => {
        setRows((list as { data: CandidateReportListData }).data.results);
        setSummary((sum as { data: CandidateReportsSummary }).data);
      })
      .catch((e: unknown) => {
        const msg = e instanceof Error ? e.message : 'Failed to load candidate reports';
        setError(msg);
        toast.error(msg);
      })
      .finally(() => setLoading(false));
  }, []);

  useEffect(load, [load]);

  const handleDownload = async (candidateId: number, version?: number) => {
    setBusyId(candidateId);
    try {
      const qs = version ? `?version=${version}` : '';
      const res = await fetch(`${API_BASE_URL}/reports/candidate-reports/${candidateId}/download/${qs}`, {
        headers: { Authorization: `Bearer ${Cookies.get('access_token')}` },
      });
      if (!res.ok) throw new Error(res.status === 404 ? 'No report generated yet' : `Download failed (status ${res.status})`);
      const disposition = res.headers.get('content-disposition') || '';
      const filename = disposition.match(/filename="?([^";]+)"?/)?.[1] || `candidate_${candidateId}_report.pdf`;
      const blob = await res.blob();
      const url = URL.createObjectURL(blob);
      const a = document.createElement('a');
      a.href = url;
      a.download = filename;
      a.click();
      URL.revokeObjectURL(url);
      toast.success('PDF report downloaded');
    } catch (e) {
      toast.error(e instanceof Error ? e.message : 'Download failed');
    } finally {
      setBusyId(null);
    }
  };

  const handleGenerate = async () => {
    if (!confirming) return;
    const target = confirming;
    setBusyId(target.candidate_id);
    try {
      const action = target.has_report ? 'regenerate' : 'generate';
      const res = (await api.post(`/reports/candidate-reports/${target.candidate_id}/${action}/`)) as { message?: string };
      toast.success(res.message || 'Report generated');
      setConfirming(null);
      setViewerKey((k) => k + 1);
      load();
    } catch (e) {
      toast.error(e instanceof Error ? e.message : 'Generation failed');
    } finally {
      setBusyId(null);
    }
  };

  const rowFor = (candidateId: number): CandidateReportRow | undefined =>
    rows.find((r) => r.candidate_id === candidateId);

  const columns = useMemo<ColumnDef<CandidateReportRow>[]>(() => [
    {
      accessorKey: 'name',
      header: 'Candidate Name',
      cell: ({ row }) => (
        <div>
          <span className="font-bold text-slate-800 dark:text-white">{row.original.name || '—'}</span>
          <span className="block text-[10px] text-slate-400 dark:text-slate-500 font-medium">{row.original.candidate_code}</span>
        </div>
      ),
    },
    {
      accessorKey: 'job_title',
      header: 'Job Title',
      cell: ({ getValue }) => (
        <span className="block max-w-[160px] truncate" title={String(getValue() || '')}>{(getValue() as string) || '—'}</span>
      ),
    },
    {
      accessorKey: 'overall_score',
      header: 'Overall Score',
      cell: ({ row }) =>
        row.original.overall_score !== null ? (
          <span className={`font-bold ${scoreColor(row.original.overall_score)}`}>{row.original.overall_score}%</span>
        ) : '—',
    },
    {
      accessorKey: 'classification',
      header: 'Classification',
      filterFn: 'equalsString',
      cell: ({ getValue }) => {
        const v = getValue() as string;
        return v ? (
          <span className={`inline-flex px-2 py-0.5 rounded-full text-[10px] font-extrabold ${CLASSIFICATION_BADGES[v] || ''}`}>{v}</span>
        ) : (
          <span className="text-slate-400 dark:text-slate-600">No report</span>
        );
      },
    },
    {
      accessorKey: 'recommendation',
      header: 'Recommendation',
      cell: ({ getValue }) => (
        <span className="block max-w-[240px] truncate" title={String(getValue() || '')}>{(getValue() as string) || '—'}</span>
      ),
    },
    {
      accessorKey: 'report_version',
      header: 'Report Version',
      cell: ({ getValue }) => (getValue() != null ? `v${getValue()}` : '—'),
    },
    {
      accessorKey: 'generated_by',
      header: 'Generated By',
      cell: ({ getValue }) => (getValue() as string) || '—',
    },
    {
      accessorKey: 'report_generated_at',
      header: 'Generated Date',
      cell: ({ getValue }) => (getValue() as string) || '—',
    },
    // Hidden-by-default columns — used for global search / filtering, toggleable via "Columns"
    {
      accessorKey: 'email',
      header: 'Email',
      cell: ({ getValue }) => (getValue() as string) || '—',
    },
    {
      accessorKey: 'client',
      header: 'Client',
      filterFn: 'equalsString',
      cell: ({ getValue }) => (getValue() as string) || '—',
    },
    {
      accessorKey: 'recruiter',
      header: 'Recruiter',
      filterFn: 'equalsString',
      cell: ({ getValue }) => (getValue() as string) || '—',
    },
    {
      accessorKey: 'candidate_status',
      header: 'Status',
      filterFn: 'equalsString',
      cell: ({ getValue }) => (getValue() as string) || '—',
    },
    {
      id: 'actions',
      header: () => <div className="text-right">Actions</div>,
      enableSorting: false,
      enableHiding: false,
      cell: ({ row }) => {
        const r = row.original;
        return (
          <div className="flex items-center justify-end gap-1.5">
            <button
              onClick={() => setViewing(r.candidate_id)}
              className="px-2 py-1 rounded-none text-[10px] font-bold text-indigo-600 dark:text-indigo-400 border border-indigo-200 dark:border-indigo-900/50 hover:bg-indigo-600 hover:text-white dark:hover:bg-indigo-600 transition cursor-pointer"
              title="View report"
            >
              <i className="fa-solid fa-eye" />
            </button>
            <button
              onClick={() => handleDownload(r.candidate_id)}
              disabled={!r.has_report || busyId === r.candidate_id}
              className="px-2 py-1 rounded-none text-[10px] font-bold text-slate-600 dark:text-slate-300 border border-slate-200 dark:border-slate-700 hover:bg-slate-600 hover:text-white dark:hover:bg-slate-600 transition cursor-pointer disabled:opacity-40 disabled:cursor-not-allowed"
              title={r.has_report ? 'Download PDF' : 'No report generated yet'}
            >
              <i className="fa-solid fa-download" />
            </button>
            {canGenerate && (
              <button
                onClick={() => setConfirming(r)}
                disabled={busyId === r.candidate_id}
                className="px-2 py-1 rounded-none text-[10px] font-bold text-emerald-600 dark:text-emerald-400 border border-emerald-200 dark:border-emerald-900/50 hover:bg-emerald-600 hover:text-white dark:hover:bg-emerald-600 transition cursor-pointer disabled:opacity-40"
                title={r.has_report ? 'Regenerate report (new version)' : 'Generate report'}
              >
                <i className={`fa-solid ${busyId === r.candidate_id ? 'fa-spinner fa-spin' : r.has_report ? 'fa-rotate' : 'fa-wand-magic-sparkles'}`} />
              </button>
            )}
          </div>
        );
      },
    },
  ], [busyId, canGenerate]);

  const filters = useMemo<ToolbarFilterConfig[]>(() => [
    { columnId: 'classification', title: 'Classification', options: CLASSIFICATIONS.map((c) => ({ label: c, value: c })) },
    { columnId: 'candidate_status', title: 'Status', options: uniqueOptions(rows, 'candidate_status') },
    { columnId: 'client', title: 'Client', options: uniqueOptions(rows, 'client') },
    { columnId: 'recruiter', title: 'Recruiter', options: uniqueOptions(rows, 'recruiter') },
  ], [rows]);

  return (
    <div className="space-y-5">
      {/* Title */}
      <div>
        <h1 className="text-xl font-bold text-slate-900 dark:text-white">Candidate Reports</h1>
        <p className="text-sm text-slate-500 dark:text-slate-400 mt-0.5">
          Generate, view and download per-candidate PDF evaluation reports.
        </p>
      </div>

      {/* Analytics cards */}
      {summary ? (
        <CandidateReportSummaryCards summary={summary} onClassificationClick={() => { /* filtering now handled in-table */ }} />
      ) : (
        <div className="grid grid-cols-1 sm:grid-cols-2 xl:grid-cols-5 gap-4">
          {[...Array(5)].map((_, i) => <SkeletonBlock key={i} className="h-32" />)}
        </div>
      )}

      {/* DataTable */}
      {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 candidate reports</p>
          <p className="text-xs text-slate-400 dark:text-slate-500 mt-1">{error}</p>
          <button
            onClick={load}
            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>
      ) : (
        <DataTable
          columns={columns}
          data={rows}
          loading={loading}
          compact
          collapsibleFilters
          enableColumnVisibility
          filters={filters}
          exportConfig={{ fileName: 'candidate_reports' }}
          initialColumnVisibility={{ email: false, client: false, recruiter: false, candidate_status: false }}
          searchPlaceholder="Search candidate, email…"
          emptyStateTitle="No candidate reports"
          emptyStateDescription="No candidates match the current filters. Adjust or reset the filters to see more."
        />
      )}

      {/* Report viewer modal */}
      {viewing !== null && (
        <CandidateReportViewer
          key={`${viewing}-${viewerKey}`}
          candidateId={viewing}
          onClose={() => setViewing(null)}
          onDownload={handleDownload}
          canGenerate={canGenerate}
          onGenerate={(id) => {
            const row = rowFor(id);
            if (row) setConfirming(row);
          }}
        />
      )}

      {/* Generate/regenerate confirmation */}
      {confirming && (
        <GenerateReportModal
          candidateName={confirming.name}
          isRegenerate={confirming.has_report}
          busy={busyId === confirming.candidate_id}
          onConfirm={handleGenerate}
          onCancel={() => setConfirming(null)}
        />
      )}
    </div>
  );
}
