import { useCallback, useMemo, useState } from 'react';
import { useTranslation } from 'react-i18next';
import {Badge, Button, Center, Container, Group, Loader, Modal, Paper, SegmentedControl, Stack, Text, Textarea} from '@mantine/core';
import { IconEye, IconInbox, IconPaperclip } from '@tabler/icons-react';
import { AdvancedTable, notify, PageHeader, PdfPreviewModal, type AdvancedColumn } from '@ema-platform/ui';
import { useDateDisplayer } from '@ema-platform/shared';
import {
  extractErrorMessage,
  useGetAttachmentsQuery,
  useGetPendingMedicalQuery,
  useGetPendingSeaServiceQuery,
  useVerifyMedicalCertificateMutation,
  useVerifySeaServiceRecordMutation,
} from '@ema-platform/api';
import type {
  MedicalCertificate,
  RecordQueueFilter,
  SeaServiceRecord,
} from '@ema-platform/api';
import { medicalColumns, seaServiceColumns, ownerName } from './columns';
import { medicalActionsColumn, seaServiceActionsColumn } from './actions';

const PAGE_SIZE = 10;

/** Reject dialog — the remark is what the seafarer sees and must act on. */
function RejectModal({
  title,
  opened,
  onClose,
  onConfirm,
  loading,
}: {
  title: string;
  opened: boolean;
  onClose: () => void;
  onConfirm: (remark: string) => void;
  loading: boolean;
}) {
  const { t } = useTranslation();
  const [remark, setRemark] = useState('');
  return (
    <Modal opened={opened} onClose={onClose} title={title} centered>
      <Stack>
        <Textarea
          label={t('recordVerification.rejectReasonLabel', 'What must the seafarer fix?')}
          required
          minRows={2}
          value={remark}
          onChange={(e) => setRemark(e.target.value)}
        />
        <Group justify="flex-end">
          <Button variant="default" onClick={onClose}>
            {t('recordVerification.cancel', 'Cancel')}
          </Button>
          <Button
            color="red"
            disabled={remark.trim().length < 3}
            loading={loading}
            onClick={() => {
              onConfirm(remark.trim());
              setRemark('');
            }}
          >
            {t('recordVerification.reject', 'Reject')}
          </Button>
        </Group>
      </Stack>
    </Modal>
  );
}

/** Attachments / Evidence Modal for viewing uploaded files for a record */
function AttachmentsModal({
  opened,
  ownerType,
  ownerId,
  title,
  onClose,
}: {
  opened: boolean;
  ownerType: 'MEDICAL_CERTIFICATE' | 'SEA_SERVICE_RECORD';
  ownerId: string | null;
  title: string;
  onClose: () => void;
}) {
  const { t } = useTranslation();
  const { data: attachments, isLoading } = useGetAttachmentsQuery(
    { ownerType, ownerId: ownerId ?? '' },
    { skip: !ownerId },
  );
  const [preview, setPreview] = useState<{ url: string; title: string } | null>(
    null,
  );

  const files = useMemo(
    () => (attachments ?? []).flatMap((a) => a.files ?? []),
    [attachments],
  );

  return (
    <Modal opened={opened} onClose={onClose} title={title} size="md" centered>
      <Stack gap="sm">
        {isLoading ? (
          <Center py="xl">
            <Loader size="sm" />
          </Center>
        ) : files.length === 0 ? (
          <Center py="xl">
            <Group gap="xs" c="dimmed">
              <IconInbox size={18} />
              <Text size="sm" c="dimmed">
                {t(
                  'recordVerification.noAttachments',
                  'No evidence attachments uploaded for this record.',
                )}
              </Text>
            </Group>
          </Center>
        ) : (
          files.map((file) => (
            <Paper key={file.id} withBorder p="xs" radius="sm">
              <Group justify="space-between" wrap="nowrap">
                <Group gap="xs" wrap="nowrap" style={{ minWidth: 0 }}>
                  <IconPaperclip size={18} />
                  <div style={{ minWidth: 0 }}>
                    <Text size="sm" fw={500} truncate>
                      {file.originalName}
                    </Text>
                    {file.sizeBytes && (
                      <Text size="xs" c="dimmed">
                        {(file.sizeBytes / 1024).toFixed(1)} KB
                      </Text>
                    )}
                  </div>
                </Group>
                {file.url ? (
                  <Button
                    size="compact-xs"
                    variant="light"
                    leftSection={<IconEye size={14} />}
                    onClick={() =>
                      setPreview({ url: file.url as string, title: file.originalName })
                    }
                  >
                    {t('recordVerification.view', 'View')}
                  </Button>
                ) : (
                  <Badge size="sm" variant="light" color="gray">
                    {t('recordVerification.noUrl', 'No URL')}
                  </Badge>
                )}
              </Group>
            </Paper>
          ))
        )}
      </Stack>
      <PdfPreviewModal
        opened={Boolean(preview)}
        onClose={() => setPreview(null)}
        url={preview?.url ?? ''}
        title={preview?.title}
      />
    </Modal>
  );
}

