import React, { useState, useEffect, useCallback, useRef } from "react";
import { createRoot } from "react-dom/client";

interface Project {
	path: string;
	name: string;
	color: string;
}

interface AggregatedTask {
	id: string;
	title: string;
	status: string;
	priority?: string;
	description?: string;
	assignee: string[];
	labels: string[];
	projectName: string;
	projectColor: string;
	projectPath: string;
	createdDate?: string;
	updatedDate?: string;
}

interface WebSocketMessage {
	type: "init" | "update";
	projects: Project[];
	tasks: AggregatedTask[];
	timestamp?: number;
}

function App() {
	const [projects, setProjects] = useState<Project[]>([]);
	const [tasks, setTasks] = useState<AggregatedTask[]>([]);
	const [connected, setConnected] = useState(false);
	const [lastUpdate, setLastUpdate] = useState<Date | null>(null);
	const [filter, setFilter] = useState<string>("");
	const [selectedProject, setSelectedProject] = useState<string | null>(null);
	const wsRef = useRef<WebSocket | null>(null);
	const reconnectTimeoutRef = useRef<ReturnType<typeof setTimeout> | null>(null);

	const connectWebSocket = useCallback(() => {
		const protocol = window.location.protocol === "https:" ? "wss:" : "ws:";
		const ws = new WebSocket(`${protocol}//${window.location.host}`);

		ws.onopen = () => {
			setConnected(true);
			console.log("WebSocket connected");
		};

		ws.onmessage = (event) => {
			try {
				const data: WebSocketMessage = JSON.parse(event.data);
				if (data.type === "init" || data.type === "update") {
					setProjects(data.projects);
					setTasks(data.tasks);
					setLastUpdate(new Date());
				}
			} catch (error) {
				console.error("Failed to parse WebSocket message:", error);
			}
		};

		ws.onclose = () => {
			setConnected(false);
			console.log("WebSocket disconnected, reconnecting...");
			reconnectTimeoutRef.current = setTimeout(connectWebSocket, 3000);
		};

		ws.onerror = (error) => {
			console.error("WebSocket error:", error);
		};

		wsRef.current = ws;
	}, []);

	useEffect(() => {
		connectWebSocket();
		return () => {
			wsRef.current?.close();
			if (reconnectTimeoutRef.current) {
				clearTimeout(reconnectTimeoutRef.current);
			}
		};
	}, [connectWebSocket]);

	// Group tasks by status
	const statuses = ["To Do", "In Progress", "Done"];
	const tasksByStatus = statuses.reduce(
		(acc, status) => {
			acc[status] = tasks.filter((t) => {
				const statusMatch = t.status.toLowerCase() === status.toLowerCase();
				const projectMatch = !selectedProject || t.projectName === selectedProject;
				const filterMatch =
					!filter ||
					t.title.toLowerCase().includes(filter.toLowerCase()) ||
					t.projectName.toLowerCase().includes(filter.toLowerCase());
				return statusMatch && projectMatch && filterMatch;
			});
			return acc;
		},
		{} as Record<string, AggregatedTask[]>,
	);

	return (
		<div
			style={{
				minHeight: "100vh",
				backgroundColor: "#0f172a",
				color: "#e2e8f0",
				fontFamily: "system-ui, -apple-system, sans-serif",
			}}
		>
			{/* Header */}
			<header
				style={{
					padding: "1rem 2rem",
					backgroundColor: "#1e293b",
					borderBottom: "1px solid #334155",
					display: "flex",
					justifyContent: "space-between",
					alignItems: "center",
				}}
			>
				<div style={{ display: "flex", alignItems: "center", gap: "1rem" }}>
					<h1 style={{ margin: 0, fontSize: "1.5rem", fontWeight: 600 }}>Backlog Aggregator</h1>
					<span
						style={{
							padding: "0.25rem 0.5rem",
							borderRadius: "9999px",
							fontSize: "0.75rem",
							backgroundColor: connected ? "#22c55e" : "#ef4444",
							color: "white",
						}}
					>
						{connected ? "Live" : "Reconnecting..."}
					</span>
				</div>
				<div style={{ display: "flex", alignItems: "center", gap: "1rem" }}>
					<span style={{ fontSize: "0.875rem", color: "#94a3b8" }}>
						{projects.length} projects | {tasks.length} tasks
						{lastUpdate && ` | Updated ${lastUpdate.toLocaleTimeString()}`}
					</span>
				</div>
			</header>

			{/* Project Filter Bar */}
			<div
				style={{
					padding: "1rem 2rem",
					backgroundColor: "#1e293b",
					display: "flex",
					gap: "0.5rem",
					flexWrap: "wrap",
					alignItems: "center",
				}}
			>
				<input
					type="text"
					placeholder="Filter tasks..."
					value={filter}
					onChange={(e) => setFilter(e.target.value)}
					style={{
						padding: "0.5rem 1rem",
						borderRadius: "0.375rem",
						border: "1px solid #334155",
						backgroundColor: "#0f172a",
						color: "#e2e8f0",
						minWidth: "200px",
					}}
				/>
				<button
					onClick={() => setSelectedProject(null)}
					style={{
						padding: "0.5rem 1rem",
						borderRadius: "0.375rem",
						border: selectedProject === null ? "2px solid #3b82f6" : "1px solid #334155",
						backgroundColor: selectedProject === null ? "#1e40af" : "#0f172a",
						color: "#e2e8f0",
						cursor: "pointer",
					}}
				>
					All Projects
				</button>
				{projects.map((project) => (
					<button
						key={project.path}
						onClick={() => setSelectedProject(project.name)}
						style={{
							padding: "0.5rem 1rem",
							borderRadius: "0.375rem",
							border: selectedProject === project.name ? `2px solid ${project.color}` : "1px solid #334155",
							backgroundColor: selectedProject === project.name ? project.color + "33" : "#0f172a",
							color: "#e2e8f0",
							cursor: "pointer",
							display: "flex",
							alignItems: "center",
							gap: "0.5rem",
						}}
					>
						<span
							style={{
								width: "0.75rem",
								height: "0.75rem",
								borderRadius: "50%",
								backgroundColor: project.color,
							}}
						/>
						{project.name}
					</button>
				))}
			</div>

			{/* Kanban Board */}
			<div
				style={{
					padding: "2rem",
					display: "grid",
					gridTemplateColumns: "repeat(3, 1fr)",
					gap: "1.5rem",
					minHeight: "calc(100vh - 180px)",
				}}
			>
				{statuses.map((status) => (
					<div
						key={status}
						style={{
							backgroundColor: "#1e293b",
							borderRadius: "0.5rem",
							padding: "1rem",
							display: "flex",
							flexDirection: "column",
						}}
					>
						{/* Column Header */}
						<div
							style={{
								display: "flex",
								justifyContent: "space-between",
								alignItems: "center",
								marginBottom: "1rem",
								paddingBottom: "0.5rem",
								borderBottom: "1px solid #334155",
							}}
						>
							<h2 style={{ margin: 0, fontSize: "1rem", fontWeight: 600 }}>{status}</h2>
							<span
								style={{
									backgroundColor: "#334155",
									padding: "0.25rem 0.5rem",
									borderRadius: "9999px",
									fontSize: "0.75rem",
								}}
							>
								{tasksByStatus[status]?.length || 0}
							</span>
						</div>

						{/* Tasks */}
						<div style={{ display: "flex", flexDirection: "column", gap: "0.75rem", flex: 1, overflowY: "auto" }}>
							{tasksByStatus[status]?.map((task) => (
								<TaskCard key={`${task.projectPath}:${task.id}`} task={task} />
							))}
							{(!tasksByStatus[status] || tasksByStatus[status].length === 0) && (
								<div style={{ color: "#64748b", textAlign: "center", padding: "2rem", fontSize: "0.875rem" }}>
									No tasks
								</div>
							)}
						</div>
					</div>
				))}
			</div>
		</div>
	);
}

