import type { ReactNode } from "react";

const SAFE_HTTP_URL = /^https?:\/\//i;

type InlineToken =
    | { type: "text"; value: string }
    | { type: "link"; label: string; href: string };

function parseLinks(text: string): InlineToken[] {
    const tokens: InlineToken[] = [];
    const pattern = /\[([^\]]+)\]\(([^)\s]+)\)/g;
    let lastIndex = 0;
    let match: RegExpExecArray | null;

    while ((match = pattern.exec(text)) !== null) {
        if (match.index > lastIndex) {
            tokens.push({ type: "text", value: text.slice(lastIndex, match.index) });
        }

        const label = match[1] ?? "";
        const href = match[2] ?? "";
        if (SAFE_HTTP_URL.test(href)) {
            tokens.push({ type: "link", label, href });
        } else {
            tokens.push({ type: "text", value: match[0] });
        }

        lastIndex = pattern.lastIndex;
    }

    if (lastIndex < text.length) {
        tokens.push({ type: "text", value: text.slice(lastIndex) });
    }

    return tokens;
}

function renderEmphasis(text: string, keyPrefix: string): ReactNode[] {
    const nodes: ReactNode[] = [];
    const pattern = /(\*\*\*[^*]+?\*\*\*|\*\*[^*]+?\*\*|\*[^*]+?\*)/g;
    let lastIndex = 0;
    let match: RegExpExecArray | null;
    let idx = 0;

    while ((match = pattern.exec(text)) !== null) {
        if (match.index > lastIndex) {
            nodes.push(text.slice(lastIndex, match.index));
        }

        const token = match[0];
        const key = `${keyPrefix}-em-${idx++}`;
        if (token.startsWith("***")) {
            nodes.push(
                <strong key={key}>
                    <em>{token.slice(3, -3)}</em>
                </strong>
            );
        } else if (token.startsWith("**")) {
            nodes.push(<strong key={key}>{token.slice(2, -2)}</strong>);
        } else {
            nodes.push(<em key={key}>{token.slice(1, -1)}</em>);
        }

        lastIndex = pattern.lastIndex;
    }

    if (lastIndex < text.length) {
        nodes.push(text.slice(lastIndex));
    }

    return nodes;
}

export function renderInlineMarkdown(text: string): ReactNode[] {
    const withLines = text.split("\n");
    const nodes: ReactNode[] = [];

    withLines.forEach((line, lineIndex) => {
        const tokens = parseLinks(line);
        tokens.forEach((token, tokenIndex) => {
            const keyBase = `ln-${lineIndex}-tok-${tokenIndex}`;
            if (token.type === "text") {
                nodes.push(...renderEmphasis(token.value, keyBase));
                return;
            }

            nodes.push(
                <a
                    key={`${keyBase}-link`}
                    href={token.href}
                    target="_blank"
                    rel="noopener noreferrer"
                    style={{ color: "inherit", textDecoration: "underline" }}
                >
                    {renderEmphasis(token.label, `${keyBase}-label`)}
                </a>
            );
        });

        if (lineIndex < withLines.length - 1) {
            nodes.push(<br key={`ln-${lineIndex}-br`} />);
        }
    });

    return nodes;
}
