import { useState } from 'react';
import { useTranslation } from 'react-i18next';
import {
  Alert,
  Badge,
  Button,
  Center,
  Group,
  Loader,
  Modal,
  Paper,
  Select,
  Stack,
  Table,
  Text,
  Textarea,
  Title,
} from '@mantine/core';
import { IconGavel, IconInfoCircle } from '@tabler/icons-react';
import { notify } from '@ema-platform/ui';
import { useDateDisplayer } from '@ema-platform/shared';
import { extractErrorMessage } from '@ema-platform/api';
import {
  useGetPendingAppealsQuery,
  useDecideAppealMutation,
} from '../api/result-api';
import type { ExamAppeal } from '../types/result';

/**
 * The appeals desk (US-EXAM-016).
 *
 * Upholding an appeal deliberately does not edit the mark here: it returns
 * the result to the examiner, so the correction travels the same moderation
 * and approval chain as the original.
 */
export function ExamAppealsPage() {
  const { t, i18n } = useTranslation();
  const locale = i18n.language as 'en' | 'am';
  const showDate = useDateDisplayer();
  const { data: appeals, isLoading, isError } = useGetPendingAppealsQuery();
  const [decideAppeal, { isLoading: isDeciding }] = useDecideAppealMutation();

  const [target, setTarget] = useState<ExamAppeal | null>(null);
  const [outcome, setOutcome] = useState<'UPHELD' | 'REJECTED'>('UPHELD');
  const [remark, setRemark] = useState('');

  const decide = async () => {
    if (!target) return;
    if (!remark.trim()) {
      notify.error(t('result.review.remarkRequired'));
      return;
    }
    try {
      await decideAppeal({ id: target.id, outcome, remark: remark.trim() }).unwrap();
      notify.success(t('result.appeals.decided'));
      setTarget(null);
      setRemark('');
    } catch (error) {
      notify.error(extractErrorMessage(error, t('result.appeals.error')));
    }
  };

  if (isLoading) {
    return (
      <Center py="xl">
        <Loader />
      </Center>
    );
  }
  if (isError) {
    return (
      <Alert icon={<IconInfoCircle size={16} />} color="red">
        {t('result.appeals.error')}
      </Alert>
    );
  }

  return (
    <Stack gap="lg">
      <div>
        <Title order={2}>{t('result.appeals.title')}</Title>
        <Text fz="sm" c="dimmed">
          {t('result.appeals.subtitle')}
        </Text>
      </div>

      <Paper withBorder radius="md">
        {(appeals ?? []).length === 0 ? (
          <Text c="dimmed" ta="center" py="xl">
            {t('result.appeals.none')}
          </Text>
        ) : (
          <Table striped highlightOnHover>
            <Table.Thead bg="var(--mantine-color-default-hover)">
              <Table.Tr>
                <Table.Th>{t('result.appeals.number')}</Table.Th>
                <Table.Th>{t('result.appeals.candidate')}</Table.Th>
                <Table.Th>{t('result.appeals.exam')}</Table.Th>
                <Table.Th>{t('result.appeals.reason')}</Table.Th>
                <Table.Th>{t('result.appeals.lodged')}</Table.Th>
                <Table.Th />
              </Table.Tr>
            </Table.Thead>
            <Table.Tbody>
              {(appeals ?? []).map((appeal) => (
                <Table.Tr key={appeal.id}>
                  <Table.Td>
                    <Text fz="sm" ff="monospace" fw={600}>
                      {appeal.appealNumber}
                    </Text>
                  </Table.Td>
                  <Table.Td>
                    <Text fz="sm">
                      {appeal.profile
                        ? `${appeal.profile.firstName} ${appeal.profile.lastName}`
                        : appeal.profileId.slice(0, 8)}
                    </Text>
                  </Table.Td>
                  <Table.Td>
                    <Text fz="sm">
                      {appeal.result?.exam?.title?.[locale] ?? '—'}
                    </Text>
                    <Badge size="xs" variant="light" color="gray">
                      {appeal.result?.status} · {appeal.result?.totalScore}
                    </Badge>
                  </Table.Td>
                  <Table.Td>
                    <Text fz="xs" maw={300} lineClamp={3}>
                      {appeal.reason}
                    </Text>
                  </Table.Td>
                  <Table.Td>
                    <Text fz="xs">{showDate(appeal.createdAt)}</Text>
                  </Table.Td>
                  <Table.Td>
                    <Button
                      size="compact-xs"
                      variant="light"
                      color="grape"
                      leftSection={<IconGavel size={12} />}
                      onClick={() => {
                        setTarget(appeal);
                        setOutcome('UPHELD');
                        setRemark('');
                      }}
                    >
                      {t('result.appeals.decide')}
                    </Button>
                  </Table.Td>
                </Table.Tr>
              ))}
            </Table.Tbody>
          </Table>
        )}
      </Paper>

      <Modal
        opened={Boolean(target)}
        onClose={() => setTarget(null)}
        title={`${t('result.appeals.decide')} — ${target?.appealNumber ?? ''}`}
        size="md"
        radius="lg"
      >
        <Stack gap="sm">
          <Text fz="sm">{target?.reason}</Text>
          <Select
            label={t('result.appeals.decide')}
            data={[
              { value: 'UPHELD', label: t('result.appeals.uphold') },
              { value: 'REJECTED', label: t('result.appeals.reject') },
            ]}
            value={outcome}
            onChange={(value) =>
              setOutcome((value as 'UPHELD' | 'REJECTED') ?? 'UPHELD')
            }
            size="sm"
          />
          {outcome === 'UPHELD' && (
            <Alert color="yellow" icon={<IconInfoCircle size={15} />}>
              {t('result.appeals.upheldHint')}
            </Alert>
          )}
          <Textarea
            label={t('result.appeals.remark')}
            minRows={3}
            autosize
            value={remark}
            onChange={(event) => setRemark(event.currentTarget.value)}
            required
          />
          <Group justify="flex-end">
            <Button variant="default" size="sm" onClick={() => setTarget(null)}>
              {t('result.cancel')}
            </Button>
            <Button size="sm" loading={isDeciding} onClick={decide}>
              {t('result.appeals.decide')}
            </Button>
          </Group>
        </Stack>
      </Modal>
    </Stack>
  );
}

export default ExamAppealsPage;
