'use client';

import { useRef, useState } from 'react';
import { useRouter } from 'next/navigation';
import { ImageIcon, X } from 'lucide-react';
import { fetchApi } from '@/lib/utils/client';
import useAuth from '@/hooks/useAuth';
import EmojiPicker from '@/app/component/EmojiPicker';

const MAX_LENGTH = 2000;
const MAX_IMAGES = 4;

type Props = {
	onSubmitted?: () => void;
};

export default function FeedComposer({ onSubmitted }: Props = {}) {
	const router = useRouter();
	const { member, loginCheck } = useAuth();
	const [content, setContent] = useState('');
	const [images, setImages] = useState<File[]>([]);
	const [previews, setPreviews] = useState<string[]>([]);
	const [submitting, setSubmitting] = useState(false);
	const [error, setError] = useState<string|null>(null);
	const fileInputRef = useRef<HTMLInputElement|null>(null);
	const textareaRef = useRef<HTMLTextAreaElement|null>(null);

	const isOver = content.length > MAX_LENGTH;

	const handleFilesSelected = (files: FileList|null) => {
		if (!files) {
			return;
		}

		const next: File[] = [...images];
		const nextPreviews: string[] = [...previews];

		for (const file of Array.from(files)) {
			if (next.length >= MAX_IMAGES) {
				break;
			}

			if (!file.type.startsWith('image/')) {
				continue;
			}

			next.push(file);
			nextPreviews.push(URL.createObjectURL(file));
		}

		setImages(next);
		setPreviews(nextPreviews);
	};

	const removeImage = (index: number) => {
		setImages((prev) => prev.filter((_, i) => i !== index));
		setPreviews((prev) => {
			const url = prev[index];
			if (url) {
				URL.revokeObjectURL(url);
			}
			return prev.filter((_, i) => i !== index);
		});
	};

	const handleEmojiSelect = (emoji: string) => {
		const textarea = textareaRef.current;

		if (!textarea) {
			setContent((prev) => prev + emoji);
			return;
		}

		const start = textarea.selectionStart ?? content.length;
		const end = textarea.selectionEnd ?? content.length;
		const next = content.slice(0, start) + emoji + content.slice(end);

		setContent(next);

		requestAnimationFrame(() => {
			textarea.focus();
			const caret = start + emoji.length;
			textarea.setSelectionRange(caret, caret);
		});
	};

	const handleSubmit = async () => {
		if (!loginCheck()) {
			return;
		}

		const trimmed = content.trim();
		if (trimmed.length === 0 && images.length === 0) {
			setError('내용을 입력하거나 이미지를 첨부해주세요.');
			return;
		}

		if (trimmed.length > MAX_LENGTH) {
			setError(`내용은 최대 ${MAX_LENGTH}자까지 작성할 수 있습니다.`);
			return;
		}

		setSubmitting(true);
		setError(null);

		try {
			const form = new FormData();
			form.append('Content', trimmed);

			for (const file of images) {
				form.append('images', file);
			}

			const res = await fetchApi<{ id: number }>('/api/feed', {
				method: 'POST',
				body: form,
				silent: true
			});

			if (!res.success) {
				setError(res.message ?? '게시 실패');
				return;
			}

			setContent('');
			setImages([]);
			setPreviews((prev) => {
				for (const url of prev) {
					URL.revokeObjectURL(url);
				}
				return [];
			});

			// FeedList 가 듣고 첫 페이지를 재조회해서 새 글을 prepend 함
			if (typeof window !== 'undefined') {
				window.dispatchEvent(new CustomEvent('feed:posted', { detail: { postID: res.data?.id } }));
			}

			if (onSubmitted) {
				onSubmitted();
			} else {
				router.push('/feed/all');
			}
		} catch (err) {
			console.error(err);
			setError(err instanceof Error ? err.message : '게시 실패');
		} finally {
			setSubmitting(false);
		}
	};

	if (!member) {
		return (
			<div className="feed__composer feed__composer--login">
				<p>글 작성을 위해 로그인이 필요합니다.</p>
			</div>
		);
	}

	return (
		<div className="feed__composer">
			<div className="feed__composer-avatar">
				{member.thumb ? (
					<img src={member.thumb} alt={member.name ?? member.sid} />
				) : (
					<span className="feed__composer-avatar-fallback">{(member.name ?? member.sid).charAt(0).toUpperCase()}</span>
				)}
			</div>

			<div className="feed__composer-body">
				<textarea
					ref={textareaRef}
					id="feed-composer-content"
					name="content"
					className="feed__composer-input"
					placeholder="무슨 일이 일어나고 있나요? #태그 @멘션 가능"
					value={content}
					onChange={(e) => setContent(e.target.value)}
					rows={3}
					maxLength={MAX_LENGTH + 100}
					disabled={submitting}
				/>

				{previews.length > 0 && (
					<div className="feed__composer-previews">
						{previews.map((url, index) => (
							<div key={url} className="feed__composer-preview">
								<img src={url} alt={`첨부 ${index + 1}`} />
								<button type="button" className="feed__composer-preview-remove" onClick={() => removeImage(index)} aria-label="첨부 제거">
									<X size={14} />
								</button>
							</div>
						))}
					</div>
				)}

				{error && <p className="feed__composer-error">{error}</p>}

				<div className="feed__composer-footer">
					<div className="feed__composer-tools">
						<EmojiPicker onEmojiSelect={handleEmojiSelect} />
						<button
							type="button"
							onClick={() => fileInputRef.current?.click()}
							disabled={submitting || images.length >= MAX_IMAGES}
							className="feed__composer-tool"
							aria-label="이미지 첨부"
						>
							<ImageIcon size={18} />
						</button>
						<input
							ref={fileInputRef}
							type="file"
							accept="image/*"
							multiple
							hidden
							onChange={(e) => handleFilesSelected(e.target.files)}
						/>
					</div>

					<div className="feed__composer-submit">
						<span className={`feed__composer-count${isOver ? ' feed__composer-count--over' : ''}`}>
							{content.length.toLocaleString()} / {MAX_LENGTH.toLocaleString()}
						</span>
						<button
							type="button"
							onClick={handleSubmit}
							disabled={submitting || (content.trim().length === 0 && images.length === 0) || isOver}
							className="feed__composer-submit-btn"
						>
							{submitting ? '게시 중...' : '게시하기'}
						</button>
					</div>
				</div>
			</div>
		</div>
	);
}