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

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

/**
 * 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, refetch } = useGetExamIncidentsQuery(examId);
  const table = useServerTable();
  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 startResolve = (incident: ExamIncident) => {
    setResolveTarget(incident);
    setOutcome('RESOLVED');
    setResolution('');
  };

  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;

  const paged = table.paginate(incidents ?? []);

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

      {(incidents ?? []).length === 0 ? (
        <Alert color="gray" icon={<IconInfoCircle size={16} />}>
          {t('exam.incidents.none')}
        </Alert>
      ) : (
        <AdvancedTable<ExamIncident>
          tableName={t('exam.incidents.section')}
          columns={examIncidentColumns(t, showDate, { onResolve: startResolve })}
          data={paged.rows}
          itemCount={paged.itemCount}
          pageIndex={paged.pageIndex}
          onPageChange={table.setPageIndex}
          pageSize={table.pageSize}
          refresh={refetch}
        />
      )}

      <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>
  );
}
