import { Anchor, Button, Group, Modal, Stack, Text, ThemeIcon } from '@mantine/core';
import { IconExternalLink, IconFileUnknown } from '@tabler/icons-react';

/** How a file is shown, once its type is known. */
type PreviewKind = 'image' | 'video' | 'audio' | 'embed' | 'unsupported';

const IMAGE_EXTENSIONS = ['jpg', 'jpeg', 'png', 'gif', 'webp', 'bmp', 'avif', 'svg'];
const VIDEO_EXTENSIONS = ['mp4', 'webm', 'ogv', 'mov', 'm4v'];
const AUDIO_EXTENSIONS = ['mp3', 'wav', 'ogg', 'm4a'];
const EMBED_EXTENSIONS = ['pdf', 'txt', 'csv', 'json', 'xml'];

/**
 * What the browser can actually render, decided from the mime type where there
 * is one and the URL's extension where there is not.
 *
 * Presigned links carry the storage key in the path, so the extension survives
 * even when the caller only has a URL. `image/tiff` and `image/heic` are
 * deliberately treated as images: Safari renders both, and everywhere else the
 * `<img>` fails visibly rather than an iframe offering a silent download.
 */
export function resolvePreviewKind(url: string, mimeType?: string | null): PreviewKind {
  const mime = mimeType?.toLowerCase() ?? '';
  if (mime.startsWith('image/')) return 'image';
  if (mime.startsWith('video/')) return 'video';
  if (mime.startsWith('audio/')) return 'audio';
  if (mime === 'application/pdf' || mime.startsWith('text/')) return 'embed';
  // Word, Excel and the rest: nothing renders them inline, and an iframe would
  // quietly start a download instead of previewing anything.
  if (mime) return 'unsupported';

  const extension = extensionOf(url);
  if (!extension) return 'embed';
  if (IMAGE_EXTENSIONS.includes(extension)) return 'image';
  if (VIDEO_EXTENSIONS.includes(extension)) return 'video';
  if (AUDIO_EXTENSIONS.includes(extension)) return 'audio';
  if (EMBED_EXTENSIONS.includes(extension)) return 'embed';
  return 'unsupported';
}

function extensionOf(url: string): string | null {
  // Presigned URLs carry a query string; the path is the part with the name.
  const path = url.split(/[?#]/)[0];
  const name = path.slice(path.lastIndexOf('/') + 1);
  const dot = name.lastIndexOf('.');
  return dot > 0 ? name.slice(dot + 1).toLowerCase() : null;
}

/**
 * The one place a stored file gets opened anywhere in the app.
 *
 * Never `window.open` / `target="_blank"` a file that can be shown here —
 * route it through this modal so the reviewer never loses their place to a new
 * tab. What a slot accepts is configuration now, so this had to grow past the
 * PDF it started as: a national ID arrives as a photograph, evidence arrives
 * as video, and an academic record sometimes arrives as the Word file its
 * institution issued. The last of those genuinely cannot be rendered by a
 * browser, so it gets an honest panel and a link out rather than an iframe
 * that silently downloads it.
 */
export function FilePreviewModal({
  opened,
  onClose,
  url,
  title = 'Document',
  mimeType,
  /** Overrides the detected kind — for a blob URL with no extension. */
  kind,
  labels,
}: {
  opened: boolean;
  onClose: () => void;
  url: string;
  title?: string;
  mimeType?: string | null;
  kind?: PreviewKind;
  /** Supplied by the app so this stays out of the i18n bundles. */
  labels?: { unsupported?: string; openInNewTab?: string; close?: string };
}) {
  const resolved = kind ?? resolvePreviewKind(url, mimeType);

  return (
    <Modal
      opened={opened}
      onClose={onClose}
      title={title}
      size="80%"
      centered
      trapFocus
      returnFocus
      styles={
        resolved === 'image' || resolved === 'video'
          ? // A photograph on a white sheet loses its own edges; the dark mat
            // is what tells the eye where the file ends.
            { body: { background: 'var(--mantine-color-dark-8)', padding: 0 } }
          : undefined
      }
    >
      {url && resolved === 'image' && (
        <img
          src={url}
          alt={title}
          style={{
            display: 'block',
            margin: '0 auto',
            maxWidth: '100%',
            maxHeight: '85vh',
            objectFit: 'contain',
          }}
        />
      )}

      {url && resolved === 'video' && (
        // Controls only, no autoplay: a review screen that starts making noise
        // on open is a review screen people mute and then miss the audio on.
        <video
          src={url}
          controls
          preload="metadata"
          style={{ display: 'block', width: '100%', maxHeight: '85vh' }}
        >
          <track kind="captions" />
        </video>
      )}

      {url && resolved === 'audio' && (
        <Stack p="md">
          <audio src={url} controls style={{ width: '100%' }}>
            <track kind="captions" />
          </audio>
        </Stack>
      )}

      {url && resolved === 'embed' && (
        <iframe
          src={url}
          title={title}
          style={{ width: '100%', height: '85vh', border: 'none' }}
        />
      )}

      {url && resolved === 'unsupported' && (
        <Stack align="center" gap="sm" py="xl">
          <ThemeIcon size={56} radius="xl" variant="light" color="gray">
            <IconFileUnknown size={28} stroke={1.5} />
          </ThemeIcon>
          <Text fz="sm" c="dimmed" ta="center" maw={420}>
            {labels?.unsupported ??
              'This file type cannot be shown here. Open it in a new tab to download it.'}
          </Text>
          <Group>
            <Button
              component="a"
              href={url}
              target="_blank"
              rel="noopener noreferrer"
              variant="light"
              leftSection={<IconExternalLink size={15} />}
            >
              {labels?.openInNewTab ?? 'Open in a new tab'}
            </Button>
            <Anchor component="button" type="button" fz="sm" onClick={onClose}>
              {labels?.close ?? 'Close'}
            </Anchor>
          </Group>
        </Stack>
      )}
    </Modal>
  );
}
