"use client";

import Link from "next/link";
import { Fragment, ReactNode } from "react";
import { cn } from "@/lib/utils";
import {
  buildPostLinkPath,
  POST_LINK_TOKEN_REGEX,
  PostLinkKind,
} from "@/lib/postLinkCaption";

const TOKEN_REGEX =
  /(\s+|#[\w\u0600-\u06FF\u0750-\u077F\u08A0-\u08FF]+|@[\w.\u0600-\u06FF]+)/g;

type CaptionWithMentionsProps = {
  text: string;
  fullText?: string;
  className?: string;
  mentionClassName?: string;
  hashtagClassName?: string;
  packageClassName?: string;
  linkClassName?: string;
};

function resolveTrailingPartialMention(displayText: string, fullText: string) {
  const atIndex = displayText.lastIndexOf("@");
  if (atIndex === -1) return null;

  const partial = displayText.slice(atIndex);
  if (!/^@[\w.]*$/.test(partial)) return null;

  const fullMention = fullText.slice(atIndex).match(/^@[\w.]+/);
  if (!fullMention) return null;

  const full = fullMention[0];
  if (full.length <= partial.length) return null;

  return {
    prefix: displayText.slice(0, atIndex),
    partial,
    username: full.slice(1),
  };
}

function renderTokens(
  text: string,
  mentionClassName: string,
  hashtagClassName: string,
  keyPrefix: string
) {
  const parts = text.split(TOKEN_REGEX).filter((part) => part.length > 0);

  return parts.map((part, index) => {
    if (part.startsWith("@") && part.length > 1) {
      const username = part.slice(1);
      return (
        <Link
          key={`${keyPrefix}-m-${index}`}
          href={`/users/${encodeURIComponent(username)}`}
          className={mentionClassName}
          onClick={(e) => e.stopPropagation()}
        >
          {part}
        </Link>
      );
    }
    if (part.startsWith("#") && part.length > 1) {
      return (
        <Link
          key={`${keyPrefix}-h-${index}`}
          href={`/?hashtag=${encodeURIComponent(part.slice(1))}`}
          className={hashtagClassName}
          onClick={(e) => e.stopPropagation()}
        >
          {part}
        </Link>
      );
    }
    return <Fragment key={`${keyPrefix}-t-${index}`}>{part}</Fragment>;
  });
}

function renderRichCaption(
  text: string,
  mentionClassName: string,
  hashtagClassName: string,
  linkClassName: string,
  keyPrefix: string
): ReactNode[] {
  const nodes: ReactNode[] = [];
  let lastIndex = 0;
  const re = new RegExp(POST_LINK_TOKEN_REGEX.source, "gi");
  let match: RegExpExecArray | null;

  while ((match = re.exec(text)) !== null) {
    if (match.index > lastIndex) {
      nodes.push(
        ...renderTokens(
          text.slice(lastIndex, match.index),
          mentionClassName,
          hashtagClassName,
          `${keyPrefix}-pre-${lastIndex}`
        )
      );
    }

    const kind = match[1] as PostLinkKind;
    const id = match[2];
    const title = match[3];
    nodes.push(
      <Link
        key={`${keyPrefix}-link-${match.index}`}
        href={buildPostLinkPath(kind, id, title)}
        className={cn(linkClassName, "inline")}
        onClick={(e) => e.stopPropagation()}
      >
        {`${title.trim()}`}
      </Link>
    );
    lastIndex = match.index + match[0].length;
  }

  if (lastIndex < text.length) {
    nodes.push(
      ...renderTokens(
        text.slice(lastIndex),
        mentionClassName,
        hashtagClassName,
        `${keyPrefix}-tail-${lastIndex}`
      )
    );
  }

  return nodes;
}

export default function CaptionWithMentions({
  text,
  fullText,
  className,
  mentionClassName = "font-bold text-blue-400 hover:underline",
  hashtagClassName = "font-bold text-blue-500",
  packageClassName = "font-bold text-[#FF107D] hover:underline",
  linkClassName,
}: CaptionWithMentionsProps) {
  if (!text) return null;

  const resolvedLinkClass = linkClassName ?? packageClassName;
  const source = fullText ?? text;
  const trailing =
    fullText && fullText !== text
      ? resolveTrailingPartialMention(text, source)
      : null;

  const visibleText = trailing ? trailing.prefix : text;

  const lines = visibleText.split("\n");

  return (
    <span className={cn(className, "whitespace-pre-wrap")}>
      {lines.map((line, lineIndex) => (
        <Fragment key={`line-${lineIndex}`}>
          {lineIndex > 0 ? <br /> : null}
          {renderRichCaption(
            line,
            mentionClassName,
            hashtagClassName,
            resolvedLinkClass,
            `main-${lineIndex}`
          )}
        </Fragment>
      ))}
      {trailing ? (
        <Link
          href={`/users/${encodeURIComponent(trailing.username)}`}
          className={mentionClassName}
          onClick={(e) => e.stopPropagation()}
        >
          {trailing.partial}
        </Link>
      ) : null}
    </span>
  );
}
