import { useState } from "react";
import type { ChatMessage } from "../../types/message";
import { useAvatars } from "../../context/AvatarContext";
import {
	downloadTextFile,
	messageMarkdownFilename,
	singleAssistantMarkdown,
} from "../../utils/exportConversation";
import { renderMarkdown } from "../../utils/markdown";
import { imageToDataUrl } from "../../utils/images";
import { ToolCallBlock } from "./ToolCallBlock";
import styles from "./MessageList.module.css";

interface MessageBubbleProps {
	message: ChatMessage;
	showAgentAvatar?: boolean;
	agentAvatarSpacer?: boolean;
}

function ChatAvatar({ src, className }: { src: string; className: string }) {
	const [failed, setFailed] = useState(false);
	if (!src || failed) return null;
	return (
		<img
			className={className}
			src={src}
			width={32}
			height={32}
			alt=""
			decoding="async"
			referrerPolicy="no-referrer"
			onError={() => setFailed(true)}
		/>
	);
}

function AssistantActions({ content }: { content: string }) {
	const [copied, setCopied] = useState(false);
	const markdown = singleAssistantMarkdown(content);

	const handleCopy = async () => {
		try {
			await navigator.clipboard.writeText(markdown);
			setCopied(true);
			window.setTimeout(() => setCopied(false), 1500);
		} catch {
			/* ignore */
		}
	};

	const handleDownload = () => {
		downloadTextFile(messageMarkdownFilename(content), markdown, "text/markdown");
	};

	return (
		<div className={styles.assistantToolbar}>
			<button
				type="button"
				className={`${styles.msgActionBtn} ${copied ? styles.msgActionBtnCopied : ""}`}
				onClick={() => void handleCopy()}
				title="复制 Markdown"
			>
				{copied ? "已复制" : "复制"}
			</button>
			<button
				type="button"
				className={styles.msgActionBtn}
				onClick={handleDownload}
				title="下载 Markdown"
			>
				下载
			</button>
		</div>
	);
}

export function MessageBubble({
	message,
	showAgentAvatar = false,
	agentAvatarSpacer = false,
}: MessageBubbleProps) {
	const { userAvatarUrl, agentAvatarUrl } = useAvatars();

	if (message.role === "tool_call") {
		return (
			<div className={styles.assistantRow}>
				{showAgentAvatar ? (
					<ChatAvatar src={agentAvatarUrl} className={styles.assistantAvatar} />
				) : agentAvatarSpacer ? (
					<div className={styles.assistantAvatarSpacer} aria-hidden="true" />
				) : null}
				<div className={`${styles.msg} ${styles.toolCall}`}>
					<ToolCallBlock content={message.content} />
				</div>
			</div>
		);
	}

	const classNames = [styles.msg];
	if (message.role === "user") classNames.push(styles.user);
	if (message.role === "assistant") classNames.push(styles.assistant);
	if (message.role === "system") classNames.push(styles.system);
	if (message.streaming) classNames.push(styles.streaming);

	if (message.role === "assistant") {
		const showActions = !message.streaming && message.content.trim().length > 0;
		return (
			<div className={styles.assistantRow}>
				<ChatAvatar src={agentAvatarUrl} className={styles.assistantAvatar} />
				<div className={classNames.join(" ")}>
					{showActions ? <AssistantActions content={message.content} /> : null}
					<div
						className={styles.assistantBody}
						dangerouslySetInnerHTML={{ __html: renderMarkdown(message.content) }}
					/>
				</div>
			</div>
		);
	}

	if (message.role === "user") {
		return (
			<div className={styles.userRow}>
				<div className={classNames.join(" ")}>
					{message.content ? <div>{message.content}</div> : null}
					{message.images?.length ? (
						<div className={styles.userImages}>
							{message.images.map((img, index) => (
								<img
									key={`${img.mimeType}-${index}`}
									className={styles.userImage}
									src={imageToDataUrl(img)}
									alt=""
									loading="lazy"
								/>
							))}
						</div>
					) : null}
				</div>
				<ChatAvatar src={userAvatarUrl} className={styles.userAvatar} />
			</div>
		);
	}

	return <div className={classNames.join(" ")}>{message.content}</div>;
}
