import type { ChatMessagePart } from './types';

const LINK_CARD_LINE_PATTERN = /^\s*\[\[link-card:(.+?)\]\]\s*$/i;
const CARD_LINE_PATTERN = /^\s*\[\[card:(.+?)\]\]\s*$/i;
const PROMPT_LINE_PATTERN = /^\s*\[\[prompt:(.+?)\]\]\s*$/i;
const STANDALONE_MARKDOWN_LINK_LINE_PATTERN = /^\s*(?:[-*+]\s+|\d+\.\s+)?\[([^\]]+)\]\((.+)\)\s*$/;
const STANDALONE_URL_LINE_PATTERN = /^\s*(?:[-*+]\s+|\d+\.\s+)?((?:https?:\/\/|\/)[^\s<>)\]]+)\s*$/i;
const CARD_BLOCK_START_PATTERN = /^\s*\[\[card:\s*$/i;
const PROMPT_BLOCK_START_PATTERN = /^\s*\[\[prompt:\s*$/i;
const PROMPT_BLOCK_END_PATTERN = /^\s*\]\]\s*$/;
const PROMPT_CODE_BLOCK_START_PATTERN = /^\s*```(?:json|prompt)(?:\s+prompt)?\s*$/i;
const CODE_BLOCK_END_PATTERN = /^\s*```\s*$/;
const CODE_FENCE_TOGGLE_PATTERN = /^\s*```/;
const ATTACHMENT_SECTION_TITLE_PATTERN = /^\s*첨부\s*파일\s*:?\s*$/i;
const ATTACHMENT_ENTRY_PATTERN = /^\s*-\s+(.+?)\s*:\s*(.+?)\s*$/;
const RESOURCE_PATH_PREFIXES = ['/api/chat/resources/', '/public/.codex_chat/', '/.codex_chat/'] as const;
const CHAT_API_RESOURCE_MARKER = '/api/chat/resources/';
const CHAT_DOT_CODEX_MARKER = '/.codex_chat/';
const CHAT_PUBLIC_DOT_CODEX_MARKER = '/public/.codex_chat/';
const RESOURCE_MANAGER_PREVIEW_MARKER = '/api/resource-manager/preview/';
const RESOURCE_MANAGER_ROOT_MARKER = 'resource/';

function buildCanonicalChatApiResourcePath(relativePath: string) {
  const normalizedRelativePath = normalizeText(relativePath).replace(/^\/+/, '');

  if (!normalizedRelativePath) {
    return '';
  }

  if (normalizedRelativePath.startsWith('.codex_chat/')) {
    return `${CHAT_API_RESOURCE_MARKER}${normalizedRelativePath}`;
  }

  return `${CHAT_API_RESOURCE_MARKER}.codex_chat/${normalizedRelativePath}`;
}
type PromptPart = Extract<ChatMessagePart, { type: 'prompt' }>;
type PromptOption = PromptPart['options'][number];
type PromptPreview = NonNullable<PromptOption['preview']>;
type PromptStep = NonNullable<PromptPart['steps']>[number];
type PreviewCardPart = Extract<ChatMessagePart, { type: 'preview_card' }>;

function normalizeText(value: unknown) {
  return String(value ?? '').trim();
}

function normalizePromptPreviewType(typeValue: unknown, url: string, content: string, editableMode = false) {
  const normalizedType = normalizeText(typeValue).toLowerCase();

  if (
    normalizedType === 'image' ||
    normalizedType === 'md' ||
    normalizedType === 'markdown' ||
    normalizedType === 'html' ||
    normalizedType === 'resource' ||
    normalizedType === 'editable' ||
    normalizedType === 'editor' ||
    normalizedType === 'code'
  ) {
    if (normalizedType === 'editable' || normalizedType === 'editor' || normalizedType === 'code') {
      return 'editable';
    }

    return normalizedType;
  }

  if (normalizedType === 'text' || normalizedType === 'plain' || normalizedType === 'txt') {
    return editableMode ? 'editable' : 'markdown';
  }

  if (normalizedType === 'htm') {
    return 'html';
  }

  if (editableMode && (url || content)) {
    return 'editable';
  }

  if (editableMode) {
    return null;
  }

  const normalizedContent = String(content ?? '').trim();
  const normalizedUrl = normalizeUrl(url).toLowerCase();

  if (normalizedUrl.endsWith('.md') || normalizedUrl.endsWith('.markdown')) {
    return 'markdown';
  }

  if (normalizedUrl.endsWith('.html') || normalizedUrl.endsWith('.htm')) {
    return 'html';
  }

  if (!normalizedContent) {
    return null;
  }

  if (/<(?:!doctype\s+html|html|head|body|main|section|article|div)\b/i.test(normalizedContent)) {
    return 'html';
  }

  if (/^#{1,6}\s|^\s*[-*+]\s+|^\s*\d+\.\s+|^\s*>\s+|\[[^\]]+\]\([^)]+\)/m.test(normalizedContent)) {
    return 'markdown';
  }

  return 'resource';
}

function unwrapMarkdownLinkTarget(value: string) {
  const normalized = normalizeText(value);

  if (!normalized) {
    return '';
  }

  const matched = normalized.match(/^<([\s\S]+)>$/);
  return matched?.[1]?.trim() ?? normalized;
}

function normalizeResourceManagerPathSegment(segment: string) {
  const normalized = normalizeText(segment);

  if (!normalized) {
    return '';
  }

  try {
    return encodeURIComponent(decodeURIComponent(normalized));
  } catch {
    return encodeURIComponent(normalized);
  }
}

function normalizeUrlFragmentValue(value: string) {
  const normalized = normalizeText(value).replace(/^#+/, '');

  if (!normalized) {
    return '';
  }

  try {
    return decodeURIComponent(normalized);
  } catch {
    return normalized;
  }
}

function decodeRepeatedly(value: string, maxIterations = 3) {
  let current = value;

  for (let index = 0; index < maxIterations; index += 1) {
    try {
      const decoded = decodeURIComponent(current);

      if (!decoded || decoded === current) {
        break;
      }

      current = decoded;
    } catch {
      break;
    }
  }

  return current;
}

function normalizePreviewPathHash(value: string) {
  const normalized = normalizeText(value);

  if (!normalized) {
    return '';
  }

  const isAbsoluteUrl = /^[a-z][a-z0-9+.-]*:\/\//i.test(normalized);
  const isRootRelative = normalized.startsWith('/');

  try {
    const parsed = new URL(normalized, 'https://local.invalid');
    const segments = parsed.pathname.split('/');
    const lastSegment = segments.at(-1) ?? '';
    const decodedLastSegment = decodeRepeatedly(lastSegment);
    const hashIndex = decodedLastSegment.lastIndexOf('#');

    if (hashIndex <= 0 || parsed.hash) {
      return normalized;
    }

    const fileName = decodedLastSegment.slice(0, hashIndex).trim();
    const fragment = normalizeUrlFragmentValue(decodedLastSegment.slice(hashIndex + 1));

    if (!fileName || !fragment || !/\.[a-z0-9]{1,16}$/i.test(fileName)) {
      return normalized;
    }

    segments[segments.length - 1] = encodeURIComponent(fileName);
    parsed.pathname = segments.join('/');
    parsed.hash = fragment;

    if (isAbsoluteUrl) {
      return parsed.toString();
    }

    const pathWithQueryAndHash = `${parsed.pathname}${parsed.search}${parsed.hash}`;
    return isRootRelative ? pathWithQueryAndHash : pathWithQueryAndHash.replace(/^\/+/, '');
  } catch {
    return normalized;
  }
}

function buildResourceManagerPreviewUrl(value: string) {
  const normalized = normalizePreviewPathHash(normalizeText(value).replace(/\\/g, '/'));
  const hashIndex = normalized.indexOf('#');
  const hash = hashIndex >= 0 ? normalizeUrlFragmentValue(normalized.slice(hashIndex + 1)) : '';
  const normalizedPath = hashIndex >= 0 ? normalized.slice(0, hashIndex) : normalized;
  const matchedResourcePath = normalizedPath.match(/(?:^|\/)(resource\/.+)$/i)?.[1];
  const resourcePath = normalizeText(matchedResourcePath).replace(/^\/+/, '');

  if (!resourcePath) {
    return '';
  }

  const relativePath = resourcePath.slice(RESOURCE_MANAGER_ROOT_MARKER.length).replace(/^\/+/, '');

  if (!relativePath) {
    return '';
  }

  const encodedPath = relativePath
    .split('/')
    .filter(Boolean)
    .map((segment) => normalizeResourceManagerPathSegment(segment))
    .join('/');

  return encodedPath ? `${RESOURCE_MANAGER_PREVIEW_MARKER}${encodedPath}${hash ? `#${hash}` : ''}` : '';
}

function extractKnownPreviewPath(value: string) {
  const normalized = normalizeText(value);

  if (!normalized) {
    return '';
  }

  try {
    const parsed = new URL(normalized, 'https://local.invalid');
    const pathname = `${parsed.pathname || ''}${parsed.search || ''}${parsed.hash || ''}`;

    if (pathname.startsWith(CHAT_API_RESOURCE_MARKER) || pathname.startsWith(RESOURCE_MANAGER_PREVIEW_MARKER)) {
      return normalizePreviewPathHash(pathname);
    }

    if (pathname.startsWith(CHAT_PUBLIC_DOT_CODEX_MARKER)) {
      return buildCanonicalChatApiResourcePath(pathname.slice(CHAT_PUBLIC_DOT_CODEX_MARKER.length));
    }

    if (pathname.startsWith(CHAT_DOT_CODEX_MARKER)) {
      return buildCanonicalChatApiResourcePath(pathname.slice(CHAT_DOT_CODEX_MARKER.length));
    }

    return normalized;
  } catch {
    return '';
  }
}

function normalizeUrl(value: string) {
  const normalized = unwrapMarkdownLinkTarget(value);

  if (!normalized) {
    return '';
  }

  const knownPreviewPath = extractKnownPreviewPath(normalized);

  if (knownPreviewPath) {
    return knownPreviewPath;
  }

  const malformedResourceMatch = normalized.match(/^https?:\/(api\/chat\/resources\/.+)$/i);
  if (malformedResourceMatch?.[1]) {
    return `/${malformedResourceMatch[1]}`;
  }

  const apiMarkerIndex = normalized.lastIndexOf(CHAT_API_RESOURCE_MARKER);
  if (apiMarkerIndex >= 0) {
    const apiPath = normalized.slice(apiMarkerIndex);
    const dotCodexIndex = apiPath.indexOf(CHAT_DOT_CODEX_MARKER);
    return dotCodexIndex >= 0
      ? buildCanonicalChatApiResourcePath(apiPath.slice(dotCodexIndex + 1))
      : apiPath;
  }

  const publicDotCodexIndex = normalized.lastIndexOf(CHAT_PUBLIC_DOT_CODEX_MARKER);
  if (publicDotCodexIndex >= 0) {
    return buildCanonicalChatApiResourcePath(normalized.slice(publicDotCodexIndex + 8));
  }

  const dotCodexIndex = normalized.lastIndexOf(CHAT_DOT_CODEX_MARKER);
  if (dotCodexIndex >= 0) {
    return buildCanonicalChatApiResourcePath(normalized.slice(dotCodexIndex + 1));
  }

  if (normalized === 'resource' || normalized === '/resource' || normalized.startsWith('resource/') || normalized.includes('/resource/')) {
    const resourceManagerPreviewUrl = buildResourceManagerPreviewUrl(normalized);

    if (resourceManagerPreviewUrl) {
      return resourceManagerPreviewUrl;
    }
  }

  if (/^(?:https?:\/\/|\/)/i.test(normalized)) {
    return normalized;
  }

  return '';
}

function hasKnownFileExtension(url: string) {
  const pathname = url.split('?')[0] ?? '';
  return /\.[a-z0-9]{1,8}$/i.test(pathname);
}

function isStructuredLinkCardCandidate(url: string) {
  const normalized = normalizeUrl(url);

  if (!normalized) {
    return false;
  }

  if (isInternalResourceUrl(normalized)) {
    return false;
  }

  return /^https?:\/\//i.test(normalized) && !hasKnownFileExtension(normalized);
}

function buildFallbackLinkTitle(url: string) {
  try {
    const parsed = new URL(url, 'https://local.invalid');
    const lastSegment = parsed.pathname.split('/').filter(Boolean).at(-1)?.trim();
    return lastSegment || parsed.hostname || normalizeText(url);
  } catch {
    return normalizeText(url);
  }
}

function normalizeStandaloneTitle(value: string) {
  return value
    .replace(/^\s*(?:[-*+]\s+|\d+\.\s+)?/, '')
    .replace(/[`'"]+/g, '')
    .replace(/\s+/g, ' ')
    .trim();
}

function resolveStandaloneLinkTitle(keptLines: string[], url: string) {
  for (let index = keptLines.length - 1; index >= 0; index -= 1) {
    const candidate = normalizeStandaloneTitle(keptLines[index] ?? '');

    if (candidate) {
      return candidate;
    }
  }

  return buildFallbackLinkTitle(url);
}

function normalizePromptPreview(value: unknown): PromptPreview | null {
  if (!value || typeof value !== 'object' || Array.isArray(value)) {
    return null;
  }

  const record = value as Record<string, unknown>;
  const url = normalizeUrl(normalizeText(record.url));
  const content = String(record.content ?? '').trim() || null;
  const alt = normalizeText(record.alt) || null;
  const title = normalizeText(record.title) || null;
  const editable = record.editable === true;
  const type = normalizePromptPreviewType(record.type, url, content || '', editable);

  if (!type) {
    return null;
  }

  if (type === 'image' || (type === 'resource' && !editable)) {
    if (!url) {
      return null;
    }
  } else if (type !== 'editable' && !content && !url) {
    return null;
  }

  if (type === 'editable' && !content && !url) {
    return null;
  }

  return {
    type,
    url: url || null,
    content,
    alt,
    title,
    editable: editable || type === 'editable' ? true : null,
  };
}

function buildPreviewCardPart(rawBody: string): PreviewCardPart | null {
  const trimmed = rawBody.trim();

  if (!trimmed) {
    return null;
  }

  let parsed: unknown;

  try {
    parsed = JSON.parse(trimmed);
  } catch {
    return null;
  }

  if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed)) {
    return null;
  }

  const record = parsed as Record<string, unknown>;
  const title = normalizeText(record.title) || normalizeText(record.label);
  const preview =
    normalizePromptPreview(record.preview) ||
    normalizePromptPreview({
      type: record.type,
      url: record.url,
      content: record.content,
      alt: record.alt,
      title: record.previewTitle ?? record.title,
    });

  if (!title || !preview) {
    return null;
  }

  return {
    type: 'preview_card',
    title,
    description: normalizeText(record.description) || null,
    kindLabel: normalizeText(record.kindLabel) || null,
    actionLabel: normalizeText(record.actionLabel) || null,
    preview,
  };
}

