// pnpm --filter @roo-code/vscode-webview test src/components/chat/__tests__/ChatView.spec.tsx

import React from "react"
import { render, waitFor, act } from "@/utils/test-utils"
import { QueryClient, QueryClientProvider } from "@tanstack/react-query"

import { ExtensionStateContextProvider } from "@src/context/ExtensionStateContext"

import ChatView, { ChatViewProps } from "../ChatView"

// Define minimal types needed for testing
interface ClineMessage {
	type: "say" | "ask"
	say?: string
	ask?: string
	ts: number
	text?: string
	partial?: boolean
}

interface ExtensionState {
	version: string
	clineMessages: ClineMessage[]
	taskHistory: any[]
	shouldShowAnnouncement: boolean
	allowedCommands: string[]
	alwaysAllowExecute: boolean
	[key: string]: any
}

// Mock vscode API
vi.mock("@src/utils/vscode", () => ({
	vscode: {
		postMessage: vi.fn(),
	},
}))

// Mock use-sound hook
const mockPlayFunction = vi.fn()
vi.mock("use-sound", () => ({
	default: vi.fn().mockImplementation(() => {
		return [mockPlayFunction]
	}),
}))

// Mock components that use ESM dependencies
vi.mock("../ChatRow", () => ({
	default: function MockChatRow({
		message,
		isFollowUpAnswered,
		isMultipleChoiceAnswered,
	}: {
		message: ClineMessage
		isFollowUpAnswered?: boolean
		isMultipleChoiceAnswered?: boolean
	}) {
		return (
			<div
				data-testid="chat-row"
				data-ask={message.ask}
				data-followup-answered={String(isFollowUpAnswered)}
				data-multiple-choice-answered={String(isMultipleChoiceAnswered)}>
				{JSON.stringify(message)}
			</div>
		)
	},
}))

vi.mock("../AutoApproveMenu", () => ({
	default: () => null,
}))

// Mock react-virtuoso to render items directly without virtualization
// This allows tests to verify items rendered in the chat list
vi.mock("react-virtuoso", () => ({
	Virtuoso: function MockVirtuoso({
		data,
		itemContent,
	}: {
		data: ClineMessage[]
		itemContent: (index: number, item: ClineMessage) => React.ReactNode
	}) {
		return (
			<div data-testid="virtuoso-item-list">
				{data.map((item, index) => (
					<div key={item.ts} data-testid={`virtuoso-item-${index}`}>
						{itemContent(index, item)}
					</div>
				))}
			</div>
		)
	},
}))

// Mock VersionIndicator - returns null by default to prevent rendering in tests
vi.mock("../../common/VersionIndicator", () => ({
	default: vi.fn(() => null),
}))

// Get the mock function after the module is mocked
const mockVersionIndicator = vi.mocked((await import("../../common/VersionIndicator")).default)

vi.mock("../Announcement", () => ({
	default: function MockAnnouncement({ hideAnnouncement }: { hideAnnouncement: () => void }) {
		// eslint-disable-next-line @typescript-eslint/no-require-imports
		const React = require("react")
		return React.createElement(
			"div",
			{ "data-testid": "announcement-modal" },
			React.createElement("div", null, "What's New"),
			React.createElement("button", { onClick: hideAnnouncement }, "Close"),
		)
	},
}))

// Mock DismissibleUpsell component
vi.mock("@/components/common/DismissibleUpsell", () => ({
	default: function MockDismissibleUpsell({ children }: { children: React.ReactNode }) {
		return <div data-testid="dismissible-upsell">{children}</div>
	},
}))

// Mock QueuedMessages component
vi.mock("../QueuedMessages", () => ({
	QueuedMessages: function MockQueuedMessages({
		queue = [],
		onRemove,
	}: {
		queue?: Array<{ id: string; text: string; images?: string[] }>
		onRemove?: (index: number) => void
		onUpdate?: (index: number, newText: string) => void
	}) {
		if (!queue || queue.length === 0) {
			return null
		}
		return (
			<div data-testid="queued-messages">
				{queue.map((msg, index) => (
					<div key={msg.id}>
						<span>{msg.text}</span>
						<button aria-label="Remove message" onClick={() => onRemove?.(index)}>
							Remove
						</button>
					</div>
				))}
			</div>
		)
	},
}))

