import React, { useEffect, useRef, useMemo, useCallback, useState } from "react";
import type { Task } from "../../types";
import type { GraphFilters } from "../types/graph";
import {
	buildDependencyGraph,
	generateMermaidFlowchart,
	filterGraph,
	extractTaskIdFromNodeId,
} from "../utils/dependency-graph";
import { ensureMermaid } from "../utils/mermaid";

interface DependencyViewProps {
	tasks: Task[];
	onEditTask: (task: Task) => void;
	filters?: GraphFilters;
}

export default function DependencyView({ tasks, onEditTask, filters }: DependencyViewProps) {
	const containerRef = useRef<HTMLDivElement>(null);
	const [error, setError] = useState<string | null>(null);
	const [isLoading, setIsLoading] = useState(true);

	// Create task lookup map
	const taskMap = useMemo(() => new Map(tasks.map((t) => [t.id, t])), [tasks]);

	// Build and filter graph, generate Mermaid code
	const { mermaidCode, nodeCount, edgeCount } = useMemo(() => {
		const fullGraph = buildDependencyGraph(tasks);
		const graph = filters ? filterGraph(fullGraph, filters) : fullGraph;
		return {
			mermaidCode: generateMermaidFlowchart(graph),
			nodeCount: graph.nodes.length,
			edgeCount: graph.edges.length,
		};
	}, [tasks, filters]);

	// Attach click handlers to rendered SVG nodes
	const attachClickHandlers = useCallback(
		(svg: SVGElement) => {
			// Find all node groups (Mermaid uses .node class)
			const nodes = svg.querySelectorAll(".node");
			for (const node of nodes) {
				const nodeEl = node as SVGElement;
				const nodeId = nodeEl.getAttribute("id") || "";
				const taskId = extractTaskIdFromNodeId(nodeId);

				if (taskId) {
					nodeEl.style.cursor = "pointer";

					// Click to open task details
					nodeEl.addEventListener("click", () => {
						const task = taskMap.get(taskId);
						if (task) onEditTask(task);
					});

					// Hover effects for dependency highlighting
					nodeEl.addEventListener("mouseenter", () => {
						highlightDependencyPath(svg, taskId, taskMap);
					});
					nodeEl.addEventListener("mouseleave", () => {
						clearHighlights(svg);
					});
				}
			}
		},
		[taskMap, onEditTask],
	);

	// Render Mermaid diagram
	useEffect(() => {
		if (!containerRef.current) return;

		const render = async () => {
			setIsLoading(true);
			setError(null);

			try {
				const m = await ensureMermaid();

				// Initialize with loose security to allow click handlers
				m.default.initialize({
					startOnLoad: false,
					securityLevel: "loose",
					theme: "default",
				});

				// Generate unique ID for this render
				const id = `dependency-graph-${Date.now()}`;

				// Render the diagram
				const result = await m.default.render(id, mermaidCode);

				if (containerRef.current) {
					containerRef.current.innerHTML = result.svg;

					// Bind any Mermaid-provided functions
					if (result.bindFunctions && containerRef.current) {
						result.bindFunctions(containerRef.current);
					}

					// Attach our custom click handlers
					const svgElement = containerRef.current.querySelector("svg");
					if (svgElement) {
						attachClickHandlers(svgElement);
					}
				}
			} catch (err) {
				console.error("Failed to render dependency graph:", err);
				setError(err instanceof Error ? err.message : "Failed to render graph");
			} finally {
				setIsLoading(false);
			}
		};

		render();
	}, [mermaidCode, attachClickHandlers]);

	// Empty state
	if (tasks.length === 0) {
		return (
			<div className="flex items-center justify-center h-96 bg-white dark:bg-gray-800 rounded-lg border border-gray-200 dark:border-gray-700">
				<div className="text-center text-gray-500 dark:text-gray-400">
					<svg className="w-16 h-16 mx-auto mb-4 opacity-50" fill="none" stroke="currentColor" viewBox="0 0 24 24">
						<path
							strokeLinecap="round"
							strokeLinejoin="round"
							strokeWidth={1}
							d="M13.828 10.172a4 4 0 00-5.656 0l-4 4a4 4 0 105.656 5.656l1.102-1.101m-.758-4.899a4 4 0 005.656 0l4-4a4 4 0 00-5.656-5.656l-1.1 1.1"
						/>
					</svg>
					<p className="text-lg font-medium">No tasks to display</p>
					<p className="text-sm mt-1">Create some tasks to see the dependency graph</p>
				</div>
			</div>
		);
	}

	// No nodes after filtering
	if (nodeCount === 0) {
		return (
			<div className="flex items-center justify-center h-96 bg-white dark:bg-gray-800 rounded-lg border border-gray-200 dark:border-gray-700">
				<div className="text-center text-gray-500 dark:text-gray-400">
					<svg className="w-16 h-16 mx-auto mb-4 opacity-50" fill="none" stroke="currentColor" viewBox="0 0 24 24">
						<path
							strokeLinecap="round"
							strokeLinejoin="round"
							strokeWidth={1}
							d="M3 4a1 1 0 011-1h16a1 1 0 011 1v2.586a1 1 0 01-.293.707l-6.414 6.414a1 1 0 00-.293.707V17l-4 4v-6.586a1 1 0 00-.293-.707L3.293 7.293A1 1 0 013 6.586V4z"
						/>
					</svg>
					<p className="text-lg font-medium">No tasks match filters</p>
					<p className="text-sm mt-1">Try adjusting your filter criteria</p>
				</div>
			</div>
		);
	}

	return (
		<div className="relative">
			{/* Stats bar */}
			<div className="flex items-center justify-between mb-2 text-sm text-gray-500 dark:text-gray-400">
				<span>
					{nodeCount} task{nodeCount !== 1 ? "s" : ""} • {edgeCount} dependenc{edgeCount !== 1 ? "ies" : "y"}
				</span>
				<span className="text-xs">Click a task to view details • Hover to highlight dependencies</span>
			</div>

			{/* Loading overlay */}
			{isLoading && (
				<div className="absolute inset-0 flex items-center justify-center bg-white/50 dark:bg-gray-800/50 z-10">
					<div className="flex items-center gap-2 text-gray-600 dark:text-gray-300">
						<svg className="animate-spin h-5 w-5" fill="none" viewBox="0 0 24 24">
							<circle className="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" strokeWidth="4" />
							<path
								className="opacity-75"
								fill="currentColor"
								d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"
							/>
						</svg>
						<span>Loading graph...</span>
					</div>
				</div>
			)}

			{/* Error state */}
			{error && (
				<div className="p-4 bg-red-50 dark:bg-red-900/20 border border-red-200 dark:border-red-800 rounded-lg text-red-700 dark:text-red-300">
					<p className="font-medium">Failed to render graph</p>
					<p className="text-sm mt-1">{error}</p>
				</div>
			)}

			{/* Graph container */}
			<div
				className="w-full overflow-auto bg-white dark:bg-gray-800 rounded-lg border border-gray-200 dark:border-gray-700"
				style={{ minHeight: "500px" }}
			>
				<div
					ref={containerRef}
					className="min-h-[500px] p-4 dependency-graph-container"
					style={{ minWidth: "100%" }}
				/>
			</div>

			{/* Legend */}
			<div className="flex flex-wrap items-center gap-4 mt-4 text-sm">
				<span className="text-gray-500 dark:text-gray-400">Legend:</span>
				<div className="flex items-center gap-2">
					<span className="w-4 h-4 rounded" style={{ backgroundColor: "#22c55e" }} />
					<span className="text-gray-600 dark:text-gray-300">Done</span>
				</div>
				<div className="flex items-center gap-2">
					<span className="w-4 h-4 rounded" style={{ backgroundColor: "#3b82f6" }} />
					<span className="text-gray-600 dark:text-gray-300">In Progress</span>
				</div>
				<div className="flex items-center gap-2">
					<span className="w-4 h-4 rounded" style={{ backgroundColor: "#6b7280" }} />
					<span className="text-gray-600 dark:text-gray-300">To Do</span>
				</div>
				<div className="flex items-center gap-2">
					<span className="w-4 h-4 rounded border-2" style={{ borderColor: "#ef4444" }} />
					<span className="text-gray-600 dark:text-gray-300">High Priority</span>
				</div>
			</div>
		</div>
	);
}