function isPromptOption(value: PromptOption | null): value is PromptOption {
  return value != null;
}

function normalizePromptOption(value: unknown): PromptOption | null {
  if (!value || typeof value !== 'object' || Array.isArray(value)) {
    return null;
  }

  const record = value as Record<string, unknown>;
  const optionValue = normalizeText(record.value);
  const label = normalizeText(record.label);

  if (!optionValue || !label) {
    return null;
  }

  return {
    value: optionValue,
    label,
    description: normalizeText(record.description) || null,
    preview: normalizePromptPreview(record.preview),
  };
}

function normalizePromptSelectedValues(value: unknown) {
  return [
    ...(Array.isArray(value) ? value : []),
  ]
    .map((item) => normalizeText(item))
    .filter(Boolean)
    .filter((item, index, array) => array.indexOf(item) === index);
}

function normalizePromptAttachment(value: unknown) {
  if (!value || typeof value !== 'object' || Array.isArray(value)) {
    return null;
  }

  const record = value as Record<string, unknown>;
  const id = normalizeText(record.id);
  const name = normalizeText(record.name);
  const path = normalizeText(record.path);
  const publicUrl = normalizeText(record.publicUrl);
  const size = Number(record.size);
  const mimeType = normalizeText(record.mimeType);

  if (!id || !name || !path || !publicUrl || !Number.isFinite(size) || size < 0 || !mimeType) {
    return null;
  }

  return {
    id,
    name,
    path,
    publicUrl,
    size,
    mimeType,
  };
}