// Mock RooTips component
vi.mock("@src/components/welcome/RooTips", () => ({
	default: function MockRooTips() {
		return <div data-testid="roo-tips">Tips content</div>
	},
}))

// Mock RooHero component
vi.mock("@src/components/welcome/RooHero", () => ({
	default: function MockRooHero() {
		return <div data-testid="roo-hero">Hero content</div>
	},
}))

// Mock TelemetryBanner component
vi.mock("../common/TelemetryBanner", () => ({
	default: function MockTelemetryBanner() {
		return null // Don't render anything to avoid interference
	},
}))

// Mock i18n
vi.mock("react-i18next", () => ({
	useTranslation: () => ({
		t: (key: string, options?: any) => {
			if (key === "chat:versionIndicator.ariaLabel" && options?.version) {
				return `Version ${options.version}`
			}
			return key
		},
	}),
	initReactI18next: {
		type: "3rdParty",
		init: () => {},
	},
	Trans: ({ i18nKey, children }: { i18nKey: string; children?: React.ReactNode }) => {
		return <>{children || i18nKey}</>
	},
}))

interface ChatTextAreaProps {
	onSend: () => void
	inputValue?: string
	setInputValue?: (value: string) => void
	sendingDisabled?: boolean
	placeholderText?: string
	selectedImages?: string[]
	shouldDisableImages?: boolean
}

const mockInputRef = React.createRef<HTMLInputElement>()
const mockFocus = vi.fn()

vi.mock("../ChatTextArea", () => {
	// eslint-disable-next-line @typescript-eslint/no-require-imports
	const mockReact = require("react")

	const ChatTextAreaComponent = mockReact.forwardRef(function MockChatTextArea(
		props: ChatTextAreaProps,
		ref: React.ForwardedRef<{ focus: () => void }>,
	) {
		// Use useImperativeHandle to expose the mock focus method
		mockReact.useImperativeHandle(ref, () => ({
			focus: mockFocus,
		}))

		return (
			<div data-testid="chat-textarea">
				<input
					ref={mockInputRef}
					type="text"
					value={props.inputValue || ""}
					onChange={(e) => {
						// Use parent's setInputValue if available
						if (props.setInputValue) {
							props.setInputValue(e.target.value)
						}
					}}
					onKeyDown={(e) => {
						// Only call onSend when Enter is pressed (simulating real behavior)
						if (e.key === "Enter" && !e.shiftKey) {
							e.preventDefault()
							props.onSend()
						}
					}}
					data-sending-disabled={props.sendingDisabled}
				/>
			</div>
		)
	})

	return {
		default: ChatTextAreaComponent,
		ChatTextArea: ChatTextAreaComponent, // Export as named export too
	}
})

// Mock VSCode components
vi.mock("@vscode/webview-ui-toolkit/react", () => ({
	VSCodeButton: function MockVSCodeButton({
		children,
		onClick,
		appearance,
	}: {
		children: React.ReactNode
		onClick?: () => void
		appearance?: string
	}) {
		return (
			<button onClick={onClick} data-appearance={appearance}>
				{children}
			</button>
		)
	},
	VSCodeTextField: function MockVSCodeTextField({
		value,
		onInput,
		placeholder,
	}: {
		value?: string
		onInput?: (e: { target: { value: string } }) => void
		placeholder?: string
	}) {
		return (
			<input
				type="text"
				value={value}
				onChange={(e) => onInput?.({ target: { value: e.target.value } })}
				placeholder={placeholder}
			/>
		)
	},
	VSCodeLink: function MockVSCodeLink({ children, href }: { children: React.ReactNode; href?: string }) {
		return <a href={href}>{children}</a>
	},
}))

// Mock window.postMessage to trigger state hydration
const mockPostMessage = (state: Partial<ExtensionState>) => {
	window.postMessage(
		{
			type: "state",
			state: {
				version: "1.0.0",
				clineMessages: [],
				taskHistory: [],
				shouldShowAnnouncement: false,
				allowedCommands: [],
				alwaysAllowExecute: false,
				cloudIsAuthenticated: false,
				telemetrySetting: "disabled",
				...state,
			},
		},
		"*",
	)
}