/**
 * The record-verification workspace (US-SSM-003/007): everything seafarers
 * have submitted and no officer has ruled on yet, oldest first. VERIFIED
 * freezes a record — sea service starts counting toward sea time, a medical
 * certificate starts satisfying the submission gate.
 */
export type VerificationKind = 'medical' | 'sea-service';

/**
 * One kind per page — the sidebar lists "Sea Service Verification" and
 * "Medical Verification" separately, so an officer lands on the queue they
 * came for rather than on a tab.
 */
export function MedicalVerificationPage({ kind = 'medical' }: { kind?: VerificationKind }) {
  const { t } = useTranslation();
  const isMedical = kind === 'medical';
  const [filter, setFilter] = useState<RecordQueueFilter>('SUBMITTED');
  const {
    data: pendingMedical,
    isLoading: loadingMedical,
    isFetching: fetchingMedical,
    refetch: refetchMedical,
  } = useGetPendingMedicalQuery(filter, { skip: !isMedical });

  const {
    data: pendingSeaService,
    isLoading: loadingSeaService,
    isFetching: fetchingSeaService,
    refetch: refetchSeaService,
  } = useGetPendingSeaServiceQuery(filter, { skip: isMedical });

  const [verifyMedical, { isLoading: rulingMedical }] =
    useVerifyMedicalCertificateMutation();
  const [verifySeaService, { isLoading: rulingSeaService }] =
    useVerifySeaServiceRecordMutation();

  const [rejectMedical, setRejectMedical] = useState<MedicalCertificate | null>(
    null,
  );
  const [rejectSeaService, setRejectSeaService] =
    useState<SeaServiceRecord | null>(null);

  const [attachmentModal, setAttachmentModal] = useState<{
    ownerType: 'MEDICAL_CERTIFICATE' | 'SEA_SERVICE_RECORD';
    ownerId: string;
    title: string;
  } | null>(null);

  const showDate = useDateDisplayer();

  const [medicalPage, setMedicalPage] = useState(0);
  const [seaServicePage, setSeaServicePage] = useState(0);
  const [medicalPageSize, setMedicalPageSize] = useState(PAGE_SIZE);
  const [seaServicePageSize, setSeaServicePageSize] = useState(PAGE_SIZE);

  const rule = useCallback(
    async (run: () => Promise<unknown>, done: string): Promise<void> => {
      try {
        await run();
        notify.success(done);
      } catch (error) {
        notify.error(
          extractErrorMessage(error, t('recordVerification.rulingFailed', 'Could not record the ruling')),
        );
      }
    },
    [t],
  );

  const pendingMedicalList = useMemo(
    () => pendingMedical ?? [],
    [pendingMedical],
  );
  const pendingSeaServiceList = useMemo(
    () => pendingSeaService ?? [],
    [pendingSeaService],
  );

  const pagedMedical = useMemo(() => {
    const start = medicalPage * medicalPageSize;
    return pendingMedicalList.slice(start, start + medicalPageSize);
  }, [pendingMedicalList, medicalPage, medicalPageSize]);

  const pagedSeaService = useMemo(() => {
    const start = seaServicePage * seaServicePageSize;
    return pendingSeaServiceList.slice(start, start + seaServicePageSize);
  }, [pendingSeaServiceList, seaServicePage, seaServicePageSize]);

  const changeFilter = useCallback((value: string) => {
    setFilter(value as RecordQueueFilter);
    setMedicalPage(0);
    setSeaServicePage(0);
  }, []);

  const handleMedicalPageSizeChange = useCallback((size: number) => {
    setMedicalPageSize(size);
    setMedicalPage(0);
  }, []);

  const handleSeaServicePageSizeChange = useCallback((size: number) => {
    setSeaServicePageSize(size);
    setSeaServicePage(0);
  }, []);

  const statusFilter = (
    <SegmentedControl
      mb="md"
      value={filter}
      onChange={changeFilter}
      data={[
        {
          value: 'SUBMITTED',
          label: t('recordVerification.filter.pending', 'Pending'),
        },
        {
          value: 'VERIFIED',
          label: t('recordVerification.filter.verified', 'Accepted'),
        },
        {
          value: 'REJECTED',
          label: t('recordVerification.filter.rejected', 'Rejected'),
        },
        { value: 'ALL', label: t('recordVerification.filter.all', 'All') },
      ]}
    />
  );

  const emptyText =
    filter === 'SUBMITTED'
      ? t('recordVerification.emptyText', 'Nothing awaiting verification.')
      : t('recordVerification.emptyTextFiltered', 'No records match this filter.');

  const medicalTableColumns: AdvancedColumn<MedicalCertificate>[] = useMemo(
    () => [
      ...medicalColumns(t, showDate),
      medicalActionsColumn(t, {
        ruling: rulingMedical,
        onEvidence: (certificate) =>
          setAttachmentModal({
            ownerType: 'MEDICAL_CERTIFICATE',
            ownerId: certificate.id,
            title: t('recordVerification.evidenceTitleMedical', {
              name: ownerName(certificate.profile),
              defaultValue: 'Evidence for {{name}} Medical Certificate',
            }),
          }),
        onVerify: (certificate) =>
          rule(
            () =>
              verifyMedical({
                id: certificate.id,
                outcome: 'VERIFIED',
              }).unwrap(),
            t('recordVerification.certificateVerified', 'Certificate verified'),
          ),
        onReject: (certificate) => setRejectMedical(certificate),
      }),
    ],
    [rulingMedical, rule, verifyMedical, showDate, t],
  );

  const seaServiceTableColumns: AdvancedColumn<SeaServiceRecord>[] = useMemo(
    () => [
      ...seaServiceColumns(t, showDate),
      seaServiceActionsColumn(t, {
        ruling: rulingSeaService,
        onEvidence: (record) =>
          setAttachmentModal({
            ownerType: 'SEA_SERVICE_RECORD',
            ownerId: record.id,
            title: t('recordVerification.evidenceTitleSeaService', {
              name: ownerName(record.profile),
              defaultValue: 'Evidence for {{name}} Sea Service Record',
            }),
          }),
        onVerify: (record) =>
          rule(
            () =>
              verifySeaService({
                id: record.id,
                outcome: 'VERIFIED',
              }).unwrap(),
            t('recordVerification.seaServiceVerified', 'Sea-service record verified'),
          ),
        onReject: (record) => setRejectSeaService(record),
      }),
    ],
    [rulingSeaService, rule, verifySeaService, showDate, t],
  );

  return (
    <Container size="xl" py="md">
      <PageHeader
        title={
          isMedical
            ? t('recordVerification.medicalTitle', 'Medical Certificate Verification')
            : t('recordVerification.seaServiceTitle', 'Sea Service Verification')
        }
        subtitle={
          isMedical
            ? t(
                'recordVerification.medicalSubtitle',
                'Submitted medical certificates awaiting a ruling. Verified certificates are frozen; rejections return to the seafarer with your remark.',
              )
            : t(
                'recordVerification.seaServiceSubtitle',
                'Submitted sea-service records awaiting a ruling. Verified records are frozen and count toward sea time; rejections return to the seafarer with your remark.',
              )
        }
      />

      {statusFilter}

      {isMedical ? (
        <AdvancedTable
          columns={medicalTableColumns}
          data={pagedMedical}
          tableName={t('recordVerification.tabs.medical', {
            count: pendingMedicalList.length,
            defaultValue: 'Medical ({{count}})',
          })}
          itemCount={pendingMedicalList.length}
          pageIndex={medicalPage}
          onPageChange={setMedicalPage}
          pageSize={medicalPageSize}
          onPageSizeChange={handleMedicalPageSizeChange}
          refresh={refetchMedical}
          isLoading={loadingMedical || fetchingMedical}
          emptyText={emptyText}
        />
      ) : (
        <AdvancedTable
          columns={seaServiceTableColumns}
          data={pagedSeaService}
          tableName={t('recordVerification.tabs.seaService', {
            count: pendingSeaServiceList.length,
            defaultValue: 'Sea Service ({{count}})',
          })}
          itemCount={pendingSeaServiceList.length}
          pageIndex={seaServicePage}
          onPageChange={setSeaServicePage}
          pageSize={seaServicePageSize}
          onPageSizeChange={handleSeaServicePageSizeChange}
          refresh={refetchSeaService}
          isLoading={loadingSeaService || fetchingSeaService}
          emptyText={emptyText}
        />
      )}

      <AttachmentsModal
        opened={Boolean(attachmentModal)}
        ownerType={attachmentModal?.ownerType ?? 'MEDICAL_CERTIFICATE'}
        ownerId={attachmentModal?.ownerId ?? null}
        title={attachmentModal?.title ?? t('recordVerification.evidenceModalTitle', 'Evidence Attachments')}
        onClose={() => setAttachmentModal(null)}
      />

      <RejectModal
        title={t('recordVerification.rejectMedicalTitle', 'Reject medical certificate')}
        opened={Boolean(rejectMedical)}
        onClose={() => setRejectMedical(null)}
        loading={rulingMedical}
        onConfirm={(remark) => {
          if (!rejectMedical) return;
          rule(
            () =>
              verifyMedical({
                id: rejectMedical.id,
                outcome: 'REJECTED',
                remark,
              }).unwrap(),
            t('recordVerification.certificateRejected', 'Certificate rejected'),
          );
          setRejectMedical(null);
        }}
      />
      <RejectModal
        title={t('recordVerification.rejectSeaServiceTitle', 'Reject sea-service record')}
        opened={Boolean(rejectSeaService)}
        onClose={() => setRejectSeaService(null)}
        loading={rulingSeaService}
        onConfirm={(remark) => {
          if (!rejectSeaService) return;
          rule(
            () =>
              verifySeaService({
                id: rejectSeaService.id,
                outcome: 'REJECTED',
                remark,
              }).unwrap(),
            t('recordVerification.seaServiceRejected', 'Sea-service record rejected'),
          );
          setRejectSeaService(null);
        }}
      />
    </Container>
  );
}

export const SeaServiceVerificationPage = () => <MedicalVerificationPage kind="sea-service" />;

export default MedicalVerificationPage;