function normalizePromptAttachments(value: unknown) {
  if (!Array.isArray(value)) {
    return [];
  }

  const seen = new Set<string>();

  return value
    .map((item) => normalizePromptAttachment(item))
    .filter((item): item is NonNullable<PromptPart['attachments']>[number] => Boolean(item))
    .filter((item) => {
      if (seen.has(item.id)) {
        return false;
      }

      seen.add(item.id);
      return true;
    });
}

function normalizePromptSteps(value: unknown): PromptStep[] {
  if (!Array.isArray(value)) {
    return [];
  }

  return value.flatMap((item, index) => {
    if (!item || typeof item !== 'object' || Array.isArray(item)) {
      return [];
    }

    const record = item as Record<string, unknown>;
    const key = normalizeText(record.key) || `step-${index + 1}`;
    const title = normalizeText(record.title);
    const options = Array.isArray(record.options)
      ? record.options.map((option) => normalizePromptOption(option)).filter(isPromptOption)
      : [];

    if (!title || options.length === 0) {
      return [];
    }

    return [
      {
        key,
        title,
        description: normalizeText(record.description) || null,
        submitLabel: normalizeText(record.submitLabel) || null,
        mode: record.mode === 'direct' || record.mode === 'queue' ? record.mode : null,
        multiple: record.multiple === true,
        optional: record.optional === true,
        responseTemplate: normalizeText(record.responseTemplate) || null,
        freeTextLabel: normalizeText(record.freeTextLabel) || null,
        freeTextPlaceholder: normalizeText(record.freeTextPlaceholder) || null,
        selectedValues: normalizePromptSelectedValues(record.selectedValues),
        options,
      },
    ];
  });
}

