import { Badge, Button, Text, Tooltip } from '@mantine/core';
import { IconFileText, IconGavel, IconPlayerPlay } from '@tabler/icons-react';
import type { TFunction } from 'i18next';
import type { AdvancedColumn } from '@ema-platform/ui';
import type { Bilingual } from '@ema-platform/api';
import { PORTAL_PERMISSIONS } from '@ema-platform/auth';
import type {
  AttendanceStatus,
  MyAppeal,
  MyRegistration,
  MyResult,
} from './index';

const ATTENDANCE_COLOR: Record<AttendanceStatus, string> = {
  REGISTERED: 'gray',
  PRESENT: 'teal',
  LATE: 'yellow',
  ABSENT: 'red',
  WITHDRAWN: 'orange',
  DISQUALIFIED: 'red',
};

/**
 * Attendance rulings that permit sitting the paper — an allow-list mirroring
 * the server's (ExamAttemptService.MAY_SIT). The deny-list this replaced named
 * only ABSENT/WITHDRAWN/DISQUALIFIED, so the default REGISTERED fell through
 * and "Take exam" appeared before any invigilator had confirmed the candidate
 * was there. LATE counts: a late arrival is present, just not on time.
 */
const MAY_SIT: AttendanceStatus[] = ['PRESENT', 'LATE'];

export function registrationColumns(
  t: TFunction,
  deps: {
    /** Permission check from usePermissions() — hooks can't run in a cell. */
    can: (required?: string[]) => boolean;
    localized: (value: Bilingual | undefined) => string;
    showDate: (value: string | null | undefined) => string;
    onDownloadSlip: (registration: MyRegistration) => void;
    onStartExam: (registration: MyRegistration) => void;
  },
): AdvancedColumn<MyRegistration>[] {
  return [
    {
      header: t('exams.columns.admission'),
      cell: ({ row }) => (
        <Text ff="monospace" size="sm" fw={600}>
          {row.original.admissionNumber}
        </Text>
      ),
    },
    {
      header: t('exams.columns.examination'),
      cell: ({ row }) => deps.localized(row.original.exam?.title) || '—',
    },
    {
      header: t('exams.columns.date'),
      cell: ({ row }) => deps.showDate(row.original.exam?.date),
    },
    {
      header: t('exams.columns.venue'),
      cell: ({ row }) => row.original.exam?.venue ?? '—',
    },
    {
      header: t('exams.columns.attempt'),
      cell: ({ row }) => (
        <Badge
          size="sm"
          variant="light"
          color={row.original.kind === 'RETAKE' ? 'orange' : 'blue'}
        >
          {row.original.kind === 'RETAKE'
            ? t('exams.columns.retake', { n: row.original.attemptNumber })
            : t('exams.columns.firstSitting')}
        </Badge>
      ),
    },
    {
      header: t('exams.columns.attendance'),
      cell: ({ row }) => (
        <Badge
          size="sm"
          variant="light"
          color={ATTENDANCE_COLOR[row.original.attendanceStatus] ?? 'gray'}
        >
          {t(`exams.columns.attendanceStatus.${row.original.attendanceStatus}`)}
        </Badge>
      ),
    },
    {
      header: t('exams.columns.slip'),
      cell: ({ row }) =>
        deps.can([PORTAL_PERMISSIONS.VIEW_OWN_EXAM]) ? (
          <Button
            size="compact-xs"
            variant="light"
            leftSection={<IconFileText size={13} />}
            onClick={() => deps.onDownloadSlip(row.original)}
          >
            {t('exams.columns.slip')}
          </Button>
        ) : null,
    },
    {
      header: t('exams.columns.exam'),
      cell: ({ row }) => {
        const exam = row.original.exam;
        const attemptStatus = row.original.attempt?.status;
        // Already finished — no restart, no more room for "Take exam" to
        // invite a click that the backend would just refuse.
        if (attemptStatus === 'SUBMITTED') {
          return (
            <Badge size="sm" variant="light" color="teal">
              {t('exams.columns.completed')}
            </Badge>
          );
        }
        if (attemptStatus === 'EXPIRED') {
          return (
            <Badge size="sm" variant="light" color="red">
              {t('exams.columns.timeExpired')}
            </Badge>
          );
        }
        if (!deps.can([PORTAL_PERMISSIONS.APPLY_EXAM])) return null;
        // Say why the exam is shut rather than rendering an empty cell: the
        // candidate is waiting on an invigilator, and silence reads as a bug.
        if (row.original.attendanceStatus === 'REGISTERED') {
          return (
            <Tooltip label={t('exams.columns.awaitingAttendanceHint')} multiline w={240}>
              <Badge size="sm" variant="light" color="gray">
                {t('exams.columns.awaitingAttendance')}
              </Badge>
            </Tooltip>
          );
        }
        if (!MAY_SIT.includes(row.original.attendanceStatus)) {
          return (
            <Badge size="sm" variant="light" color="orange">
              {t('exams.columns.notSitting')}
            </Badge>
          );
        }
        if (exam?.status !== 'ACTIVE') return null;
        return (
          <Button
            size="compact-xs"
            color="teal"
            leftSection={<IconPlayerPlay size={13} />}
            onClick={() => deps.onStartExam(row.original)}
          >
            {attemptStatus === 'IN_PROGRESS'
              ? t('exams.columns.resumeExam')
              : t('exams.columns.takeExam')}
          </Button>
        );
      },
    },
  ];
}

export function resultColumns(
  t: TFunction,
  deps: {
    /** Permission check from usePermissions() — hooks can't run in a cell. */
    can: (required?: string[]) => boolean;
    localized: (value: Bilingual | undefined) => string;
    showDate: (value: string | null | undefined) => string;
    appeals: MyAppeal[];
    onAppeal: (result: MyResult) => void;
  },
): AdvancedColumn<MyResult>[] {
  return [
    {
      header: t('exams.columns.examination'),
      cell: ({ row }) => deps.localized(row.original.exam?.title) || '—',
    },
    {
      header: t('exams.columns.published'),
      cell: ({ row }) => deps.showDate(row.original.publishedAt),
    },
    {
      header: t('exams.columns.score'),
      cell: ({ row }) => (
        <Text fw={600} size="sm">
          {row.original.totalScore}
        </Text>
      ),
    },
    {
      header: t('exams.columns.outcome'),
      cell: ({ row }) => (
        <Badge
          variant="light"
          color={row.original.status === 'PASSED' ? 'teal' : 'red'}
        >
          {t(`exams.columns.outcomeStatus.${row.original.status}`)}
        </Badge>
      ),
    },
    {
      header: t('exams.columns.appeal'),
      cell: ({ row }) => {
        const appeal = deps.appeals.find((a) => a.resultId === row.original.id);
        return appeal ? (
          <Badge size="sm" variant="light" color="grape">
            {appeal.appealNumber} ·{' '}
            {t(`exams.columns.appealStatus.${appeal.status}`)}
          </Badge>
        ) : deps.can([PORTAL_PERMISSIONS.VIEW_OWN_EXAM]) ? (
          <Button
            size="compact-xs"
            variant="light"
            color="grape"
            leftSection={<IconGavel size={13} />}
            onClick={() => deps.onAppeal(row.original)}
          >
            {t('exams.columns.appeal')}
          </Button>
        ) : null;
      },
    },
  ];
}