function TaskCard({ task }: { task: AggregatedTask }) {
	const [expanded, setExpanded] = useState(false);

	const priorityColors: Record<string, string> = {
		high: "#ef4444",
		medium: "#f59e0b",
		low: "#22c55e",
	};

	return (
		<div
			onClick={() => setExpanded(!expanded)}
			style={{
				backgroundColor: "#0f172a",
				borderRadius: "0.375rem",
				padding: "0.75rem",
				cursor: "pointer",
				borderLeft: `4px solid ${task.projectColor}`,
				transition: "transform 0.1s, box-shadow 0.1s",
			}}
			onMouseEnter={(e) => {
				e.currentTarget.style.transform = "translateY(-1px)";
				e.currentTarget.style.boxShadow = "0 4px 6px -1px rgba(0, 0, 0, 0.3)";
			}}
			onMouseLeave={(e) => {
				e.currentTarget.style.transform = "translateY(0)";
				e.currentTarget.style.boxShadow = "none";
			}}
		>
			{/* Task Header */}
			<div style={{ display: "flex", justifyContent: "space-between", alignItems: "flex-start", gap: "0.5rem" }}>
				<div style={{ flex: 1 }}>
					<div style={{ fontSize: "0.875rem", fontWeight: 500, marginBottom: "0.25rem" }}>{task.title}</div>
					<div style={{ fontSize: "0.75rem", color: "#64748b" }}>
						{task.id} | {task.projectName}
					</div>
				</div>
				{task.priority && (
					<span
						style={{
							padding: "0.125rem 0.375rem",
							borderRadius: "0.25rem",
							fontSize: "0.625rem",
							fontWeight: 500,
							textTransform: "uppercase",
							backgroundColor: priorityColors[task.priority.toLowerCase()] + "22",
							color: priorityColors[task.priority.toLowerCase()],
						}}
					>
						{task.priority}
					</span>
				)}
			</div>

			{/* Labels */}
			{task.labels && task.labels.length > 0 && (
				<div style={{ display: "flex", gap: "0.25rem", flexWrap: "wrap", marginTop: "0.5rem" }}>
					{task.labels.map((label) => (
						<span
							key={label}
							style={{
								padding: "0.125rem 0.375rem",
								borderRadius: "0.25rem",
								fontSize: "0.625rem",
								backgroundColor: "#334155",
								color: "#94a3b8",
							}}
						>
							{label}
						</span>
					))}
				</div>
			)}

			{/* Expanded Details */}
			{expanded && task.description && (
				<div
					style={{
						marginTop: "0.75rem",
						paddingTop: "0.75rem",
						borderTop: "1px solid #334155",
						fontSize: "0.8rem",
						color: "#94a3b8",
						whiteSpace: "pre-wrap",
					}}
				>
					{task.description.slice(0, 500)}
					{task.description.length > 500 && "..."}
				</div>
			)}

			{/* Assignees */}
			{task.assignee && task.assignee.length > 0 && (
				<div style={{ marginTop: "0.5rem", fontSize: "0.75rem", color: "#64748b" }}>
					{task.assignee.join(", ")}
				</div>
			)}
		</div>
	);
}

// Mount the app
const root = createRoot(document.getElementById("root")!);
root.render(<App />);