function decodeUrlComponentSafely(value: string) {
  try {
    return decodeURIComponent(value);
  } catch {
    return value;
  }
}

function resolveLinkCardUrlAndActionLabel(rawUrl: string, rawActionLabel?: string) {
  let resolvedUrl = normalizeText(rawUrl);
  let resolvedActionLabel = normalizeText(rawActionLabel);

  if (!resolvedActionLabel) {
    const decodedUrl = decodeUrlComponentSafely(resolvedUrl);
    const dividerIndex = decodedUrl.lastIndexOf('|');

    if (dividerIndex > 0 && dividerIndex < decodedUrl.length - 1) {
      resolvedUrl = decodedUrl.slice(0, dividerIndex).trim();
      resolvedActionLabel = decodedUrl.slice(dividerIndex + 1).trim();
    }
  }

  return {
    url: normalizeUrl(resolvedUrl),
    actionLabel: resolvedActionLabel || null,
  };
}

function isInternalResourceUrl(url: string) {
  return RESOURCE_PATH_PREFIXES.some((prefix) => url.startsWith(prefix));
}

function buildLinkCardPart(rawBody: string): ChatMessagePart | null {
  const segments = rawBody
    .split('|')
    .map((segment) => segment.trim())
    .filter(Boolean);

  if (segments.length < 2) {
    return null;
  }

  const [rawTitle, rawUrl, rawActionLabel] = segments;
  const title = normalizeText(rawTitle);
  const { url, actionLabel } = resolveLinkCardUrlAndActionLabel(rawUrl, rawActionLabel);

  if (!title || !url) {
    return null;
  }

  return {
    type: 'link_card',
    title,
    url,
    actionLabel,
  };
}

