/**
 * T074: Markdown rendering configuration and wikilink handling
 * T019-T028: Wikilink preview tooltips with HoverCard
 * T039-T040: Heading ID generation for Table of Contents
 */
import React, { useState } from 'react';
import type { Components } from 'react-markdown';
import { HoverCard, HoverCardTrigger, HoverCardContent } from '@/components/ui/hover-card';
import { getNote, searchNotes } from '@/services/api';

export interface WikilinkComponentProps {
  linkText: string;
  resolved: boolean;
  onClick?: (linkText: string) => void;
}

/**
 * T019: Preview cache for wikilink tooltips
 */
const previewCache = new Map<string, string>();

/**
 * T039-T040: Track slugs to handle duplicates
 */
const slugCache = new Map<string, number>();

/**
 * T040: Slugify heading text to create valid HTML IDs
 * Handles duplicates by appending -2, -3, etc.
 */
function slugify(text: string): string {
  // Basic slugification
  const baseSlug = text
    .toLowerCase()
    .replace(/\s+/g, '-')
    .replace(/[^\w-]/g, '');

  // T050: Handle duplicates
  const count = slugCache.get(baseSlug) || 0;
  slugCache.set(baseSlug, count + 1);

  if (count === 0) {
    return baseSlug;
  }

  return `${baseSlug}-${count + 1}`;
}

/**
 * Reset slug cache (call when rendering a new document)
 */
export function resetSlugCache(): void {
  slugCache.clear();
}

/**
 * T021-T026: Wikilink preview component with HoverCard
 */
