import { useEffect, useMemo, useRef } from "react";
import { useChatContext } from "../../context/ChatContext";
import type { MessageRole } from "../../types/message";
import { MessageBubble } from "./MessageBubble";
import styles from "./MessageList.module.css";

const NEAR_BOTTOM_THRESHOLD = 96;

function isNearBottom(el: HTMLElement): boolean {
	return el.scrollHeight - el.scrollTop - el.clientHeight <= NEAR_BOTTOM_THRESHOLD;
}

function scrollToBottom(el: HTMLElement): void {
	el.scrollTop = el.scrollHeight;
}

function isAgentSideRole(role: MessageRole): boolean {
	return role === "assistant" || role === "thinking" || role === "tool_call" || role === "bash";
}

export function MessageList() {
	const { messages, toolsExpanded, showThinkingAndTools } = useChatContext();
	const visibleMessages = useMemo(
		() =>
			showThinkingAndTools
				? messages
				: messages.filter((m) => m.role !== "thinking" && m.role !== "tool_call"),
		[messages, showThinkingAndTools],
	);
	const chatRef = useRef<HTMLDivElement>(null);
	const stickToBottomRef = useRef(true);
	const prevMessageCountRef = useRef(0);

	const lastMessage = messages[messages.length - 1];
	const scrollKey = lastMessage
		? `${messages.length}:${lastMessage.id}:${lastMessage.content.length}:${lastMessage.streaming ? 1 : 0}`
		: String(messages.length);

	useEffect(() => {
		const el = chatRef.current;
		if (!el) return;

		const onScroll = () => {
			stickToBottomRef.current = isNearBottom(el);
		};

		el.addEventListener("scroll", onScroll, { passive: true });
		return () => el.removeEventListener("scroll", onScroll);
	}, []);

	useEffect(() => {
		const el = chatRef.current;
		if (!el) return;

		const prevCount = prevMessageCountRef.current;
		const messageCount = messages.length;
		prevMessageCountRef.current = messageCount;

		const last = messages[messageCount - 1];
		const userJustSent = messageCount > prevCount && last?.role === "user";

		if (userJustSent || prevCount === 0) {
			stickToBottomRef.current = true;
		}

		if (!stickToBottomRef.current) return;

		requestAnimationFrame(() => {
			if (chatRef.current) scrollToBottom(chatRef.current);
		});
	}, [scrollKey, messages.length]);

	if (messages.length === 0) {
		return (
			<div className={styles.chat} ref={chatRef}>
				<div className={styles.empty}>
					<div className={styles.emptyIcon}>
						<svg width="48" height="48" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round">
							<path d="M21 15a2 2 0 01-2 2H7l-4 4V5a2 2 0 012-2h14a2 2 0 012 2z" />
						</svg>
					</div>
					<p>发送一条消息开始对话</p>
					<p className={styles.emptyHint}>按 Enter 发送 · Shift+Enter 换行</p>
				</div>
			</div>
		);
	}

	return (
		<div className={styles.chat} ref={chatRef}>
			{visibleMessages.map((msg, index) => {
				const prev = visibleMessages[index - 1];
				const prevIsAgentSide = prev ? isAgentSideRole(prev.role) : false;
				const isAgentSide = isAgentSideRole(msg.role);
				const agentGutter = isAgentSide ? (prevIsAgentSide ? "spacer" : "avatar") : "none";

				return (
					<MessageBubble
						key={msg.id}
						message={msg}
						agentGutter={agentGutter}
						toolsExpanded={toolsExpanded}
						showThinkingAndTools={showThinkingAndTools}
					/>
				);
			})}
		</div>
	);
}