const defaultProps: ChatViewProps = {
	isHidden: false,
	showAnnouncement: false,
	hideAnnouncement: () => {},
}

const queryClient = new QueryClient()

const renderChatView = (props: Partial<ChatViewProps> = {}) => {
	return render(
		<ExtensionStateContextProvider>
			<QueryClientProvider client={queryClient}>
				<ChatView {...defaultProps} {...props} />
			</QueryClientProvider>
		</ExtensionStateContextProvider>,
	)
}

describe("ChatView - Sound Playing Tests", () => {
	beforeEach(() => vi.clearAllMocks())

	it("plays celebration sound for completion results", async () => {
		renderChatView()

		// First hydrate state with initial task
		mockPostMessage({
			soundEnabled: true, // Enable sound
			clineMessages: [
				{
					type: "say",
					say: "task",
					ts: Date.now() - 2000,
					text: "Initial task",
				},
			],
		})

		// Clear any initial calls
		mockPlayFunction.mockClear()

		// Add completion result
		mockPostMessage({
			soundEnabled: true, // Enable sound
			clineMessages: [
				{
					type: "say",
					say: "task",
					ts: Date.now() - 2000,
					text: "Initial task",
				},
				{
					type: "ask",
					ask: "completion_result",
					ts: Date.now(),
					text: "Task completed successfully",
					partial: false, // Ensure it's not partial
				},
			],
		})

		// Wait for sound to be played
		await waitFor(() => {
			expect(mockPlayFunction).toHaveBeenCalled()
		})
	})

	it("plays progress_loop sound for api failures", async () => {
		renderChatView()

		// First hydrate state with initial task
		mockPostMessage({
			soundEnabled: true, // Enable sound
			clineMessages: [
				{
					type: "say",
					say: "task",
					ts: Date.now() - 2000,
					text: "Initial task",
				},
			],
		})

		// Clear any initial calls
		mockPlayFunction.mockClear()

		// Add API failure
		mockPostMessage({
			soundEnabled: true, // Enable sound
			clineMessages: [
				{
					type: "say",
					say: "task",
					ts: Date.now() - 2000,
					text: "Initial task",
				},
				{
					type: "ask",
					ask: "api_req_failed",
					ts: Date.now(),
					text: "API request failed",
					partial: false, // Ensure it's not partial
				},
			],
		})

		// Wait for sound to be played
		await waitFor(() => {
			expect(mockPlayFunction).toHaveBeenCalled()
		})
	})

	it("does not play sound when resuming a task from history", () => {
		renderChatView()

		// Clear any initial calls
		mockPlayFunction.mockClear()

		// Hydrate state with a task that has a resumeTaskId (indicating it's resumed from history)
		mockPostMessage({
			resumeTaskId: "task-123",
			clineMessages: [
				{
					type: "say",
					say: "task",
					ts: Date.now() - 2000,
					text: "Resumed task",
				},
				{
					type: "ask",
					ask: "tool",
					ts: Date.now(),
					text: JSON.stringify({ tool: "readFile", path: "test.txt" }),
				},
			],
		})

		// Should not play sound when resuming from history
		expect(mockPlayFunction).not.toHaveBeenCalled()
	})

	it("does not play sound when resuming a completed task from history", () => {
		renderChatView()

		// Clear any initial calls
		mockPlayFunction.mockClear()

		// Hydrate state with a completed task that has a resumeTaskId
		mockPostMessage({
			resumeTaskId: "task-123",
			clineMessages: [
				{
					type: "say",
					say: "task",
					ts: Date.now() - 2000,
					text: "Resumed task",
				},
				{
					type: "ask",
					ask: "completion_result",
					ts: Date.now(),
					text: "Task completed",
				},
			],
		})

		// Should not play sound for completion when resuming from history
		expect(mockPlayFunction).not.toHaveBeenCalled()
	})
})

