'use client';

import './style.scss';
import { useRouter } from 'next/navigation';
import Link from 'next/link';
import { useState, useEffect, useCallback, useRef, FormEvent } from 'react';
import Loading from '@/app/component/Loading';
import { BoardLayout, PostConst } from '@/constants/forum';
import { fetchApi } from '@/lib/utils/client';
import { checkPermission, isBoardAdmin } from '@/lib/utils/permission';
import useAuth from '@/hooks/useAuth';
import useErrorAlert from '@/hooks/useErrorAlert';
import { BoardResponse } from '@/types/response/forum/board';
import { BoardListResponse } from '@/types/response/forum/board';
import { PostCreateResponse } from '@/types/response/forum/post';
import Editor, { Handle } from '../_component/Editor';
import HeaderContent from '../_component/HeaderContent';
import FooterContent from '../_component/FooterContent';
import PostTagInput from '../_component/PostTagInput';

type Props = {
	_boardList: BoardListResponse,
	_board: BoardResponse
};

export default function View({ _boardList, _board }: Props)
{
	const router = useRouter();
	const { member } = useAuth();
	const { setError } = useErrorAlert();
	const [loading, setLoading] = useState<boolean>(false);
	const [permissionDenied, setPermissionDenied] = useState<boolean>(false);
	const [isChanged, setIsChanged] = useState<boolean>(false);
	const [board, setBoard] = useState<BoardResponse|null>(_board);
	const [boardList, setBoardList] = useState<BoardListResponse>(_boardList);
	const [boardCode, setBoardCode] = useState<string>(_board.code);
	const [boardPrefix, setBoardPrefix] = useState<string>('');
	const [subject, setSubject] = useState<string>('');
	const [content, setContent] = useState<string>('');
	const [isSecret, setIsSecret] = useState<boolean>(false);
	const [isNotice, setIsNotice] = useState<boolean>(false);
	const [isSpeaker, setIsSpeaker] = useState<boolean>(false);
	const [tags, setTags] = useState<string[]>([]);

	const editorRef = useRef<Handle>(null);
	const boardCodeRef = useRef<HTMLSelectElement>(null);
	const boardPrefixRef = useRef<HTMLSelectElement>(null);
	const subjectRef = useRef<HTMLInputElement>(null);
	const contentRef = useRef<HTMLTextAreaElement>(null);

	useEffect(() => {
		if (!boardCode) {
			return;
		}

		setLoading(true);
		setPermissionDenied(false);

		// 게시판 상세 정보 호출
		fetchApi<BoardResponse>('/api/forum/boards/' + boardCode).then((res) => {
			if (res.success && res.data) {
				// 게시글 작성 권한 확인
				if (!checkPermission(res.data.boardMeta, res.data.boardManager, member).canWritePost) {
					setBoard(res.data);
					setPermissionDenied(true);
					return;
				}
				setBoard(res.data);
			} else {
				throw new Error('게시판을 조회할 수 없습니다.');
			}
		}).catch((err) => {
			setError(err.message);
		}).finally(() => {
			setLoading(false);
		});
	}, [boardCode, member]);

	// 게시판 변경 시
	useEffect(() => {
		if (board) {
			resetForm();

			// 게시판 목록 호출
			if (boardList.total <= 0) {
				fetchApi<BoardListResponse>('/api/forum/boards?boardGroupCode=' + board.boardGroup.code).then((res) => {
					if (res.success) {
						if (res.data && res.data.total > 0) {
							setBoardList(res.data);
						}
					} else {
						throw new Error('게시판을 조회할 수 없습니다.');
					}
				}).catch((err) => {
					setError(err.message);
				}).finally(() => {
					setLoading(false);
				});
			}
		}
	}, [board, boardList]);

	// 게시글 초기화
	const resetForm = () => {
		setIsChanged(false);
		setBoardPrefix('');
		setSubject(board?.boardMeta.write.defaultSubject || '');
		setIsSecret(false);
		setIsNotice(false);
		setIsSpeaker(false);
		setTags([]);

		const defaultContent = (board?.boardMeta.write.defaultContent || '');
    	setContent(defaultContent);

		// Editor 초기화
		if (editorRef.current?.editorInstance) {
			editorRef.current.editorInstance.setData(defaultContent);
		}
	};

	// 게시판 선택 시
	const handleBoardChange = useCallback((e: React.ChangeEvent<HTMLSelectElement>) => {
		const code = e.target.value;

		if (isChanged) {
			if (!confirm('작성 중인 내용이 사라질 수 있습니다. 게시판을 변경하시겠습니까?')) {
				return
			}
		}

		setBoardCode(code);
		setIsChanged(false);
	}, [isChanged]);

	// 제목, 내용, 말머리 변경 시
	const handleChange = useCallback((e: React.ChangeEvent<HTMLSelectElement|HTMLInputElement|HTMLTextAreaElement>) => {
		const { name, value } = e.target as HTMLInputElement|HTMLSelectElement|HTMLTextAreaElement;
		const checked = (e.target as HTMLInputElement).checked;

		switch (name) {
			case 'boardPrefix':
				setBoardPrefix(value);
				break;
			case 'isSecret':
				setIsSecret(checked);
				break;
			case 'isNotice':
				setIsNotice(checked);
				setIsSpeaker(false);
				break;
			case 'isSpeaker':
				setIsSpeaker(checked);
				setIsNotice(false);
				break;
			case 'subject':
				setSubject(value);
				break;
			case 'content':
				setContent(value);
				break;
		}

		setIsChanged(true);
	}, []);

	// CKEditor에서 내용 변경 시
	const handleEditorChange = useCallback((data: string) => {
		setContent(data);
		setIsChanged(true);
	}, []);

	const validate = useCallback(() => {
		if (!boardCode || !board) {
			boardCodeRef.current?.focus();
			throw new Error('게시판을 선택해주세요.');
		}

		if (board.boardMeta.write.allowPrefix && board.boardMeta.write.requiredPrefix && !boardPrefix) {
			boardPrefixRef.current?.focus();
			throw new Error((board.boardMeta.list.layout === BoardLayout.QnA ? '분류' : '말머리') + '를 선택해주세요.');
		}

		if (!subject) {
			subjectRef.current?.focus();
			throw new Error('제목을 입력해주세요.');
		} else if (subject.length > PostConst.MaxAllowedSubjectLength) {
			subjectRef.current?.focus();
			throw new Error(`제목은 ${PostConst.MaxAllowedSubjectLength}자 이내로 작성해주세요.`);
		}

		if (!content) {
			if (board.boardMeta.write.allowEditor) {
				editorRef.current?.editorInstance?.editing.view.focus();
			} else {
				contentRef.current?.focus();
			}

			throw new Error('내용을 입력해주세요.');
		} else if (!board.boardMeta.write.allowEditor) {
			// 기본 textarea 사용 시 글자 수 검사
			if (content.length > PostConst.MaxAllowedContentLength) {
				contentRef.current?.focus();
				throw new Error(`내용은 ${PostConst.MaxAllowedContentLength}자 이내로 작성해주세요.`);
			}
		}

		if (board.boardMeta.write.allowTag && tags.length > board.boardMeta.write.tagLimit) {
			throw new Error(`태그는 ${board.boardMeta.write.tagLimit}개 이내로 작성해주세요.`);
		}
	}, [boardCode, board, boardPrefix, subject, content, tags]);

	// 게시글 등록 처리
	const handleSubmit = useCallback(async (e: FormEvent) => {
		e.preventDefault();

		try {

			validate();
			setLoading(true);

			if (!board) {
				throw new Error('게시판을 선택해 주세요.');
			}

			const formData = new FormData();
			formData.append('boardID', String(board.id));
			formData.append('boardCode', boardCode);
			formData.append('boardPrefixID', boardPrefix);
			formData.append('isSecret', String(isSecret));
			formData.append('isNotice', String(isNotice));
			formData.append('isSpeaker', String(isSpeaker));
			formData.append('subject', subject);

			if (content) {
				const doc = new DOMParser().parseFromString(content, 'text/html');
				doc.querySelectorAll('img[src]').forEach(img => {
					img.setAttribute('src', 'data:image/');
				});

				formData.append('content', doc.body.innerHTML);
			}

			// 태그
			if (board.boardMeta.write.allowTag) {
				tags.forEach(tag => formData.append('tags', tag));
			}

			// 파일 업로드 권한 체크
			const canUploadFile = checkPermission(board.boardMeta, board.boardManager, member).canUploadFile;

			// 이미지 정보
			if (board.boardMeta.write.allowEditor && board.boardMeta.write.allowImage) {
				const images = editorRef.current?.getImageStore() || [];
				console.log('[DEBUG] allowEditor:', board.boardMeta.write.allowEditor, 'allowImage:', board.boardMeta.write.allowImage);
				console.log('[DEBUG] _imageStore:', images);
				console.log('[DEBUG] _imageStore count:', images.length);
				images.forEach((i, idx) => {
					console.log(`[DEBUG] image[${idx}]:`, { name: i.name, size: i.size, type: i.type, hasFile: !!i.image, fileSize: i.image?.size });
				});
				if (images.length > 0 && !canUploadFile) {
					throw new Error('이미지를 첨부할 수 있는 권한이 없습니다.');
				}
				images.forEach(i => {
					if (i.image?.size > 0 && i.name) {
						formData.append('images', i.image, i.name);
					}
				});
			}

			// 미디어 정보
			if (board.boardMeta.write.allowEditor && board.boardMeta.write.allowMedia) {
				const medias = editorRef.current?.getMediaStore() || [];
				if (medias.length > 0 && !canUploadFile) {
					throw new Error('영상을 첨부할 수 있는 권한이 없습니다.');
				}
				medias.forEach((m) => {
					if (m.url) {
						formData.append('medias', m.url);
					}
				});
			}

			// 첨부 파일
			if (board.boardMeta.write.allowEditor && board.boardMeta.write.allowFile) {
				const files = editorRef.current?.getFileStore() || [];
				if (files.length > 0 && !canUploadFile) {
					throw new Error('파일을 첨부할 수 있는 권한이 없습니다.');
				}
				files.forEach(f => {
					if (f?.size > 0 && f.name) {
						formData.append('files', f.file, f.name);
					}
				});
			}

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

			if (res.success) {
				resetForm();
				router.push(`/post/${res.data?.id}`);
			}

		} catch (err) {
			if (err instanceof Error) {
				setError(err.message);
			}
		}
	}, [boardCode, board, boardPrefix, subject, content, isSecret, isNotice, isSpeaker, tags]);

	if (permissionDenied) {
		return (
			<div className="permission-denied">
				<h1>⚠️ 권한이 부족합니다</h1>
				<p>이 게시판에 글을 작성할 수 있는 권한이 없습니다.</p>
				<button type='button' onClick={() => router.back()}>돌아가기</button>
			</div>
		);
	}

	return (
		<form id='postWrite' onSubmit={handleSubmit}>
			{loading && <Loading />}

			<fieldset>
				<legend><h1>{board?.name} 글쓰기</h1></legend>

				{/* 상단 안내 */}
				{<HeaderContent isEnabled={board?.boardMeta.write.showHeader} content={board?.boardMeta.write.headerContent}/>}

				{/* 게시판 선택, 말머리, 비밀글, 공지, 전체 공지 */}
				<section>

					{/* 게시판 선택 */}
					{board?.boardMeta.list.layout !== BoardLayout.QnA && (
					<article>
						<select name='boardCode' ref={boardCodeRef} value={boardCode} onChange={handleBoardChange} title='게시판 선택'>
							<option value=''>게시판 선택</option>
							{boardList.list.map((item) => (
								<option key={item.code} value={item.code}>{item.name}</option>
							))}
						</select>
					</article>
					)}

					{/* 말머리 */}
					{board?.boardMeta.write.allowPrefix && (
						<article>
							<select name='boardPrefix' ref={boardPrefixRef} value={boardPrefix} onChange={handleChange} title='말머리 선택'>
								<option value=''>{(board.boardMeta.list.layout === BoardLayout.QnA ? '문의 유형' : '말머리') + ' 선택'}</option>
								{board?.boardPrefix.map((row) => (
									<option key={row.id} value={row.id}>{row.name}</option>
								))}
							</select>
						</article>
					)}

					<article>
						{/* 비밀글 */}
						{board?.boardMeta.write.allowSecret && (
							<>
								<input type='checkbox' name='isSecret' id='isSecret' checked={isSecret} onChange={handleChange} />
								<label htmlFor='isSecret'>비밀글</label>
							</>
						)}

						{isBoardAdmin(board?.boardManager ?? [], member) && (
							<>
							{/* 해당 게시판 공지 */}
							{!board?.boardMeta.list.exceptNotice && (
								<>
								<input type='checkbox' name='isNotice' id='isNotice' checked={isNotice} onChange={handleChange} />
								<label htmlFor='isNotice'>공지</label>
								</>
							)}

							{/* 게시판 전체 공지 */}
							{!board?.boardMeta.list.exceptSpeaker && (
								<>
								<input type='checkbox' name='isSpeaker' id='isSpeaker' checked={isSpeaker} onChange={handleChange} />
								<label htmlFor='isSpeaker'>전체 공지</label>
								</>
							)}
							</>
						)}
					</article>
				</section>

				{/* 제목 */}
				<section>
					<input type='text' name='subject' ref={subjectRef} value={subject} onChange={handleChange} placeholder='글 제목을 입력해주세요.' autoFocus maxLength={PostConst.MaxAllowedSubjectLength} />
				</section>

				{/* 내용 */}
				<section>
					{board?.boardMeta.write.allowEditor ?
					(
						<Editor ref={editorRef} key={boardCode} editorKey={boardCode} data={content} onChange={handleEditorChange} boardMeta={board?.boardMeta} />
					) : (
						<textarea name='content' ref={contentRef} value={content} onChange={handleChange} placeholder='내용을 입력해주세요.' maxLength={PostConst.MaxAllowedContentLength}></textarea>
					)}
				</section>

				{/* 태그 */}
				{board?.boardMeta.write?.allowTag && (
					<section id='postTag'>
						<PostTagInput value={tags} onChange={setTags} maxTags={board.boardMeta.write.tagLimit} />
					</section>
				)}

				{/* 하단 안내 */}
				{<FooterContent isEnabled={board?.boardMeta.write.showFooter} content={board?.boardMeta.write.footerContent}/>}

				<div>
					<br/>
				</div>

				<section>
					<button type='submit' className='btn btn-primary' disabled={loading}>
						{ loading ? '등록 중…' : '확인' }
					</button>
					<Link href={`/board/${boardCode || 'latest'}`} className='btn btn-default'>취소</Link>
				</section>
			</fieldset>
		</form>
	);
}