import React, { useMemo } from 'react';
import {
  Accordion,
  ActionIcon,
  Alert,
  Badge,
  Box,
  Group,
  Loader,
  Paper,
  Text,
  UnstyledButton,
} from '@mantine/core';
import {
  IconExternalLink,
  IconFileDescription,
  IconHash,
  IconInfoCircle,
  IconLink,
} from '@tabler/icons-react';
import { useNavigate } from 'react-router-dom';
import { useTranslation } from 'react-i18next';
import { useBacklinks } from '../queries/backlinks-query';
import type { BacklinkEntry } from '../queries/backlinks-query';
import classes from './linked-references-panel.module.css';

interface LinkedReferencesPanelProps {
  pageId: string;
}

/**
 * Panel displaying all backlinks pointing to the current page, grouped by link type.
 *
 * Placement: rendered inside the page sidebar or as a bottom-panel sticky below
 * the editor (caller decides). The component is self-contained and stateless.
 *
 * Permission awareness: the backend already filters source pages the user cannot
 * read. This component renders what it receives — no additional client-side
 * permission check needed.
 */
export function LinkedReferencesPanel({ pageId }: LinkedReferencesPanelProps) {
  const { t } = useTranslation();
  const navigate = useNavigate();
  const { data, isLoading, isError, refetch } = useBacklinks(pageId);

  const groups = useMemo(() => {
    if (!data) return [];
    const result: Array<{ key: string; label: string; icon: React.ReactNode; entries: BacklinkEntry[] }> = [];

    if (data.wikilinks.length > 0) {
      result.push({
        key: 'wikilinks',
        label: t('backlinks.group.wikilinks', 'Wikilinks'),
        icon: <IconLink size={14} />,
        entries: data.wikilinks,
      });
    }
    if (data.mentions.length > 0) {
      result.push({
        key: 'mentions',
        label: t('backlinks.group.mentions', 'Mentions'),
        icon: <IconHash size={14} />,
        entries: data.mentions,
      });
    }
    if (data.database_embeds.length > 0) {
      result.push({
        key: 'database_embeds',
        label: t('backlinks.group.embeds', 'Database embeds'),
        icon: <IconExternalLink size={14} />,
        entries: data.database_embeds,
      });
    }
    if (data.parentChild && data.parentChild.length > 0) {
      result.push({
        key: 'parent_child',
        label: t('backlinks.group.subpages', 'Sub-pages'),
        icon: <IconFileDescription size={14} />,
        entries: data.parentChild,
      });
    }
    return result;
  }, [data, t]);

  const handleNavigate = (entry: BacklinkEntry) => {
    if (entry.source.slugId) {
      // Navigate to the source page that links here.
      // The full path includes the space slug — fall back to page UUID if slugId only.
      const spacePart = entry.source.spaceSlug ? `/${entry.source.spaceSlug}` : '';
      navigate(`${spacePart}/page/${entry.source.slugId}`);
    }
  };

  if (isLoading) {
    return (
      <Box py="md" px="sm" data-testid="backlinks-loading">
        <Loader size="xs" />
      </Box>
    );
  }

  if (isError) {
    return (
      <Alert
        icon={<IconInfoCircle size={14} />}
        color="red"
        variant="light"
        py="xs"
        data-testid="backlinks-error"
      >
        <Group gap="xs">
          <Text size="xs">{t('backlinks.error', 'Could not load linked references.')}</Text>
          <UnstyledButton onClick={() => refetch()} style={{ textDecoration: 'underline' }}>
            <Text size="xs">{t('backlinks.retry', 'Retry')}</Text>
          </UnstyledButton>
        </Group>
      </Alert>
    );
  }

  if (!data || data.total === 0) {
    return (
      <Box py="md" px="sm" data-testid="backlinks-empty">
        <Text size="xs" c="dimmed">
          {t('backlinks.empty', 'No pages link here yet.')}
        </Text>
      </Box>
    );
  }

  return (
    <Box data-testid="backlinks-panel">
      <Group gap="xs" px="sm" py="xs" align="center">
        <Text size="xs" fw={600} tt="uppercase" c="dimmed">
          {t('backlinks.panel.title', 'Linked references')}
        </Text>
        <Badge size="xs" variant="light" color="gray">
          {data.total}
        </Badge>
      </Group>

      <Accordion
        multiple
        defaultValue={groups.map((g) => g.key)}
        variant="default"
        radius="md"
        chevronSize={14}
      >
        {groups.map((group) => (
          <Accordion.Item key={group.key} value={group.key}>
            <Accordion.Control icon={group.icon} py={4} px="sm">
              <Text size="xs" fw={500}>
                {group.label}
                <Badge size="xs" variant="outline" color="gray" ml={6}>
                  {group.entries.length}
                </Badge>
              </Text>
            </Accordion.Control>
            <Accordion.Panel pb={4}>
              {group.entries.map((entry) => (
                <BacklinkRow
                  key={`${entry.source.id}-${entry.linkType}`}
                  entry={entry}
                  onNavigate={handleNavigate}
                />
              ))}
            </Accordion.Panel>
          </Accordion.Item>
        ))}
      </Accordion>
    </Box>
  );
}

interface BacklinkRowProps {
  entry: BacklinkEntry;
  onNavigate: (entry: BacklinkEntry) => void;
}

function BacklinkRow({ entry, onNavigate }: BacklinkRowProps) {
  const { t } = useTranslation();

  return (
    <UnstyledButton
      onClick={() => onNavigate(entry)}
      className={classes.backlinkRow}
      data-testid={`backlink-row-${entry.source.id}`}
      px="sm"
      py={4}
      w="100%"
    >
      <Group gap="xs" wrap="nowrap" align="flex-start">
        <ActionIcon
          variant="subtle"
          component="div"
          color="gray"
          size="sm"
          mt={1}
          aria-hidden="true"
          flex="0 0 auto"
        >
          {entry.source.icon ?? <IconFileDescription size={14} stroke={1.5} />}
        </ActionIcon>
        <Box style={{ minWidth: 0, flex: 1 }}>
          <Text size="sm" fw={500} truncate>
            {entry.source.title ?? t('backlinks.untitled', 'Untitled')}
          </Text>
          {entry.source.spaceName && (
            <Text size="xs" c="dimmed" truncate>
              {entry.source.spaceName}
            </Text>
          )}
          {entry.contextExcerpt && (
            <Text
              size="xs"
              c="dimmed"
              lineClamp={2}
              mt={2}
              className={classes.excerpt}
            >
              {entry.contextExcerpt}
            </Text>
          )}
        </Box>
      </Group>
    </UnstyledButton>
  );
}

export default LinkedReferencesPanel;