function WikilinkPreview({
  linkText,
  children,
  onClick
}: {
  linkText: string;
  children: React.ReactNode;
  onClick?: () => void;
}) {
  const [preview, setPreview] = useState<string | null>(null);
  const [isLoading, setIsLoading] = useState(false);
  const [isBroken, setIsBroken] = useState(false);
  const [isOpen, setIsOpen] = useState(false);

  // T023: Fetch preview when hover card opens
  React.useEffect(() => {
    if (!isOpen) return;

    // T028: Check cache first
    if (previewCache.has(linkText)) {
      setPreview(previewCache.get(linkText)!);
      setIsLoading(false);
      setIsBroken(false);
      return;
    }

    // Start loading
    setIsLoading(true);

    const fetchPreview = async () => {
      try {
        // First search for the note by title/content to find its actual path
        const searchResults = await searchNotes(linkText);

        if (searchResults.length === 0) {
          // No results found - broken link
          setIsBroken(true);
          setPreview(null);
          setIsLoading(false);
          return;
        }

        // Get the first matching note
        const notePath = searchResults[0].note_path;
        const note = await getNote(notePath);

        // T024: Extract first 150 characters from note body
        const previewText = note.body
          .replace(/\[\[([^\]]+)\]\]/g, '$1') // Remove wikilinks
          .replace(/[#*_~`]/g, '') // Remove markdown formatting
          .trim()
          .slice(0, 150);
        const finalPreview = previewText.length < note.body.length
          ? `${previewText}...`
          : previewText;

        // T019: Cache the preview
        previewCache.set(linkText, finalPreview);
        setPreview(finalPreview);
        setIsBroken(false);
      } catch (error) {
        // T026: Handle broken wikilinks
        setIsBroken(true);
        setPreview(null);
      } finally {
        setIsLoading(false);
      }
    };

    fetchPreview();
  }, [isOpen, linkText]);

  return (
    <HoverCard openDelay={500} closeDelay={100} onOpenChange={setIsOpen}>
      <HoverCardTrigger asChild>
        <span onClick={onClick}>
          {children}
        </span>
      </HoverCardTrigger>
      <HoverCardContent className="w-80">
        {isLoading ? (
          // T025: Loading skeleton
          <div className="space-y-2">
            <div className="h-4 bg-muted animate-pulse rounded" />
            <div className="h-4 bg-muted animate-pulse rounded w-5/6" />
            <div className="h-4 bg-muted animate-pulse rounded w-4/6" />
          </div>
        ) : isBroken ? (
          // T026: Broken link message
          <div className="text-sm text-destructive">
            Note not found
          </div>
        ) : preview ? (
          <div className="text-sm text-muted-foreground">
            {preview}
          </div>
        ) : null}
      </HoverCardContent>
    </HoverCard>
  );
}

/**
 * Custom renderer for wikilinks in markdown
 */
export function createWikilinkComponent(
  onWikilinkClick?: (linkText: string) => void
): Components {
  return {
    // Style links
    a: ({ href, children, ...props }) => {
      if (href?.startsWith('wikilink:')) {
        const linkText = decodeURIComponent(href.replace('wikilink:', ''));
        return (
          <WikilinkPreview
            linkText={linkText}
            onClick={(e?: React.MouseEvent) => {
              e?.preventDefault();
              onWikilinkClick?.(linkText);
            }}
          >
            <span
              className="wikilink cursor-pointer text-primary hover:underline font-medium text-blue-500 dark:text-blue-400"
              onClick={(e) => {
                e.preventDefault();
                onWikilinkClick?.(linkText);
              }}
              role="link"
              tabIndex={0}
              onKeyDown={(e) => {
                if (e.key === 'Enter' || e.key === ' ') {
                  e.preventDefault();
                  onWikilinkClick?.(linkText);
                }
              }}
              title={`Go to ${linkText}`}
            >
              {children}
            </span>
          </WikilinkPreview>
        );
      }

      const isExternal = href?.startsWith('http');
      return (
        <a
          href={href}
          className="text-primary hover:underline"
          target={isExternal ? '_blank' : undefined}
          rel={isExternal ? 'noopener noreferrer' : undefined}
          {...props}
        >
          {children}
        </a>
      );
    },

    // T039: Style headings with ID generation for TOC
    h1: ({ children, ...props }) => {
      const text = typeof children === 'string' ? children : '';
      const id = text ? slugify(text) : undefined;
      return (
        <h1 id={id} className="text-3xl font-bold mt-6 mb-4" {...props}>
          {children}
        </h1>
      );
    },
    h2: ({ children, ...props }) => {
      const text = typeof children === 'string' ? children : '';
      const id = text ? slugify(text) : undefined;
      return (
        <h2 id={id} className="text-2xl font-semibold mt-5 mb-3" {...props}>
          {children}
        </h2>
      );
    },
    h3: ({ children, ...props }) => {
      const text = typeof children === 'string' ? children : '';
      const id = text ? slugify(text) : undefined;
      return (
        <h3 id={id} className="text-xl font-semibold mt-4 mb-2" {...props}>
          {children}
        </h3>
      );
    },

    // Style lists
    ul: ({ children, ...props }) => (
      <ul className="list-disc list-inside my-2 space-y-1" {...props}>
        {children}
      </ul>
    ),
    ol: ({ children, ...props }) => (
      <ol className="list-decimal list-inside my-2 space-y-1" {...props}>
        {children}
      </ol>
    ),

    // Style blockquotes
    blockquote: ({ children, ...props }) => (
      <blockquote className="border-l-4 border-muted-foreground pl-4 italic my-4" {...props}>
        {children}
      </blockquote>
    ),

    // Style tables
    table: ({ children, ...props }) => (
      <div className="overflow-x-auto my-4">
        <table className="min-w-full border-collapse border border-border" {...props}>
          {children}
        </table>
      </div>
    ),
    th: ({ children, ...props }) => (
      <th className="border border-border px-4 py-2 bg-muted font-semibold text-left" {...props}>
        {children}
      </th>
    ),
    td: ({ children, ...props }) => (
      <td className="border border-border px-4 py-2" {...props}>
        {children}
      </td>
    ),
  };
}

/**
 * Render broken wikilinks with distinct styling
 */
export function renderBrokenWikilink(
  linkText: string,
  onCreate?: () => void
): React.ReactElement {
  return (
    <span
      className="wikilink-broken text-destructive border-b border-dashed border-destructive cursor-pointer hover:bg-destructive/10"
      onClick={onCreate}
      role="link"
      tabIndex={0}
      title={`Note "${linkText}" not found. Click to create.`}
    >
      [[{linkText}]]
    </span>
  );
}