/**
 * Highlight the dependency path for a task (its dependencies and dependents)
 */
function highlightDependencyPath(svg: SVGElement, taskId: string, taskMap: Map<string, Task>): void {
	const task = taskMap.get(taskId);
	if (!task) return;

	// Build set of connected task IDs
	const connectedIds = new Set<string>([taskId]);
	for (const depId of task.dependencies || []) {
		connectedIds.add(depId);
	}
	// Find tasks that depend on this one
	for (const [id, t] of taskMap) {
		if (t.dependencies?.includes(taskId)) {
			connectedIds.add(id);
		}
	}

	// Dim non-connected nodes
	const allNodes = svg.querySelectorAll(".node");
	for (const node of allNodes) {
		const nodeEl = node as SVGElement;
		const nodeId = nodeEl.getAttribute("id") || "";
		const nodeTaskId = extractTaskIdFromNodeId(nodeId);

		if (nodeTaskId && !connectedIds.has(nodeTaskId)) {
			nodeEl.style.opacity = "0.3";
		}
	}

	// Dim non-connected edges
	const allEdges = svg.querySelectorAll(".edgePath");
	for (const edge of allEdges) {
		const edgeEl = edge as SVGElement;
		const edgeId = edgeEl.getAttribute("id") || "";

		// Check if edge connects to our task
		let isConnected = false;
		for (const connectedId of connectedIds) {
			if (edgeId.includes(connectedId)) {
				isConnected = true;
				break;
			}
		}

		if (!isConnected) {
			edgeEl.style.opacity = "0.1";
		} else {
			// Highlight connected edges
			const path = edgeEl.querySelector("path");
			if (path) {
				path.style.stroke = "#3b82f6";
				path.style.strokeWidth = "3";
			}
		}
	}
}

/**
 * Clear all highlight effects
 */
function clearHighlights(svg: SVGElement): void {
	// Reset node opacity
	const allNodes = svg.querySelectorAll(".node");
	for (const node of allNodes) {
		(node as SVGElement).style.opacity = "";
	}

	// Reset edge opacity and styles
	const allEdges = svg.querySelectorAll(".edgePath");
	for (const edge of allEdges) {
		const edgeEl = edge as SVGElement;
		edgeEl.style.opacity = "";
		const path = edgeEl.querySelector("path");
		if (path) {
			path.style.stroke = "";
			path.style.strokeWidth = "";
		}
	}
}
