'use client';

import Image from 'next/image';
import { useState, useEffect, useRef, useCallback } from 'react';
import { fetchApi } from '@/lib/utils/client';
import MemberSuggestion from '@/types/forum/memtionSuggetion';

type Props = {
	postID: number;
	textareaRef: React.RefObject<HTMLTextAreaElement|null>;
	onSelect: (handle: string) => void;
};

export default function MentionSuggestion({ postID, textareaRef, onSelect }: Props)
{
	const [show, setShow] = useState(false);
	const [keyword, setKeyword] = useState('');
	const [results, setResults] = useState<MemberSuggestion[]>([]);
	const [selectedIndex, setSelectedIndex] = useState(0);
	const [mentionStart, setMentionStart] = useState(-1);
	const debounceRef = useRef<ReturnType<typeof setTimeout>>(null);
	const containerRef = useRef<HTMLDivElement>(null);

	// textarea 입력 감지
	const detectMention = useCallback(() => {
		const textarea = textareaRef.current;
		if (!textarea) return;

		const value = textarea.value;
		const cursor = textarea.selectionStart;

		// 커서 앞에서 가장 가까운 @ 찾기
		const before = value.slice(0, cursor);
		const atIndex = before.lastIndexOf('@');

		if (atIndex === -1) {
			setShow(false);
			return;
		}

		// @ 앞이 공백이거나 맨 처음이어야 함
		if (atIndex > 0 && before[atIndex - 1] !== ' ' && before[atIndex - 1] !== '\n') {
			setShow(false);
			return;
		}

		// @ 뒤 텍스트에 공백이 있으면 멘션이 아님
		const query = before.slice(atIndex + 1);
		if (query.includes(' ') || query.includes('\n')) {
			setShow(false);
			return;
		}

		setMentionStart(atIndex);
		setKeyword(query);
		setShow(true);
		setSelectedIndex(0);
	}, [textareaRef]);

	// 검색 API 호출 (debounce)
	useEffect(() => {
		if (!show) {
			return;
		}

		if (!show || keyword.length === 0) {
			return;
		}

		if (debounceRef.current) {
          	clearTimeout(debounceRef.current);
      	}

		debounceRef.current = setTimeout(async () => {
			try {
				const res = await fetchApi<MemberSuggestion[]>(
					`/api/forum/comments/mention?postID=${postID}&keyword=${encodeURIComponent(keyword)}`,
				);

				if (res.data) {
					setResults(res.data);
					if (res.data.length === 0) {
						setShow(false);
					}
				}
			} catch {
				setShow(false);
			}
		}, 300);

		return () => {
			if (debounceRef.current) {
				clearTimeout(debounceRef.current);
			}
		};
	}, [keyword, show, postID]);

	// 회원 선택
	const handleSelect = useCallback((member: MemberSuggestion) => {
		const textarea = textareaRef.current;
		if (!textarea) return;

		const handle = member.name ?? member.sid;
		const value = textarea.value;
		const after = value.slice(textarea.selectionStart);

		// @keyword 부분을 @handle 로 교체
		const newValue = value.slice(0, mentionStart) + `@${handle} ` + after;
		onSelect(newValue);

		setShow(false);
		setResults([]);

		// 커서를 멘션 뒤로 이동
		setTimeout(() => {
			const cursorPos = mentionStart + handle.length + 2; // @handle + space
			textarea.setSelectionRange(cursorPos, cursorPos);
			textarea.focus();
		}, 0);
	}, [textareaRef, mentionStart, onSelect]);

	// 키보드 네비게이션
	const handleKeyDown = useCallback((e: KeyboardEvent) => {
		if (!show || results.length === 0) return;

		switch (e.key) {
			case 'ArrowDown':
				e.preventDefault();
				setSelectedIndex(prev => (prev + 1) % results.length);
				break;
			case 'ArrowUp':
				e.preventDefault();
				setSelectedIndex(prev => (prev - 1 + results.length) % results.length);
				break;
			case 'Enter':
				if (show && results.length > 0) {
					e.preventDefault();
					handleSelect(results[selectedIndex]);
				}
				break;
			case 'Escape':
				setShow(false);
				break;
		}
	}, [show, results, selectedIndex, handleSelect]);

	// textarea 이벤트 리스너
	useEffect(() => {
		const textarea = textareaRef.current;
		if (!textarea) {
			return;
		}

		textarea.addEventListener('input', detectMention);
		textarea.addEventListener('click', detectMention);
		textarea.addEventListener('keydown', handleKeyDown);

		return () => {
			textarea.removeEventListener('input', detectMention);
			textarea.removeEventListener('click', detectMention);
			textarea.removeEventListener('keydown', handleKeyDown);
		};
	}, [textareaRef, detectMention, handleKeyDown]);

	// 외부 클릭 시 닫기
	useEffect(() => {
		if (!show) return;

		const handleClickOutside = (e: MouseEvent) => {
			if (containerRef.current && !containerRef.current.contains(e.target as Node)) {
				setShow(false);
			}
		};

		document.addEventListener('mousedown', handleClickOutside);
		return () => document.removeEventListener('mousedown', handleClickOutside);
	}, [show]);

	if (!show || results.length === 0) {
		return null;
	}

	return (
		<div ref={containerRef} className="mention-suggestion">
			<ul>
				{results.map((member, index) => (
					<li
						key={member.id}
						className={index === selectedIndex ? 'selected' : ''}
						onMouseEnter={() => setSelectedIndex(index)}
						onMouseDown={(e) => {
							e.preventDefault();
							handleSelect(member);
						}}
					>
						<Image
							src={member.thumb ?? '/resources/thumb.gif'}
							alt={member.name ?? member.sid}
							width={28}
							height={28}
						/>
						<span>{member.name ?? member.sid}</span>
						{member.name && <small>{member.sid}</small>}
					</li>
				))}
			</ul>
		</div>
	);
}