function buildPromptPart(rawBody: string): ChatMessagePart | null {
  let parsed: unknown;

  try {
    parsed = JSON.parse(rawBody);
  } catch {
    return null;
  }

  if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed)) {
    return null;
  }

  const record = parsed as Record<string, unknown>;
  const title = normalizeText(record.title);
  const options = Array.isArray(record.options)
    ? record.options.map((item) => normalizePromptOption(item)).filter(isPromptOption)
    : [];
  const steps = normalizePromptSteps(record.steps);

  if (!title || (options.length === 0 && steps.length === 0)) {
    return null;
  }

  const mode = record.mode === 'direct' || record.mode === 'queue' ? record.mode : null;
  const selectedValues = [
    ...normalizePromptSelectedValues(record.selectedValues),
    ...(record.selectedValue != null ? [record.selectedValue] : []),
    ...steps.flatMap((step) => step.selectedValues ?? []),
  ]
    .map((item) => normalizeText(item))
    .filter(Boolean)
    .filter((value, index, values) => values.indexOf(value) === index);
  const resolvedBy =
    record.resolvedBy === 'user' || record.resolvedBy === 'timeout' || record.resolvedBy === 'system'
      ? record.resolvedBy
      : null;

  return {
    type: 'prompt',
    title,
    description: normalizeText(record.description) || null,
    submitLabel: normalizeText(record.submitLabel) || null,
    mode,
    multiple: record.multiple === true,
    responseTemplate: normalizeText(record.responseTemplate) || null,
    freeTextLabel: normalizeText(record.freeTextLabel) || null,
    freeTextPlaceholder: normalizeText(record.freeTextPlaceholder) || null,
    currentStepKey: normalizeText(record.currentStepKey) || null,
    steps: steps.length > 0 ? steps : undefined,
    readOnly: record.readOnly === true || resolvedBy != null,
    selectedValues,
    resolvedBy,
    resolvedAt: normalizeText(record.resolvedAt) || null,
    resultText: normalizeText(record.resultText) || null,
    attachments: normalizePromptAttachments(record.attachments),
    options,
  };
}

