import { useRef, useState } from 'react';
import { Alert, Badge, Button, Card, FileButton, Group, Loader, Stack, Text } from '@mantine/core';
import { IconAlertTriangle, IconCheck, IconFileUpload } from '@tabler/icons-react';
import {
  SEAFARER_REGISTRATION_DOCUMENTS,
  isEthiopianNationality,
  uploadDocument,
  type Attachment,
} from '@ema-platform/api';

const MAX_FILE_SIZE_BYTES = 5 * 1024 * 1024;

/** The document slots a registration asks for. */
export function documentSlots(passportDeclared: boolean, nationality?: string | null) {
  const ethiopian = isEthiopianNationality(nationality);
  return SEAFARER_REGISTRATION_DOCUMENTS.map((d) => ({
    ...d,
    isRequired: d.required === 'passport' ? passportDeclared : d.required === 'ethiopian' ? ethiopian : d.required,
  })).filter((d) => (d.required !== 'passport' || passportDeclared) && (d.required !== 'ethiopian' || ethiopian));
}

export function RegistrationDocuments({
  registrationId,
  passportDeclared,
  nationality,
  attachments,
  readOnly,
  onUploaded,
}: {
  registrationId: string;
  passportDeclared: boolean;
  nationality?: string | null;
  attachments: Attachment[];
  readOnly?: boolean;
  onUploaded: () => void;
}) {
  const [busy, setBusy] = useState<string | null>(null);
  const [error, setError] = useState<string | null>(null);
  const resetRefs = useRef<Record<string, () => void>>({});

  async function handle(documentKey: string, file: File | null) {
    if (!file) return;
    if (file.size > MAX_FILE_SIZE_BYTES) {
      setError(`File exceeds 5MB limit (${(file.size / 1024 / 1024).toFixed(1)}MB).`);
      resetRefs.current[documentKey]?.();
      return;
    }
    setBusy(documentKey);
    setError(null);
    const result = await uploadDocument({
      ownerType: 'SEAFARER_REGISTRATION',
      ownerId: registrationId,
      documentKey,
      file,
    });
    setBusy(null);
    resetRefs.current[documentKey]?.();
    if (result.ok) onUploaded();
    else setError(result.error);
  }

  return (
    <Stack gap="sm">
      {error && (
        <Alert color="red" icon={<IconAlertTriangle size={16} />}>
          {error}
        </Alert>
      )}
      {documentSlots(passportDeclared, nationality).map((slot) => {
        const existing = attachments.find((a) => a.documentKey === slot.key);
        const uploaded = Boolean(existing?.files?.length);
        return (
          <Card
            key={slot.key}
            withBorder
            padding="md"
            style={{
              borderColor: uploaded ? 'var(--mantine-color-teal-4)' : undefined,
              borderStyle: uploaded ? 'solid' : 'dashed',
            }}
          >
            <Group justify="space-between" wrap="nowrap" align="flex-start">
              <div style={{ minWidth: 0 }}>
                <Group gap="xs">
                  <Text fw={600} size="sm">
                    {slot.name}
                  </Text>
                  {!slot.isRequired && (
                    <Badge size="xs" variant="light" color="gray">
                      optional
                    </Badge>
                  )}
                  {uploaded && (
                    <Badge size="xs" color="teal" leftSection={<IconCheck size={10} />}>
                      uploaded
                    </Badge>
                  )}
                </Group>
                {slot.description && (
                  <Text size="xs" c="dimmed" mt={2}>
                    {slot.description}
                  </Text>
                )}
                {existing?.files?.[0] && (
                  <Text size="xs" c="dimmed" truncate mt={2}>
                    {existing.files[0].originalName} · {(existing.files[0].sizeBytes / 1024).toFixed(0)} KB
                  </Text>
                )}
              </div>
              <Group gap="xs" wrap="nowrap">
                {existing?.files?.[0]?.url && (
                  <Button size="xs" variant="subtle" component="a" href={existing.files[0].url} target="_blank">
                    View
                  </Button>
                )}
                {!readOnly && (
                  <FileButton
                    resetRef={(r) => {
                      if (r) resetRefs.current[slot.key] = r;
                    }}
                    onChange={(file) => handle(slot.key, file)}
                    accept={slot.accept}
                  >
                    {(props) => (
                      <Button
                        {...props}
                        size="xs"
                        variant={uploaded ? 'light' : 'filled'}
                        leftSection={busy === slot.key ? <Loader size={12} /> : <IconFileUpload size={14} />}
                        disabled={busy === slot.key}
                      >
                        {uploaded ? 'Replace' : 'Upload'}
                      </Button>
                    )}
                  </FileButton>
                )}
              </Group>
            </Group>
          </Card>
        );
      })}
    </Stack>
  );
}
