import * as React from "react";
import Markdown from "react-markdown";
import { Prism as SyntaxHighlighter } from "react-syntax-highlighter";
import { oneDark } from "react-syntax-highlighter/dist/esm/styles/prism";
import type { WizardStateData } from "../api/client";
import type { Message } from "../types";
import { MessageItem } from "./MessageItem";
import SetupWizard from "./SetupWizard";

const { useEffect, useRef } = React;

/** Fixed-height thinking trace block that auto-scrolls to bottom as text arrives. */
export function ThinkingBlock({ text }: { text: string }) {
	const scrollRef = useRef<HTMLDivElement>(null);

	useEffect(() => {
		const el = scrollRef.current;
		if (el) {
			el.scrollTop = el.scrollHeight;
		}
	}, [text]);

	return (
		<div
			data-testid="chat-thinking-block"
			ref={scrollRef}
			style={{
				maxHeight: "96px",
				overflowY: "auto",
				background: "#161b22",
				border: "1px solid #2d333b",
				borderRadius: "6px",
				padding: "6px 10px",
				fontSize: "0.78em",
				fontFamily: "monospace",
				color: "#6e7681",
				fontStyle: "italic",
				whiteSpace: "pre-wrap",
				wordBreak: "break-word",
				lineHeight: "1.4",
				marginBottom: "8px",
			}}
		>
			<span
				style={{
					display: "block",
					fontSize: "0.8em",
					color: "#444c56",
					marginBottom: "4px",
					fontStyle: "normal",
					letterSpacing: "0.04em",
					textTransform: "uppercase",
				}}
			>
				thinking
			</span>
			{text}
		</div>
	);
}

/** Streaming message renderer — stable component to avoid recreation on each render. */
export function StreamingMessage({ content }: { content: string }) {
	return (
		<Markdown
			components={{
				// biome-ignore lint/suspicious/noExplicitAny: react-markdown requires any for component props
				code: ({ className, children, ...props }: any) => {
					const match = /language-(\w+)/.exec(className || "");
					const isInline = !className;
					return !isInline && match ? (
						<SyntaxHighlighter
							// biome-ignore lint/suspicious/noExplicitAny: oneDark style types are incompatible
							style={oneDark as any}
							language={match[1]}
							PreTag="div"
						>
							{String(children).replace(/\n$/, "")}
						</SyntaxHighlighter>
					) : (
						<code className={className} {...props}>
							{children}
						</code>
					);
				},
			}}
		>
			{content}
		</Markdown>
	);
}

interface ChatMessageListProps {
	messages: Message[];
	loading: boolean;
	streamingContent: string;
	streamingThinking: string;
	activityStatus: string | null;
	wizardState: WizardStateData | null;
	setWizardState: React.Dispatch<React.SetStateAction<WizardStateData | null>>;
	needsOnboarding: boolean;
	setNeedsOnboarding: React.Dispatch<React.SetStateAction<boolean>>;
	sendMessage: (text: string) => void;
	scrollContainerRef: React.RefObject<HTMLDivElement | null>;
	messagesEndRef: React.RefObject<HTMLDivElement | null>;
	onScroll: () => void;
	onboardingTriggeredRef: React.MutableRefObject<boolean>;
}

export function ChatMessageList({
	messages,
	loading,
	streamingContent,
	streamingThinking,
	activityStatus,
	wizardState,
	setWizardState,
	needsOnboarding,
	setNeedsOnboarding,
	sendMessage,
	scrollContainerRef,
	messagesEndRef,
	onScroll,
	onboardingTriggeredRef,
}: ChatMessageListProps) {
	return (
		<div
			ref={scrollContainerRef}
			onScroll={onScroll}
			style={{
				flex: 1,
				overflowY: "auto",
				padding: "20px 0",
				display: "flex",
				flexDirection: "column",
				gap: "24px",
			}}
		>
			<div
				style={{
					maxWidth: "768px",
					margin: "0 auto",
					width: "100%",
					padding: "0 24px",
					display: "flex",
					flexDirection: "column",
					gap: "24px",
				}}
			>
				{wizardState &&
					!wizardState.completed &&
					messages.length === 0 &&
					!loading && (
						<SetupWizard
							wizardState={wizardState}
							onWizardUpdate={setWizardState}
							sendMessage={sendMessage}
						/>
					)}
				{needsOnboarding &&
					!wizardState &&
					messages.length === 0 &&
					!loading && (
						<div
							data-testid="onboarding-welcome"
							style={{
								padding: "24px",
								borderRadius: "12px",
								background: "#1c2a1c",
								border: "1px solid #2d4a2d",
								marginBottom: "8px",
							}}
						>
							<h3
								style={{
									margin: "0 0 8px 0",
									color: "#a0d4a0",
									fontSize: "1.1rem",
								}}
							>
								Welcome to Huskies
							</h3>
							<p
								style={{
									margin: "0 0 16px 0",
									color: "#ccc",
									lineHeight: 1.5,
								}}
							>
								This project needs to be set up before you can start writing
								stories. The agent will guide you through configuring your
								project goals and tech stack.
							</p>
							<button
								type="button"
								data-testid="onboarding-start-button"
								onClick={() => {
									if (onboardingTriggeredRef.current) return;
									onboardingTriggeredRef.current = true;
									setNeedsOnboarding(false);
									sendMessage(
										"I just created a new project. Help me set it up.",
									);
								}}
								style={{
									padding: "10px 20px",
									borderRadius: "8px",
									border: "none",
									backgroundColor: "#a0d4a0",
									color: "#1a1a1a",
									cursor: "pointer",
									fontSize: "0.95rem",
									fontWeight: 600,
								}}
							>
								Start Project Setup
							</button>
						</div>
					)}
				{messages.map((msg: Message, idx: number) => (
					<MessageItem
						// biome-ignore lint/suspicious/noArrayIndexKey: Message has no stable ID
						key={`msg-${idx}-${msg.role}-${msg.content.substring(0, 20)}`}
						msg={msg}
					/>
				))}
				{loading && streamingThinking && (
					<ThinkingBlock text={streamingThinking} />
				)}
				{loading && streamingContent && (
					<div
						style={{
							display: "flex",
							flexDirection: "column",
							alignItems: "flex-start",
						}}
					>
						<div
							style={{
								maxWidth: "100%",
								padding: "0",
								borderRadius: "0",
								background: "transparent",
								color: "#ececec",
								border: "none",
								fontFamily: "inherit",
								fontSize: "1em",
								fontWeight: "500",
								whiteSpace: "normal",
								lineHeight: "1.6",
							}}
						>
							<div className="markdown-body">
								<StreamingMessage content={streamingContent} />
							</div>
						</div>
					</div>
				)}
				{loading &&
					(activityStatus != null ||
						(!streamingContent && !streamingThinking)) && (
						<div
							data-testid="activity-indicator"
							style={{
								alignSelf: "flex-start",
								color: "#888",
								fontSize: "0.9em",
								marginTop: "10px",
							}}
						>
							<span className="pulse">{activityStatus ?? "Thinking..."}</span>
						</div>
					)}
				<div ref={messagesEndRef} />
			</div>
		</div>
	);
}