function buildPromptPartFromBlock(rawBody: string) {
  const trimmed = rawBody.trim();

  if (!trimmed) {
    return null;
  }

  const promptWrapperMatched = trimmed.match(/^\[\[prompt:\s*([\s\S]*?)\s*\]\]$/i);
  return buildPromptPart(promptWrapperMatched?.[1] ?? trimmed);
}

function extractAttachmentEntryUrl(rawLine: string) {
  const matched = rawLine.match(ATTACHMENT_ENTRY_PATTERN);

  if (!matched) {
    return '';
  }

  const resolvedUrl = normalizeUrl(matched[2] ?? '');
  return resolvedUrl || '';
}

export function extractAttachmentPreviewUrls(text: string) {
  const lines = String(text ?? '').split('\n');
  const keptLines: string[] = [];
  const urls: string[] = [];
  const seen = new Set<string>();

  for (let index = 0; index < lines.length; index += 1) {
    const line = lines[index] ?? '';

    if (!ATTACHMENT_SECTION_TITLE_PATTERN.test(line)) {
      keptLines.push(line);
      continue;
    }

    const attachmentUrls: string[] = [];
    let cursor = index + 1;

    while (cursor < lines.length) {
      const nextLine = lines[cursor] ?? '';

      if (!nextLine.trim()) {
        cursor += 1;
        continue;
      }

      const attachmentUrl = extractAttachmentEntryUrl(nextLine);

      if (!attachmentUrl) {
        break;
      }

      attachmentUrls.push(attachmentUrl);
      cursor += 1;
    }

    if (attachmentUrls.length === 0) {
      keptLines.push(line);
      continue;
    }

    attachmentUrls.forEach((url) => {
      if (seen.has(url)) {
        return;
      }

      seen.add(url);
      urls.push(url);
    });

    index = cursor - 1;
  }

  return {
    strippedText: keptLines.join('\n').replace(/\n{3,}/g, '\n\n').trim(),
    urls,
  };
}

