import { useState } from 'react';
import { useTranslation } from 'react-i18next';
import {
  Alert,
  Badge,
  Button,
  Group,
  Modal,
  Paper,
  Select,
  Stack,
  Table,
  Text,
  Textarea,
  Title,
} from '@mantine/core';
import { IconAlertTriangle, IconInfoCircle, IconPlus } from '@tabler/icons-react';
import { notify } from '@ema-platform/ui';
import { useDateDisplayer } from '@ema-platform/shared';
import { extractErrorMessage } from '@ema-platform/api';
import {
  useGetExamIncidentsQuery,
  useGetExamRegistrationsQuery,
  useRecordIncidentMutation,
  useResolveIncidentMutation,
} from '../api/exam-api';
import type {
  ExamIncident,
  ExamIncidentStatus,
  ExamIncidentType,
} from '../types/exam';

const TYPES: ExamIncidentType[] = [
  'MISCONDUCT',
  'TECHNICAL_FAILURE',
  'MEDICAL',
  'ADMINISTRATIVE',
  'OTHER',
];

const STATUS_COLOR: Record<ExamIncidentStatus, string> = {
  OPEN: 'red',
  UNDER_REVIEW: 'yellow',
  RESOLVED: 'teal',
  DISMISSED: 'gray',
};

/**
 * The session incident log (US-EXAM-010). Invigilators file entries during the
 * sitting; a supervisor closes each one with a written ruling that stays on
 * the record beside the original report.
 */
