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

const MAX_FILE_SIZE_BYTES = 5 * 1024 * 1024;

interface Props {
  requirements: DocumentRequirement[];
  attachments: Attachment[];
  formData: Record<string, Record<string, unknown>>;
  ownerType: 'APPLICATION' | 'APPLICATION_STAFF';
  ownerId: string;
  /** Document keys the officer flagged; these render as "needs fixing". */
  flagged?: Record<string, string>;
  /** When set, only flagged slots accept a new upload. */
  restrictToFlagged?: boolean;
  onUploaded: () => void;
  readOnly?: boolean;
}

/**
 * The upload slots for an application, driven by the configured document
 * requirements. Conditional slots appear only when their rule matches the
 * answers given — an owned vehicle asks for a libre, a rented one for the
 * rental agreement.
 */
export function DocumentSlots({
  requirements,
  attachments,
  formData,
  ownerType,
  ownerId,
  flagged = {},
  restrictToFlagged = false,
  onUploaded,
  readOnly,
}: Props) {
  const [busy, setBusy] = useState<string | null>(null);
  const [error, setError] = useState<string | null>(null);
  const resetRefs = useRef<Record<string, () => void>>({});

  const required = requirements.filter(
    (r) =>
      r.mode === 'ALWAYS' ||
      r.mode === 'OPTIONAL' ||
      (r.mode === 'CONDITIONAL' && conditionHolds(r.conditionExpression, formData)),
  );

  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, ownerId, 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>
      )}
      {required.map((requirement) => {
        const existing = attachments.find((a) => a.documentKey === requirement.key);
        const uploaded = Boolean(existing?.files?.length);
        const flagRemark = flagged[requirement.key];
        const locked = readOnly || (restrictToFlagged && !flagRemark);

        return (
          <Card
            key={requirement.id}
            withBorder
            padding="md"
            style={{
              borderColor: flagRemark
                ? 'var(--mantine-color-orange-5)'
                : 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">
                    {localized(requirement.name)}
                  </Text>
                  {requirement.mode === 'CONDITIONAL' && (
                    <Badge size="xs" variant="light" color="grape">
                      conditional
                    </Badge>
                  )}
                  {requirement.mode === 'OPTIONAL' && (
                    <Badge size="xs" variant="light" color="gray">
                      optional
                    </Badge>
                  )}
                  {uploaded && !flagRemark && (
                    <Badge size="xs" color="teal" leftSection={<IconCheck size={10} />}>
                      uploaded
                    </Badge>
                  )}
                </Group>
                {existing?.files?.[0] && (
                  <Text size="xs" c="dimmed" truncate>
                    {existing.files[0].originalName} ·{' '}
                    {(existing.files[0].sizeBytes / 1024).toFixed(0)} KB
                  </Text>
                )}
                {flagRemark && (
                  <Text size="xs" c="orange.7" mt={4}>
                    Officer: {flagRemark}
                  </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>
                )}
                {!locked && (
                  <FileButton
                    resetRef={(r) => {
                      if (r) resetRefs.current[requirement.key] = r;
                    }}
                    onChange={(file) => handle(requirement.key, file)}
                    accept={requirement.allowedMimeTypes?.join(',')}
                  >
                    {(props) => (
                      <Button
                        {...props}
                        size="xs"
                        variant={uploaded ? 'light' : 'filled'}
                        leftSection={
                          busy === requirement.key ? (
                            <Loader size={12} />
                          ) : (
                            <IconFileUpload size={14} />
                          )
                        }
                        disabled={busy === requirement.key}
                      >
                        {uploaded ? 'Replace' : 'Upload'}
                      </Button>
                    )}
                  </FileButton>
                )}
              </Group>
            </Group>
          </Card>
        );
      })}
    </Stack>
  );
}