export function extractChatMessageParts(text: string) {
  const attachmentExtraction = extractAttachmentPreviewUrls(text);
  const lines = String(attachmentExtraction.strippedText ?? '').split('\n');
  const keptLines: string[] = [];
  const parts: ChatMessagePart[] = [];
  const seenLinkKeys = new Set<string>();
  let isInsideCodeFence = false;
  const pushPart = (nextPart: ChatMessagePart | null) => {
    if (!nextPart) {
      return false;
    }

    const dedupeKey =
      nextPart.type === 'link_card'
        ? `${nextPart.type}:${nextPart.title}:${nextPart.url}:${nextPart.actionLabel ?? ''}`
        : nextPart.type === 'preview_card'
          ? [
              nextPart.type,
              nextPart.title,
              nextPart.description ?? '',
              nextPart.kindLabel ?? '',
              nextPart.actionLabel ?? '',
              nextPart.preview.type,
              nextPart.preview.url ?? '',
              nextPart.preview.content ?? '',
              nextPart.preview.alt ?? '',
              nextPart.preview.title ?? '',
            ].join(':')
          : [
            nextPart.type,
            nextPart.title,
            nextPart.options
              .map((option) =>
                [
                  option.value,
                  option.label,
                  option.preview?.type ?? '',
                  option.preview?.url ?? '',
                  option.preview?.content ?? '',
                  option.preview?.title ?? '',
                ].join('|'),
              )
              .join(','),
            (nextPart.steps ?? [])
              .map((step) =>
                [
                  step.key,
                  step.title,
                  step.options.map((option) => `${option.value}:${option.label}`).join(','),
                ].join('|'),
              )
              .join(','),
            nextPart.selectedValues?.join(',') ?? '',
            nextPart.resolvedBy ?? '',
            nextPart.resultText ?? '',
            nextPart.readOnly === true ? 'readonly' : '',
          ].join(':');

    if (seenLinkKeys.has(dedupeKey)) {
      return true;
    }

    seenLinkKeys.add(dedupeKey);
    parts.push(nextPart);
    return true;
  };

  for (let lineIndex = 0; lineIndex < lines.length; lineIndex += 1) {
    const line = lines[lineIndex] ?? '';

    if (PROMPT_CODE_BLOCK_START_PATTERN.test(line)) {
      const fencedLines = [line];
      const jsonBodyLines: string[] = [];
      let cursor = lineIndex + 1;
      let foundFenceEnd = false;

      for (; cursor < lines.length; cursor += 1) {
        const nextLine = lines[cursor] ?? '';
        fencedLines.push(nextLine);

        if (CODE_BLOCK_END_PATTERN.test(nextLine)) {
          foundFenceEnd = true;
          break;
        }

        jsonBodyLines.push(nextLine);
      }

      if (foundFenceEnd && pushPart(buildPromptPartFromBlock(jsonBodyLines.join('\n')))) {
        lineIndex = cursor;
        continue;
      }

      keptLines.push(...fencedLines);
      lineIndex = foundFenceEnd ? cursor : lines.length;
      continue;
    }

    if (CODE_FENCE_TOGGLE_PATTERN.test(line)) {
      keptLines.push(line);
      isInsideCodeFence = !isInsideCodeFence;
      continue;
    }

    if (isInsideCodeFence) {
      keptLines.push(line);
      continue;
    }

    const cardMatched = line.match(CARD_LINE_PATTERN);

    if (cardMatched) {
      if (!pushPart(buildPreviewCardPart(cardMatched[1] ?? ''))) {
        keptLines.push(line);
      }
      continue;
    }

    if (CARD_BLOCK_START_PATTERN.test(line)) {
      const wrappedLines = [line];
      const cardBodyLines: string[] = [];
      let cursor = lineIndex + 1;
      let foundBlockEnd = false;

      for (; cursor < lines.length; cursor += 1) {
        const nextLine = lines[cursor] ?? '';
        wrappedLines.push(nextLine);

        if (PROMPT_BLOCK_END_PATTERN.test(nextLine)) {
          foundBlockEnd = true;
          break;
        }

        cardBodyLines.push(nextLine);
      }

      if (foundBlockEnd && pushPart(buildPreviewCardPart(cardBodyLines.join('\n')))) {
        lineIndex = cursor;
        continue;
      }

      keptLines.push(...wrappedLines);
      lineIndex = foundBlockEnd ? cursor : lines.length;
      continue;
    }

    const promptMatched = line.match(PROMPT_LINE_PATTERN);

    if (promptMatched) {
      if (!pushPart(buildPromptPart(promptMatched[1] ?? ''))) {
        keptLines.push(line);
      }
      continue;
    }

    if (PROMPT_BLOCK_START_PATTERN.test(line)) {
      const wrappedLines = [line];
      const promptBodyLines: string[] = [];
      let cursor = lineIndex + 1;
      let foundBlockEnd = false;

      for (; cursor < lines.length; cursor += 1) {
        const nextLine = lines[cursor] ?? '';
        wrappedLines.push(nextLine);

        if (PROMPT_BLOCK_END_PATTERN.test(nextLine)) {
          foundBlockEnd = true;
          break;
        }

        promptBodyLines.push(nextLine);
      }

      if (foundBlockEnd && pushPart(buildPromptPartFromBlock(promptBodyLines.join('\n')))) {
        lineIndex = cursor;
        continue;
      }

      keptLines.push(...wrappedLines);
      lineIndex = foundBlockEnd ? cursor : lines.length;
      continue;
    }

    const matched = line.match(LINK_CARD_LINE_PATTERN);

    if (!matched) {
      const markdownLinkMatch = line.match(STANDALONE_MARKDOWN_LINK_LINE_PATTERN);
      if (markdownLinkMatch) {
        const [, rawTitle, rawUrl] = markdownLinkMatch;
        if (isStructuredLinkCardCandidate(rawUrl ?? '')) {
          if (pushPart(buildLinkCardPart(`${rawTitle}|${rawUrl}`))) {
            continue;
          }
        }
      }

      const standaloneUrlMatch = line.match(STANDALONE_URL_LINE_PATTERN);
      if (standaloneUrlMatch) {
        const rawUrl = standaloneUrlMatch[1] ?? '';
        if (isStructuredLinkCardCandidate(rawUrl)) {
          if (pushPart(buildLinkCardPart(`${resolveStandaloneLinkTitle(keptLines, rawUrl)}|${rawUrl}`))) {
            continue;
          }
        }
      }

      keptLines.push(line);
      continue;
    }

    if (!pushPart(buildLinkCardPart(matched[1] ?? ''))) {
      keptLines.push(line);
      continue;
    }

    const latestPart = parts.at(-1);
    if (latestPart?.type === 'link_card' && isInternalResourceUrl(latestPart.url)) {
      parts.pop();
      seenLinkKeys.delete(`${latestPart.type}:${latestPart.title}:${latestPart.url}:${latestPart.actionLabel ?? ''}`);
      keptLines.push(latestPart.url);
    }
  }

  const strippedWithEmbeddedPrompts = (() => {
    const nextLines: string[] = [];
    let isInsideCodeFence = false;

    keptLines.forEach((line) => {
      if (CODE_FENCE_TOGGLE_PATTERN.test(line)) {
        nextLines.push(line);
        isInsideCodeFence = !isInsideCodeFence;
        return;
      }

      if (isInsideCodeFence) {
        nextLines.push(line);
        return;
      }

      nextLines.push(
        line.replace(/\[\[prompt:(.+?)\]\]/gi, (fullMatch, rawBody) => (pushPart(buildPromptPart(rawBody)) ? '' : fullMatch)),
      );
    });

    return nextLines.join('\n');
  })();

  return {
    strippedText: strippedWithEmbeddedPrompts.replace(/\n{3,}/g, '\n\n').trim(),
    parts,
  };
}