describe("ChatView - multiple_choice loading visibility", () => {
	beforeEach(() => vi.clearAllMocks())

	it("hides stale partial multiple_choice loading rows after a later user message arrives", async () => {
		const view = renderChatView()

		const loadingTs = Date.now() - 1000
		mockPostMessage({
			clineMessages: [
				{
					type: "say",
					say: "task",
					ts: loadingTs - 1,
					text: "Initial task",
				},
				{
					type: "ask",
					ask: "multiple_choice",
					ts: loadingTs,
					text: "partial questionnaire payload",
					partial: true,
				},
			],
		})

		expect(await view.findByText(/"ask":"multiple_choice"/)).toBeInTheDocument()

		mockPostMessage({
			clineMessages: [
				{
					type: "say",
					say: "task",
					ts: loadingTs - 1,
					text: "Initial task",
				},
				{
					type: "ask",
					ask: "multiple_choice",
					ts: loadingTs,
					text: "partial questionnaire payload",
					partial: true,
				},
				{
					type: "say",
					say: "user_feedback",
					ts: loadingTs + 1,
					text: "继续",
				},
			],
		})

		await waitFor(() => {
			expect(view.queryByText(/"ask":"multiple_choice"/)).not.toBeInTheDocument()
		})
	})

	it("does not mark multiple_choice answered when only a followup is answered later", async () => {
		const view = renderChatView()
		const multipleChoiceTs = Date.now() - 100
		const followupTs = multipleChoiceTs + 1

		mockPostMessage({
			clineMessages: [
				{
					type: "say",
					say: "task",
					ts: multipleChoiceTs - 1,
					text: "Initial task",
				},
				{
					type: "ask",
					ask: "multiple_choice",
					ts: multipleChoiceTs,
					text: JSON.stringify({ questions: [] }),
				},
				{
					type: "ask",
					ask: "followup",
					ts: followupTs,
					text: "Need a follow-up answer",
				},
			],
		})

		await waitFor(() => {
			expect(view.getAllByTestId("chat-row").length).toBeGreaterThan(0)
		})

		const rows = view.getAllByTestId("chat-row")
		const multipleChoiceRow = rows.find((row) => row.getAttribute("data-ask") === "multiple_choice")
		expect(multipleChoiceRow).toHaveAttribute("data-multiple-choice-answered", "false")
	})

	it("keeps followup answered state independent from multiple_choice messages", async () => {
		const view = renderChatView()
		const followupTs = Date.now() - 100
		const multipleChoiceTs = followupTs + 1

		mockPostMessage({
			clineMessages: [
				{
					type: "say",
					say: "task",
					ts: followupTs - 1,
					text: "Initial task",
				},
				{
					type: "ask",
					ask: "followup",
					ts: followupTs,
					text: "Need a follow-up answer",
				},
				{
					type: "ask",
					ask: "multiple_choice",
					ts: multipleChoiceTs,
					text: JSON.stringify({ questions: [] }),
				},
			],
		})

		await waitFor(() => {
			expect(view.getAllByTestId("chat-row").length).toBeGreaterThan(0)
		})

		const rows = view.getAllByTestId("chat-row")
		const followupRow = rows.find((row) => row.getAttribute("data-ask") === "followup")
		expect(followupRow).toHaveAttribute("data-followup-answered", "false")
	})
})

describe("ChatView - Focus Grabbing Tests", () => {
	beforeEach(() => vi.clearAllMocks())

	it("does not grab focus when follow-up question presented", async () => {
		const { getByTestId } = renderChatView()

		// First hydrate state with initial task
		mockPostMessage({
			clineMessages: [
				{
					type: "say",
					say: "task",
					ts: Date.now() - 2000,
					text: "Initial task",
				},
			],
		})

		// Wait for the component to fully render and settle before clearing mocks
		await waitFor(() => {
			expect(getByTestId("chat-textarea")).toBeInTheDocument()
		})

		// Wait for the debounced focus effect to fire (50ms debounce + buffer for CI variability)
		await act(async () => {
			await new Promise((resolve) => setTimeout(resolve, 100))
		})

		// Clear any initial calls after state has settled
		mockFocus.mockClear()

		// Add follow-up question
		mockPostMessage({
			clineMessages: [
				{
					type: "say",
					say: "task",
					ts: Date.now() - 2000,
					text: "Initial task",
				},
				{
					type: "ask",
					ask: "followup",
					ts: Date.now(),
					text: "Should I continue?",
				},
			],
		})

		// Wait for state update to complete
		await waitFor(() => {
			expect(getByTestId("chat-textarea")).toBeInTheDocument()
		})

		// Should not grab focus for follow-up questions
		expect(mockFocus).not.toHaveBeenCalled()
	})
})

