'use client';

// D2 $종목 태그 렌더러 — 서버가 내려준 본문(HTML) 안의 `$005930(삼성전자)` 토큰을
// 클릭 가능한 종목 배지(/stock/005930 링크)로 치환한다.
// 파싱은 서버가 저장 시 수행하고, 프론트는 표시 토큰을 렌더만 한다(본문 원문 불변).
// dangerouslySetInnerHTML 로 삽입된 HTML 의 텍스트 노드만 순회해 치환(스크립트/속성 미변조).
import '@/app/styles/community.scss';
import { useEffect, useRef } from 'react';

interface Props {
	content: string;
	className?: string;
}

// $ + 6자리 숫자 + (선택) (종목명). 6자리 뒤에 숫자가 이어지면 코드로 보지 않음(경계, 서버 파서와 동일).
const TAG_PATTERN = /\$(\d{6})(?!\d)(?:\(([^)]{0,20})\))?/g;

export default function StockTagContent({ content, className }: Props)
{
	const ref = useRef<HTMLDivElement>(null);

	useEffect(() => {
		const root = ref.current;
		if (!root) {
			return;
		}

		// 이미 배지로 치환된 노드는 건너뛰기 위해 앵커 내부 텍스트는 제외
		const walker = document.createTreeWalker(root, NodeFilter.SHOW_TEXT, {
			acceptNode(node) {
				if (!node.nodeValue || !node.nodeValue.includes('$')) {
					return NodeFilter.FILTER_REJECT;
				}

				// 이미 종목 태그 앵커 안이면 스킵
				let parent = node.parentElement;
				while (parent && parent !== root) {
					if (parent.classList && parent.classList.contains('stock-tag')) {
						return NodeFilter.FILTER_REJECT;
					}
					parent = parent.parentElement;
				}

				return NodeFilter.FILTER_ACCEPT;
			}
		});

		const targets: Text[] = [];
		let current = walker.nextNode();
		while (current) {
			targets.push(current as Text);
			current = walker.nextNode();
		}

		for (const textNode of targets) {
			const text = textNode.nodeValue ?? '';
			TAG_PATTERN.lastIndex = 0;

			if (!TAG_PATTERN.test(text)) {
				continue;
			}

			TAG_PATTERN.lastIndex = 0;
			const frag = document.createDocumentFragment();
			let lastIndex = 0;
			let match: RegExpExecArray|null;

			while ((match = TAG_PATTERN.exec(text)) !== null) {
				const [full, code, name] = match;

				if (match.index > lastIndex) {
					frag.appendChild(document.createTextNode(text.slice(lastIndex, match.index)));
				}

				const anchor = document.createElement('a');
				anchor.href = `/stock/${code}`;
				anchor.className = 'stock-tag';

				const nameSpan = document.createElement('span');
				nameSpan.textContent = name ? name : code;
				anchor.appendChild(nameSpan);

				const codeSpan = document.createElement('span');
				codeSpan.className = 'stock-tag__code';
				codeSpan.textContent = code;
				anchor.appendChild(codeSpan);

				frag.appendChild(anchor);
				lastIndex = match.index + full.length;
			}

			if (lastIndex < text.length) {
				frag.appendChild(document.createTextNode(text.slice(lastIndex)));
			}

			textNode.parentNode?.replaceChild(frag, textNode);
		}
	}, [content]);

	return (
		<div
			ref={ref}
			className={className}
			dangerouslySetInnerHTML={{ __html: content }}
		></div>
	);
}
