'use client';

import { useCallback, useEffect, useRef, useState } from 'react';
import { Dialog, DialogContent, DialogHeader, DialogTitle } from '@/components/ui/dialog';
import { fetchApi } from '@/lib/utils/client';
import type { RecipientItem, SearchRecipientResponse } from '@/types/response/note/searchRecipient';
import { Search, X } from 'lucide-react';

type Props = {
	open: boolean;
	onClose: () => void;
	initialReceiver?: RecipientItem|null;
	initialTitle?: string;
	onSent?: () => void;
};

const PAGE_SIZE = 20;
const SEARCH_DEBOUNCE_MS = 300;

export default function NoteComposeModal({ open, onClose, initialReceiver, initialTitle, onSent }: Props)
{
	const [receiver, setReceiver] = useState<RecipientItem|null>(null);
	const [searchQuery, setSearchQuery] = useState('');
	const [searchResults, setSearchResults] = useState<RecipientItem[]>([]);
	const [searchHasMore, setSearchHasMore] = useState(false);
	const [searchOffset, setSearchOffset] = useState(0);
	const [searchLoading, setSearchLoading] = useState(false);
	const searchTimerRef = useRef<ReturnType<typeof setTimeout>|null>(null);

	const [title, setTitle] = useState('');
	const [content, setContent] = useState('');
	const [sendToRandom, setSendToRandom] = useState(false);
	const [sending, setSending] = useState(false);
	const [error, setError] = useState<string|null>(null);

	// 모달 열릴 때 상태 초기화
	useEffect(() => {
		if (open) {
			setReceiver(initialReceiver ?? null);
			setTitle(initialTitle ?? '');
			setContent('');
			setSearchQuery('');
			setSearchResults([]);
			setSearchHasMore(false);
			setSearchOffset(0);
			setError(null);
			setSendToRandom(false);
		}
	}, [open, initialReceiver, initialTitle]);

	const runSearch = useCallback(async (q: string, offset: number, append: boolean) => {
		const trimmed = q.trim();

		if (trimmed.length < 2) {
			setSearchResults([]);
			setSearchHasMore(false);
			setSearchOffset(0);
			return;
		}

		setSearchLoading(true);

		try {
			const params = new URLSearchParams({ q: trimmed, offset: String(offset), limit: String(PAGE_SIZE) });
			const res = await fetchApi<SearchRecipientResponse>(`/api/note/search-recipient?${params.toString()}`, { silent: true });

			if (res.data) {
				setSearchResults(prev => append ? [...prev, ...res.data!.list] : res.data!.list);
				setSearchHasMore(res.data.hasMore);
				setSearchOffset(offset + res.data.list.length);
			}
		} catch {
			// ignore — silent
		} finally {
			setSearchLoading(false);
		}
	}, []);

	// 검색 query 변경 시 debounce
	useEffect(() => {
		if (receiver) {
			return;
		}

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

		searchTimerRef.current = setTimeout(() => {
			runSearch(searchQuery, 0, false);
		}, SEARCH_DEBOUNCE_MS);

		return () => {
			if (searchTimerRef.current) {
				clearTimeout(searchTimerRef.current);
			}
		};
	}, [searchQuery, receiver, runSearch]);

	const handleShowMore = () => {
		runSearch(searchQuery, searchOffset, true);
	};

	const handleSelect = (item: RecipientItem) => {
		setReceiver(item);
		setSearchQuery('');
		setSearchResults([]);
		setSearchHasMore(false);
	};

	const handleClearReceiver = () => {
		setReceiver(null);
	};

	const handleSend = async () => {
		setError(null);

		if (!sendToRandom && !receiver) {
			setError('받는 사람을 선택해주세요.');
			return;
		}

		if (!title.trim() || !content.trim()) {
			setError('제목과 내용을 입력해주세요.');
			return;
		}

		setSending(true);

		try {
			const res = await fetchApi('/api/note/send', {
				method: 'POST',
				body: sendToRandom
					? {
						title: title.trim(),
						content: content.trim(),
						sendToRandom: true
					}
					: {
						receiverMemberID: receiver!.memberID,
						title: title.trim(),
						content: content.trim()
					}
			});

			if (res.success) {
				onSent?.();
				onClose();
				return;
			}

			setError(res.message || '전송에 실패했습니다.');
		} catch (e: unknown) {
			const message = e instanceof Error ? e.message : '전송에 실패했습니다.';
			setError(message);
		} finally {
			setSending(false);
		}
	};

	return (
		<Dialog open={open} onOpenChange={(o) => { if (!o) { onClose(); } }}>
			<DialogContent className="max-w-md">
				<DialogHeader>
					<DialogTitle>{initialTitle?.startsWith('RE:') ? '답장' : '쪽지 보내기'}</DialogTitle>
				</DialogHeader>

				<div className="flex flex-col gap-3 mt-2">
					{/* 무작위 발송 (쪽지권) */}
					<label className="flex items-center gap-2 text-sm">
						<input type="checkbox" checked={sendToRandom} onChange={(e) => setSendToRandom(e.target.checked)} />
						<span>무작위 회원에게 발송 (쪽지권 1개 소모)</span>
					</label>
					{sendToRandom && (
						<div className="text-xs text-gray-500">받는 사람은 무작위로 선택되며, 쪽지권 1개가 사용됩니다.</div>
					)}

					{/* 받는 사람 */}
					<div>
						<label className="text-sm font-medium mb-1 block">받는 사람</label>
						{receiver ? (
							<div className="flex items-center gap-2 p-2 rounded-lg border border-gray-200 dark:border-gray-700">
								{receiver.thumbnailUrl ? (
									// eslint-disable-next-line @next/next/no-img-element
									<img src={receiver.thumbnailUrl} alt={receiver.displayName} className="w-8 h-8 rounded-full object-cover" />
								) : (
									<div className="w-8 h-8 rounded-full bg-gray-200 dark:bg-gray-700 flex items-center justify-center text-xs">
										{receiver.displayName[0]?.toUpperCase() ?? '?'}
									</div>
								)}
								<div className="flex-1 overflow-hidden">
									<div className="text-sm font-medium truncate">{receiver.displayName}</div>
									{receiver.displaySubtitle && (
										<div className="text-xs text-gray-500 truncate">{receiver.displaySubtitle}</div>
									)}
								</div>
								<button
									type="button"
									onClick={handleClearReceiver}
									className="p-1 text-gray-400 hover:text-gray-600"
									aria-label="수신자 변경"
								>
									<X size={16} />
								</button>
							</div>
						) : (
							<>
								<div className="relative">
									<Search size={14} className="absolute left-3 top-1/2 -translate-y-1/2 text-gray-400" />
									<input
										type="text"
										value={searchQuery}
										onChange={(e) => setSearchQuery(e.target.value)}
										placeholder="팔로우한 회원 검색"
										className="w-full border rounded-lg pl-9 pr-3 py-2 text-sm"
									/>
								</div>

								{searchQuery.trim().length >= 2 && (
									<div className="mt-1 border rounded-lg max-h-60 overflow-y-auto">
										{searchLoading && searchResults.length === 0 ? (
											<div className="p-3 text-xs text-gray-500 text-center">검색 중…</div>
										) : searchResults.length === 0 ? (
											<div className="p-3 text-xs text-gray-500 text-center">
												검색 결과가 없습니다. 팔로우한 회원만 검색됩니다.
											</div>
										) : (
											<>
												{searchResults.map(item => (
													<button
														key={item.memberID}
														type="button"
														onClick={() => handleSelect(item)}
														className="w-full flex items-center gap-2 p-2 hover:bg-gray-100 dark:hover:bg-gray-800 text-left"
													>
														{item.thumbnailUrl ? (
															// eslint-disable-next-line @next/next/no-img-element
															<img src={item.thumbnailUrl} alt={item.displayName} className="w-7 h-7 rounded-full object-cover" />
														) : (
															<div className="w-7 h-7 rounded-full bg-gray-200 dark:bg-gray-700 flex items-center justify-center text-xs">
																{item.displayName[0]?.toUpperCase() ?? '?'}
															</div>
														)}
														<div className="flex-1 overflow-hidden">
															<div className="text-sm truncate">{item.displayName}</div>
															{item.displaySubtitle && (
																<div className="text-xs text-gray-500 truncate">{item.displaySubtitle}</div>
															)}
														</div>
													</button>
												))}
												{searchHasMore && (
													<button
														type="button"
														onClick={handleShowMore}
														disabled={searchLoading}
														className="w-full p-2 text-xs text-blue-500 hover:bg-gray-100 dark:hover:bg-gray-800 disabled:opacity-50"
													>
														{searchLoading ? '불러오는 중…' : '더 보기'}
													</button>
												)}
											</>
										)}
									</div>
								)}
							</>
						)}
					</div>

					{/* 제목 */}
					<div>
						<label className="text-sm font-medium mb-1 block">제목</label>
						<input
							type="text"
							value={title}
							onChange={(e) => setTitle(e.target.value)}
							maxLength={200}
							placeholder="제목을 입력하세요"
							className="w-full border rounded-lg px-3 py-2 text-sm"
						/>
					</div>

					{/* 내용 */}
					<div>
						<label className="text-sm font-medium mb-1 block">내용</label>
						<textarea
							value={content}
							onChange={(e) => setContent(e.target.value)}
							maxLength={2000}
							rows={6}
							placeholder="내용을 입력하세요"
							className="w-full border rounded-lg px-3 py-2 text-sm resize-none"
						/>
						<div className="text-xs text-gray-400 text-right mt-1">{content.length}/2000</div>
					</div>

					{error && (
						<div className="p-2 rounded-lg bg-red-50 text-red-700 dark:bg-red-950 dark:text-red-300 text-xs">
							{error}
						</div>
					)}

					<div className="flex gap-2 mt-2">
						<button
							type="button"
							onClick={onClose}
							disabled={sending}
							className="flex-1 border rounded-lg py-2 text-sm hover:bg-gray-50 dark:hover:bg-gray-800 disabled:opacity-50"
						>
							취소
						</button>
						<button
							type="button"
							onClick={handleSend}
							disabled={sending}
							className="flex-1 bg-blue-500 text-white rounded-lg py-2 text-sm hover:bg-blue-600 disabled:opacity-50"
						>
							{sending ? '전송 중…' : '보내기'}
						</button>
					</div>
				</div>
			</DialogContent>
		</Dialog>
	);
}
