import { useState } from 'react';
import { useTranslation } from 'react-i18next';
import {Alert, Button, Center, Group, Loader, Modal, Paper, Select, Stack, Text, Textarea} from '@mantine/core';
import { IconInfoCircle } from '@tabler/icons-react';
import { AdvancedTable, notify, PageHeader, PageLoader, useServerTable } from '@ema-platform/ui';
import { useDateDisplayer } from '@ema-platform/shared';
import { extractErrorMessage } from '@ema-platform/api';
import {
  useGetPendingAppealsQuery,
  useDecideAppealMutation,
} from '../../api/result-api';
import { examAppealsColumns } from './columns';
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, refetch } = useGetPendingAppealsQuery();
  const table = useServerTable();
  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 <PageLoader label="Loading Exam Appeals…" height={400} />;
  }
  if (isError) {
    return (
      <Alert icon={<IconInfoCircle size={16} />} color="red">
        {t('result.appeals.error')}
      </Alert>
    );
  }

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

  return (
    <Stack gap="lg">
      <PageHeader
        title={t('result.appeals.title')}
        subtitle={t('result.appeals.subtitle')}
        noMargin
      />

      <Paper withBorder radius="md">
        <AdvancedTable<ExamAppeal>
          tableName={t('result.appeals.title')}
          columns={examAppealsColumns(t, locale, showDate, {
            onDecide: (appeal) => {
              setTarget(appeal);
              setOutcome('UPHELD');
              setRemark('');
            },
          })}
          data={paged.rows}
          itemCount={paged.itemCount}
          pageIndex={paged.pageIndex}
          onPageChange={table.setPageIndex}
          pageSize={table.pageSize}
          refresh={refetch}
          emptyText={t('result.appeals.none')}
        />
      </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;