describe("ChatView - Version Indicator Tests", () => {
	beforeEach(() => {
		vi.clearAllMocks()
		// Reset the mock to return null by default
		mockVersionIndicator.mockReturnValue(null)
	})

	it("displays version indicator button", () => {
		// Mock VersionIndicator to return a button
		mockVersionIndicator.mockReturnValue(
			React.createElement("button", {
				"data-testid": "version-indicator",
				"aria-label": "Version 1.0.0",
				className: "version-indicator-button",
			}),
		)

		const { getByTestId } = renderChatView()

		// Hydrate state with no active task
		mockPostMessage({
			version: "1.0.0",
			clineMessages: [],
		})

		// Should display version indicator
		expect(getByTestId("version-indicator")).toBeInTheDocument()
	})

	it("opens announcement modal when version indicator is clicked", async () => {
		// Mock VersionIndicator to return a button with onClick
		mockVersionIndicator.mockImplementation(({ onClick }: { onClick?: () => void }) =>
			React.createElement("button", {
				"data-testid": "version-indicator",
				onClick,
			}),
		)

		const { getByTestId /* queryByTestId */ } = renderChatView({ showAnnouncement: false })

		// Hydrate state
		mockPostMessage({
			version: "1.0.0",
			clineMessages: [],
		})

		// Wait for component to render
		await waitFor(() => {
			expect(getByTestId("version-indicator")).toBeInTheDocument()
		})

		// Click version indicator
		const versionIndicator = getByTestId("version-indicator")
		act(() => {
			versionIndicator.click()
		})
		return
		// Wait for announcement modal to appear
		// await waitFor(() => {
		// 	expect(queryByTestId("announcement-modal")).toBeInTheDocument()
		// })
	})

	it("version indicator has correct styling classes", () => {
		// Mock VersionIndicator to return a button with specific classes
		mockVersionIndicator.mockReturnValue(
			React.createElement("button", {
				"data-testid": "version-indicator",
				className: "version-indicator-button absolute top-2 right-2",
			}),
		)

		const { getByTestId } = renderChatView()

		// Hydrate state
		mockPostMessage({
			version: "1.0.0",
			clineMessages: [],
		})

		const versionIndicator = getByTestId("version-indicator")
		expect(versionIndicator.className).toContain("version-indicator-button")
		expect(versionIndicator.className).toContain("absolute")
		expect(versionIndicator.className).toContain("top-2")
		expect(versionIndicator.className).toContain("right-2")
	})

	it("version indicator has proper accessibility attributes", () => {
		// Mock VersionIndicator to return a button with aria-label
		mockVersionIndicator.mockReturnValue(
			React.createElement("button", {
				"data-testid": "version-indicator",
				"aria-label": "Version 1.0.0",
				role: "button",
			}),
		)

		const { getByTestId } = renderChatView()

		// Hydrate state
		mockPostMessage({
			version: "1.0.0",
			clineMessages: [],
		})

		const versionIndicator = getByTestId("version-indicator")
		expect(versionIndicator.getAttribute("aria-label")).toBe("Version 1.0.0")
		expect(versionIndicator.getAttribute("role")).toBe("button")
	})

	it("does not display version indicator when there is an active task", () => {
		// Mock VersionIndicator to return null (simulating hidden state)
		mockVersionIndicator.mockReturnValue(null)

		const { queryByTestId } = renderChatView()

		// Hydrate state with active task
		mockPostMessage({
			version: "1.0.0",
			clineMessages: [
				{
					type: "say",
					say: "task",
					ts: Date.now(),
					text: "Active task",
				},
			],
		})

		// Should not display version indicator during active task
		expect(queryByTestId("version-indicator")).not.toBeInTheDocument()
	})

	it("displays version indicator only on welcome screen (no task)", () => {
		// Mock VersionIndicator to return a button
		mockVersionIndicator.mockReturnValue(React.createElement("button", { "data-testid": "version-indicator" }))

		const { queryByTestId } = renderChatView()

		// Hydrate state with no active task
		mockPostMessage({
			version: "1.0.0",
			clineMessages: [],
		})

		// Should display version indicator on welcome screen
		expect(queryByTestId("version-indicator")).toBeInTheDocument()
	})
})

