'use client';

import '../style.scss';
import Image from 'next/image';
import { useState, useRef, useEffect, useCallback } from 'react';
import Editor, { type Handle as EditorHandle } from '@/app/(main)/(forum)/post/_component/Editor';
import EmojiPicker from '@/app/component/EmojiPicker';
import Loading from '@/app/component/Loading';
import { useMemberContext } from '@/contexts/memberProvider';
import useErrorAlert from '@/hooks/useErrorAlert';
import { BoardResponse } from '@/types/response/forum/board';
import { PostResponse } from '@/types/response/forum/post';
import { CommentCreateRequest } from '@/types/request/forum/comment';
import { CommentCreateResponse } from '@/types/response/forum/comment';
import { CommentItem } from '@/types/forum/comment';
import { BoardLayout, CommentConst } from '@/constants/forum';
import { fetchApi } from '@/lib/utils/client';
import useAuth from '@/hooks/useAuth';
import MentionSuggestion from './MentionSuggestion';

type Props = {
	_board: BoardResponse,
	_post: PostResponse,
	_comment?: CommentItem; // null이면 새 댓글, 값이 있으면 답글
	onSuccess: (comment?: CommentItem) => void;
	onCancel?: () => void;
};

export default function WriteForm({ _board, _post, _comment, onSuccess, onCancel }: Props)
{
	const { member } = useMemberContext();
	const { loginCheck } = useAuth();
	const boardMeta = _board.boardMeta;

	const { setError } = useErrorAlert();
	const [loading, setLoading] = useState<boolean>(false);

	const [form, setForm] = useState<CommentCreateRequest>({
		postID: _post.id,
		parentID: _comment ? (_comment.parentID ?? _comment.id) : undefined,
		mention: '',
		content: '',
		isSecret: false
	});

	const textareaRef = useRef<HTMLTextAreaElement>(null);
	const editorRef = useRef<EditorHandle>(null);

	const initialContent = useCallback(() => {
		if (_comment) {
			// YouTube 스타일: 항상 최상위 댓글 아래에 붙임
			const resolvedParentID = _comment.parentID ?? _comment.id;
			const stored = localStorage.getItem('member');
			const myID = stored ? JSON.parse(stored).id : null;

			if (_comment.parentID && myID !== _comment.writer.id) {
				// 대댓글 + 다른 사용자 > 답글 대상의 작성자를 멘션
				const writerHandle = _comment.writer.name || _comment.writer.sid;
				const mentionText = `@${writerHandle} `;
				setForm(prev => ({ ...prev, parentID: resolvedParentID, mention: `@${writerHandle}`, content: mentionText }));
				setTimeout(() => textareaRef.current?.focus(), 0);
			} else {
				// 최상위 댓글 답글 또는 본인 댓글 답글
				setForm(prev => ({ ...prev, parentID: resolvedParentID, mention: '', content: '' }));
			}
		} else {
			// 새 댓글
			setForm(prev => ({ ...prev, parentID: undefined, mention: '', content: '' }));
		}
	}, [_comment]);

	useEffect(() => {
		initialContent();
	}, [initialContent]);

	// 입력 창 높이 조절
	const resizeTextarea = useCallback(() => {
		const textarea = textareaRef.current;
		if (textarea) {
			textarea.style.height = 'auto'; // 초기화
			textarea.style.height = `${textarea.scrollHeight}px`; // 높이 조정
		}
	}, []);

	useEffect(() => {
		resizeTextarea();
	}, [form.content, resizeTextarea]);

	// 멘션 자동완성 선택
	const handleMentionSelect = useCallback((newContent: string) => {
		setForm(prev => ({ ...prev, content: newContent }));
	}, []);

	// 비밀글 체크
	const handleSecretChange = useCallback((e: React.ChangeEvent<HTMLInputElement>) => {
		setForm(prev => ({ ...prev, isSecret: e.target.checked }));
	}, []);

	// 이모지 선택
	const handleEmoji = useCallback((emoji: string) => {
		setForm(prev => ({ ...prev, content: prev.content + emoji }));
	}, []);

	// 입력 내용 저장
	const handleContentChange = useCallback((e: React.ChangeEvent<HTMLTextAreaElement>) => {
		setForm(prev => ({ ...prev, content: e.target.value }));
	}, []);

	// 입력 내용 초기화
	const resetForm = useCallback(() => {
		initialContent();
		resizeTextarea();
	}, [initialContent, resizeTextarea]);

	// 댓글+답글 등록
	const handleSubmit = useCallback(async () => {
		if (!loginCheck()) {
			return;
		}

		if (!form.content.trim()) {
			if (boardMeta.list.layout === BoardLayout.QnA) {
				editorRef.current?.editorInstance?.editing.view.focus();
			} else {
				textareaRef.current?.focus();
			}

			return setError('내용을 입력해주세요.');
		}

		setLoading(true);

		try {

			{
				const trimmedContent = form.content.trim();
				const maxLen = boardMeta.comment.maxContentLength || CommentConst.MaxAllowedContentLength;
				const minLen = boardMeta.comment.minContentLength;

				if (minLen > 0 && trimmedContent.length < minLen) {
					if (boardMeta.comment.enableEditor) {
						editorRef.current?.editorInstance?.editing.view.focus();
					} else {
						textareaRef.current?.focus();
					}
					throw new Error(`내용은 ${minLen}자 이상 작성해주세요.`);
				}

				if (trimmedContent.length > maxLen) {
					if (boardMeta.comment.enableEditor) {
						editorRef.current?.editorInstance?.editing.view.focus();
					} else {
						textareaRef.current?.focus();
					}
					throw new Error(`내용은 ${maxLen}자 이내로 작성해주세요.`);
				}
			}

			const formData = new FormData();
			formData.append('postID', String(form.postID));
			formData.append('isSecret', String(form.isSecret));

			if (form.parentID) {
				formData.append('parentID', String(form.parentID));
			}

			// content에서 자동으로 붙은 @회원을 제거한다.
			let content = form.content;

			const escapeRegExp = (s: string) => s.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
			if (form.mention) {
				content = content.replace(new RegExp('^\\s*' + escapeRegExp(form.mention) + '\\s*', 'i') , '');
				formData.append('mention', form.mention.trim());
			}

			// 1:1 문의일 경우 검사
			if (boardMeta.list.layout === BoardLayout.QnA) {
				if (content) {
					const doc = new DOMParser().parseFromString(content, 'text/html');
					doc.querySelectorAll('img[src]').forEach(img => {
						img.setAttribute('src', 'data:image/');
					});

					content = doc.body.innerHTML;
				}

				// 이미지 정보
				editorRef.current?.getImageStore().forEach((i) => {
					if (i.image?.size > 0 && i.name) {
						formData.append('images', i.image, i.name);
					}
				});

				// 미디어 정보
				editorRef.current?.getMediaStore().forEach((m) => {
					if (m.url) {
						formData.append('medias', m.url);
					}
				});

				// 첨부 파일
				editorRef.current?.getFileStore().forEach((f) => {
					if (f?.size > 0 && f.name) {
						formData.append('files', f.file, f.name);
					}
				});
			}

			formData.append('content', content);

			const res = await fetchApi<CommentCreateResponse>('/api/forum/comments', {
				method: 'POST',
				body: formData
			});

			const newComment: CommentItem = {
				id: res.data!.id,
				postID: _post.id,
				memberID: member!.id,
				parentID: form.parentID,
				writer: {
					id: member!.id,
					sid: member!.sid ?? '',
					name: member!.name,
					thumbnail: member!.thumb,
					icon: member!.icon,
					createdAt: ''
				},
				mention: form.mention ? { id: 0, rawHandle: form.mention } : undefined,
				content: form.content,
				isReply: !!form.parentID,
				isSecret: form.isSecret,
				likes: 0, dislikes: 0, reports: 0, replies: 0,
				hasLike: false, hasDislike: false, hasReport: false,
				createdAt: new Date().toISOString(),
				children: []
			};

			onSuccess(newComment);

		} catch (err) {
			if (err instanceof Error) {
				setError(err.message);
			}
		} finally {
			setLoading(false);
			resetForm();
		}
	}, [form, boardMeta, _post.id, member, loginCheck, onSuccess, setError, resetForm]);

	// Ctrl + Enter 최종 제출
	const handleKeyDown = useCallback((e: React.KeyboardEvent<HTMLTextAreaElement>) => {
		if (e.ctrlKey && e.key === 'Enter') {
			e.preventDefault();
			handleSubmit();
		}
	}, [handleSubmit]);

	// 취소
	const handleCancel = useCallback(() => {
		if (onCancel) {
			onCancel();
		} else {
			resetForm();
		}
	}, [onCancel, resetForm]);

	const handleEditorChange = useCallback((data: string) => {
		setForm(prev => ({ ...prev, content: data }));
	}, []);

	return (
		<>
			{loading ? (
				<article>
					<Loading type={2} />
				</article>
			) : (
				<article className='write-form'>
					{boardMeta.comment.showMemberThumb && (
					<div>
						<Image src={member?.thumb ?? '/resources/thumb.gif'} alt={member?.name ?? member?.sid ?? ''} width={72} height={0} />
					</div>
					)}
					<div>
						<div className='relative'>
							<MentionSuggestion postID={_post.id} textareaRef={textareaRef} onSelect={handleMentionSelect} />
							{boardMeta.comment.enableEditor ? (
								<Editor
									ref={editorRef}
									editorKey='_comment'
									data={form.content}
									onChange={handleEditorChange}
									boardMeta={boardMeta}
								/>
							) : (
								<textarea
									name='_comment'
									rows={1}
									value={form.content}
									title='댓글 입력 창'
									placeholder={boardMeta.comment.contentPlaceholder ?? ''}
									ref={textareaRef}
									onChange={handleContentChange}
									onKeyDown={handleKeyDown}
									disabled={loading}
								/>
							)}
						</div>
						<div>
							<EmojiPicker onEmojiSelect={handleEmoji} />
							{boardMeta.comment.allowSecret && (
							<label className='ps-2'>
								<input type="checkbox" checked={form.isSecret} onChange={handleSecretChange} />
								<span className='ps-1'>비밀글</span>
							</label>
							)}
						</div>
						<div>
							<button type='button' className='btn btn-default' onClick={handleCancel}>취소</button>
							<button type='button' className='btn btn-submit' onClick={handleSubmit}>확인</button>
						</div>
					</div>
				</article>
			)}
		</>
	)
};