export function ExamIncidentsPanel({ examId }: { examId: string }) {
  const { t } = useTranslation();
  const showDate = useDateDisplayer();
  const { data: incidents, isError } = useGetExamIncidentsQuery(examId);
  const { data: registrations } = useGetExamRegistrationsQuery(examId);
  const [recordIncident, { isLoading: isFiling }] = useRecordIncidentMutation();
  const [resolveIncident, { isLoading: isResolving }] = useResolveIncidentMutation();

  const [addOpen, setAddOpen] = useState(false);
  const [type, setType] = useState<ExamIncidentType>('MISCONDUCT');
  const [registrationId, setRegistrationId] = useState<string | null>(null);
  const [description, setDescription] = useState('');

  const [resolveTarget, setResolveTarget] = useState<ExamIncident | null>(null);
  const [outcome, setOutcome] = useState<'RESOLVED' | 'DISMISSED'>('RESOLVED');
  const [resolution, setResolution] = useState('');

  const candidateOptions = (registrations ?? []).map((registration) => ({
    value: registration.id,
    label: `${registration.admissionNumber} — ${[
      registration.profile?.firstName,
      registration.profile?.lastName,
    ]
      .filter(Boolean)
      .join(' ')}`,
  }));

  const file = async () => {
    if (!description.trim()) {
      notify.error(t('exam.incidents.description'));
      return;
    }
    try {
      await recordIncident({
        examId,
        type,
        registrationId: registrationId ?? undefined,
        description: description.trim(),
      }).unwrap();
      notify.success(t('exam.incidents.filed'));
      setAddOpen(false);
      setDescription('');
      setRegistrationId(null);
    } catch (error) {
      notify.error(extractErrorMessage(error, t('exam.incidents.error')));
    }
  };

  const close = async () => {
    if (!resolveTarget || !resolution.trim()) {
      notify.error(t('exam.incidents.resolution'));
      return;
    }
    try {
      await resolveIncident({
        incidentId: resolveTarget.id,
        outcome,
        resolution: resolution.trim(),
      }).unwrap();
      notify.success(t('exam.incidents.resolved'));
      setResolveTarget(null);
      setResolution('');
    } catch (error) {
      notify.error(extractErrorMessage(error, t('exam.incidents.error')));
    }
  };

  // Hidden entirely from officers without the incident permission — the
  // endpoint refuses them, so there is nothing to render.
  if (isError) return null;

  return (
    <Paper withBorder radius="lg" p="lg">
      <Group justify="space-between" mb="md">
        <Title order={5}>{t('exam.incidents.section')}</Title>
        <Button
          size="xs"
          variant="light"
          color="orange"
          leftSection={<IconPlus size={14} />}
          onClick={() => setAddOpen(true)}
        >
          {t('exam.incidents.add')}
        </Button>
      </Group>

      {(incidents ?? []).length === 0 ? (
        <Alert color="gray" icon={<IconInfoCircle size={16} />}>
          {t('exam.incidents.none')}
        </Alert>
      ) : (
        <Table striped>
          <Table.Thead>
            <Table.Tr>
              <Table.Th>{t('exam.incidents.type')}</Table.Th>
              <Table.Th>{t('exam.incidents.candidate')}</Table.Th>
              <Table.Th>{t('exam.incidents.description')}</Table.Th>
              <Table.Th>{t('exam.incidents.occurred')}</Table.Th>
              <Table.Th>{t('exam.incidents.status')}</Table.Th>
              <Table.Th />
            </Table.Tr>
          </Table.Thead>
          <Table.Tbody>
            {(incidents ?? []).map((incident) => (
              <Table.Tr key={incident.id}>
                <Table.Td>
                  <Badge size="sm" variant="light" color="orange">
                    {t(`exam.incidentType.${incident.type}`)}
                  </Badge>
                </Table.Td>
                <Table.Td>
                  <Text fz="xs">
                    {incident.registration?.admissionNumber ??
                      t('exam.incidents.wholeRoom')}
                  </Text>
                </Table.Td>
                <Table.Td>
                  <Text fz="xs" maw={260} lineClamp={2}>
                    {incident.description}
                  </Text>
                  {incident.resolution && (
                    <Text fz="xs" c="dimmed" maw={260} lineClamp={2}>
                      ⤷ {incident.resolution}
                    </Text>
                  )}
                </Table.Td>
                <Table.Td>
                  <Text fz="xs">{showDate(incident.occurredAt)}</Text>
                </Table.Td>
                <Table.Td>
                  <Badge
                    size="sm"
                    variant="light"
                    color={STATUS_COLOR[incident.status] ?? 'gray'}
                  >
                    {t(`exam.incidentStatus.${incident.status}`)}
                  </Badge>
                </Table.Td>
                <Table.Td>
                  {(incident.status === 'OPEN' ||
                    incident.status === 'UNDER_REVIEW') && (
                    <Button
                      size="compact-xs"
                      variant="light"
                      leftSection={<IconAlertTriangle size={12} />}
                      onClick={() => {
                        setResolveTarget(incident);
                        setOutcome('RESOLVED');
                        setResolution('');
                      }}
                    >
                      {t('exam.incidents.resolve')}
                    </Button>
                  )}
                </Table.Td>
              </Table.Tr>
            ))}
          </Table.Tbody>
        </Table>
      )}

      <Modal
        opened={addOpen}
        onClose={() => setAddOpen(false)}
        title={t('exam.incidents.add')}
        size="md"
        radius="lg"
      >
        <Stack gap="sm">
          <Select
            label={t('exam.incidents.type')}
            data={TYPES.map((value) => ({
              value,
              label: t(`exam.incidentType.${value}`),
            }))}
            value={type}
            onChange={(value) => setType((value as ExamIncidentType) ?? 'OTHER')}
            size="sm"
          />
          <Select
            label={t('exam.incidents.candidate')}
            placeholder={t('exam.incidents.wholeRoom')}
            data={candidateOptions}
            value={registrationId}
            onChange={setRegistrationId}
            size="sm"
            clearable
            searchable
          />
          <Textarea
            label={t('exam.incidents.description')}
            minRows={3}
            autosize
            value={description}
            onChange={(event) => setDescription(event.currentTarget.value)}
            required
          />
          <Group justify="flex-end">
            <Button variant="default" size="sm" onClick={() => setAddOpen(false)}>
              {t('exam.cancel')}
            </Button>
            <Button size="sm" loading={isFiling} onClick={file}>
              {t('exam.incidents.add')}
            </Button>
          </Group>
        </Stack>
      </Modal>

      <Modal
        opened={Boolean(resolveTarget)}
        onClose={() => setResolveTarget(null)}
        title={t('exam.incidents.resolve')}
        size="md"
        radius="lg"
      >
        <Stack gap="sm">
          <Text fz="sm">{resolveTarget?.description}</Text>
          <Select
            label={t('exam.incidents.outcome')}
            data={[
              { value: 'RESOLVED', label: t('exam.incidentStatus.RESOLVED') },
              { value: 'DISMISSED', label: t('exam.incidentStatus.DISMISSED') },
            ]}
            value={outcome}
            onChange={(value) =>
              setOutcome((value as 'RESOLVED' | 'DISMISSED') ?? 'RESOLVED')
            }
            size="sm"
          />
          <Textarea
            label={t('exam.incidents.resolution')}
            minRows={3}
            autosize
            value={resolution}
            onChange={(event) => setResolution(event.currentTarget.value)}
            required
          />
          <Group justify="flex-end">
            <Button variant="default" size="sm" onClick={() => setResolveTarget(null)}>
              {t('exam.cancel')}
            </Button>
            <Button size="sm" loading={isResolving} onClick={close}>
              {t('exam.incidents.resolve')}
            </Button>
          </Group>
        </Stack>
      </Modal>
    </Paper>
  );
}