// describe("ChatView - DismissibleUpsell Display Tests", () => {
// 	beforeEach(() => vi.clearAllMocks())

// 	it("does not show DismissibleUpsell when user is authenticated to Cloud", () => {
// 		const { queryByTestId } = renderChatView()

// 		// Hydrate state with user authenticated to cloud and some task history
// 		mockPostMessage({
// 			cloudIsAuthenticated: true,
// 			taskHistory: [
// 				{ id: "1", ts: Date.now() - 4000 },
// 				{ id: "2", ts: Date.now() - 3000 },
// 				{ id: "3", ts: Date.now() - 2000 },
// 				{ id: "4", ts: Date.now() - 1000 },
// 				{ id: "5", ts: Date.now() },
// 			],
// 			clineMessages: [], // No active task
// 		})

// 	// Should not show DismissibleUpsell when authenticated
// 	expect(queryByTestId("dismissible-upsell")).not.toBeInTheDocument()
// })

// it("does not show DismissibleUpsell when user has only run 3 tasks in their history", () => {
// 	const { queryByTestId } = renderChatView()

// 		// Hydrate state with user not authenticated and only 3 tasks in history
// 		mockPostMessage({
// 			cloudIsAuthenticated: false,
// 			taskHistory: [
// 				{ id: "1", ts: Date.now() - 2000 },
// 				{ id: "2", ts: Date.now() - 1000 },
// 				{ id: "3", ts: Date.now() },
// 			],
// 			clineMessages: [], // No active task
// 		})

// 	// Should not show DismissibleUpsell with less than 4 tasks
// 	expect(queryByTestId("dismissible-upsell")).not.toBeInTheDocument()
// })

// it("shows DismissibleUpsell when user is not authenticated and has run 4 or more tasks", async () => {
// 	const { getByTestId } = renderChatView()

// 		// Hydrate state with user not authenticated and 4+ tasks in history
// 		mockPostMessage({
// 			cloudIsAuthenticated: false,
// 			taskHistory: [
// 				{ id: "1", ts: Date.now() - 3000 },
// 				{ id: "2", ts: Date.now() - 2000 },
// 				{ id: "3", ts: Date.now() - 1000 },
// 				{ id: "4", ts: Date.now() },
// 			],
// 			clineMessages: [], // No active task
// 		})

// 	// Wait for component to render and show DismissibleUpsell
// 	await waitFor(() => {
// 		expect(getByTestId("dismissible-upsell")).toBeInTheDocument()
// 	})
// })

// it("shows DismissibleUpsell when user is not authenticated and has run 5 tasks", async () => {
// 	const { getByTestId } = renderChatView()

// 		// Hydrate state with user not authenticated and 5 tasks in history
// 		mockPostMessage({
// 			cloudIsAuthenticated: false,
// 			taskHistory: [
// 				{ id: "1", ts: Date.now() - 4000 },
// 				{ id: "2", ts: Date.now() - 3000 },
// 				{ id: "3", ts: Date.now() - 2000 },
// 				{ id: "4", ts: Date.now() - 1000 },
// 				{ id: "5", ts: Date.now() },
// 			],
// 			clineMessages: [], // No active task
// 		})

// 	// Wait for component to render and show DismissibleUpsell
// 	await waitFor(() => {
// 		expect(getByTestId("dismissible-upsell")).toBeInTheDocument()
// 	})
// })

// it("does not show DismissibleUpsell when there is an active task (regardless of auth status)", async () => {
// 	const { queryByTestId } = renderChatView()

// 		// Hydrate state with user not authenticated, 4+ tasks, but with an active task
// 		mockPostMessage({
// 			cloudIsAuthenticated: false,
// 			taskHistory: [
// 				{ id: "1", ts: Date.now() - 3000 },
// 				{ id: "2", ts: Date.now() - 2000 },
// 				{ id: "3", ts: Date.now() - 1000 },
// 				{ id: "4", ts: Date.now() },
// 			],
// 			clineMessages: [
// 				{
// 					type: "say",
// 					say: "task",
// 					ts: Date.now(),
// 					text: "Active task in progress",
// 				},
// 			],
// 		})

// 	// Wait for component to render with active task
// 	await waitFor(() => {
// 		// Should not show DismissibleUpsell during active task
// 		expect(queryByTestId("dismissible-upsell")).not.toBeInTheDocument()
// 		// Should not show RooTips either since the entire welcome screen is hidden during active tasks
// 		expect(queryByTestId("roo-tips")).not.toBeInTheDocument()
// 		// Should not show RooHero either since the entire welcome screen is hidden during active tasks
// 		expect(queryByTestId("roo-hero")).not.toBeInTheDocument()
// 	})
// })

// it("shows RooTips when user is authenticated (instead of DismissibleUpsell)", () => {
// 	const { queryByTestId, getByTestId } = renderChatView()

// 		// Hydrate state with user authenticated to cloud
// 		mockPostMessage({
// 			cloudIsAuthenticated: true,
// 			taskHistory: [
// 				{ id: "1", ts: Date.now() - 3000 },
// 				{ id: "2", ts: Date.now() - 2000 },
// 				{ id: "3", ts: Date.now() - 1000 },
// 				{ id: "4", ts: Date.now() },
// 			],
// 			clineMessages: [], // No active task
// 		})

// 	// Should not show DismissibleUpsell but should show RooTips
// 	expect(queryByTestId("dismissible-upsell")).not.toBeInTheDocument()
// 	expect(getByTestId("roo-tips")).toBeInTheDocument()
// })

// it("shows RooTips when user has fewer than 4 tasks (instead of DismissibleUpsell)", () => {
// 	const { queryByTestId, getByTestId } = renderChatView()

// 		// Hydrate state with user not authenticated but fewer than 4 tasks
// 		mockPostMessage({
// 			cloudIsAuthenticated: false,
// 			taskHistory: [
// 				{ id: "1", ts: Date.now() - 2000 },
// 				{ id: "2", ts: Date.now() - 1000 },
// 				{ id: "3", ts: Date.now() },
// 			],
// 			clineMessages: [], // No active task
// 		})

// Should not show DismissibleUpsell but should show RooTips
// 		expect(queryByTestId("dismissible-upsell")).not.toBeInTheDocument()
// 		expect(getByTestId("roo-tips")).toBeInTheDocument()
// 	})
// })

// describe("ChatView - Message Queueing Tests", () => {
// 	beforeEach(() => {
// 		vi.clearAllMocks()
// 		// Reset the mock to clear any initial calls
// 		vi.mocked(vscode.postMessage).mockClear()
// 	})

// 	it("shows sending is disabled when task is active", async () => {
// 		const { getByTestId } = renderChatView()

// 		// Hydrate state with active task that should disable sending
// 		mockPostMessage({
// 			clineMessages: [
// 				{
// 					type: "say",
// 					say: "task",
// 					ts: Date.now() - 1000,
// 					text: "Task in progress",
// 				},
// 				{
// 					type: "ask",
// 					ask: "tool",
// 					ts: Date.now(),
// 					text: JSON.stringify({ tool: "readFile", path: "test.txt" }),
// 					partial: true, // Partial messages disable sending
// 				},
// 			],
// 		})

// 		// Wait for state to be updated and check that sending is disabled
// 		await waitFor(() => {
// 			const chatTextArea = getByTestId("chat-textarea")
// 			const input = chatTextArea.querySelector("input")!
// 			expect(input.getAttribute("data-sending-disabled")).toBe("true")
// 		})
// 	})

// 	it("shows sending is enabled when no task is active", async () => {
// 		const { getByTestId } = renderChatView()

// 		// Hydrate state with completed task
// 		mockPostMessage({
// 			clineMessages: [
// 				{
// 					type: "ask",
// 					ask: "completion_result",
// 					ts: Date.now(),
// 					text: "Task completed",
// 					partial: false,
// 				},
// 			],
// 		})

// 		// Wait for state to be updated
// 		await waitFor(() => {
// 			expect(getByTestId("chat-textarea")).toBeInTheDocument()
// 		})

// 		// Check that sending is enabled
// 		const chatTextArea = getByTestId("chat-textarea")
// 		const input = chatTextArea.querySelector("input")!
// 		expect(input.getAttribute("data-sending-disabled")).toBe("false")
// 	})
// })
