import type { Task } from "../types/index.ts";

export interface VelocityStats {
	/** Tasks completed in the last 7 days */
	completedLast7Days: number;
	/** Average time from To Do to Done in milliseconds */
	avgCycleTime: number | null;
	/** Average time from To Do to In Progress in milliseconds */
	avgTimeToStart: number | null;
	/** Average tasks completed per week (based on last 4 weeks) */
	weeklyThroughput: number;
	/** Weekly completion counts for the last 4 weeks [this week, last week, 2 weeks ago, 3 weeks ago] */
	weeklyCompletions: number[];
	/** Number of tasks with status history data */
	tasksWithHistory: number;
}

export interface TaskStatistics {
	statusCounts: Map<string, number>;
	priorityCounts: Map<string, number>;
	totalTasks: number;
	completedTasks: number;
	completionPercentage: number;
	draftCount: number;
	recentActivity: {
		created: Task[];
		updated: Task[];
	};
	projectHealth: {
		averageTaskAge: number;
		staleTasks: Task[];
		blockedTasks: Task[];
	};
	velocity: VelocityStats;
	/** Tasks marked for "Do Today" */
	doTodayTasks: Task[];
}

/**
 * Parse a timestamp string to Date object
 */
function parseTimestamp(ts: string | undefined): Date | null {
	if (!ts) return null;
	// Handle "YYYY-MM-DD HH:mm" format
	const date = new Date(ts.replace(" ", "T"));
	return Number.isNaN(date.getTime()) ? null : date;
}

/**
 * Calculate velocity metrics from task status history
 */
function calculateVelocityStats(tasks: Task[]): VelocityStats {
	const now = new Date();
	const sevenDaysAgo = new Date(now.getTime() - 7 * 24 * 60 * 60 * 1000);
	const fourWeeksAgo = new Date(now.getTime() - 28 * 24 * 60 * 60 * 1000);

	let completedLast7Days = 0;
	const cycleTimes: number[] = [];
	const timesToStart: number[] = [];
	const weeklyCompletions = [0, 0, 0, 0]; // Last 4 weeks
	let tasksWithHistory = 0;

	for (const task of tasks) {
		const history = task.statusHistory || [];
		if (history.length === 0) continue;

		tasksWithHistory++;

		// Find status transitions
		let todoTime: Date | null = null;
		let inProgressTime: Date | null = null;
		let doneTime: Date | null = null;

		for (const entry of history) {
			const ts = parseTimestamp(entry.timestamp);
			if (!ts) continue;
			const status = entry.status.toLowerCase();
			if (status === "to do" && !todoTime) todoTime = ts;
			if (status === "in progress" && !inProgressTime) inProgressTime = ts;
			if (status === "done" && !doneTime) doneTime = ts;
		}

		// Count completions in last 7 days
		if (doneTime && doneTime >= sevenDaysAgo) {
			completedLast7Days++;
		}

		// Track weekly completions
		if (doneTime && doneTime >= fourWeeksAgo) {
			const weekIndex = Math.floor((now.getTime() - doneTime.getTime()) / (7 * 24 * 60 * 60 * 1000));
			if (weekIndex >= 0 && weekIndex < 4 && weeklyCompletions[weekIndex] !== undefined) {
				weeklyCompletions[weekIndex] = weeklyCompletions[weekIndex] + 1;
			}
		}

		// Calculate cycle time (To Do -> Done)
		if (todoTime && doneTime && doneTime > todoTime) {
			cycleTimes.push(doneTime.getTime() - todoTime.getTime());
		}

		// Calculate time to start (To Do -> In Progress)
		if (todoTime && inProgressTime && inProgressTime > todoTime) {
			timesToStart.push(inProgressTime.getTime() - todoTime.getTime());
		}
	}

	return {
		completedLast7Days,
		avgCycleTime: cycleTimes.length > 0 ? cycleTimes.reduce((a, b) => a + b, 0) / cycleTimes.length : null,
		avgTimeToStart: timesToStart.length > 0 ? timesToStart.reduce((a, b) => a + b, 0) / timesToStart.length : null,
		weeklyThroughput: weeklyCompletions.reduce((a, b) => a + b, 0) / 4,
		weeklyCompletions,
		tasksWithHistory,
	};
}

/**
 * Calculate comprehensive task statistics for the overview
 */
export function getTaskStatistics(tasks: Task[], drafts: Task[], statuses: string[]): TaskStatistics {
	const statusCounts = new Map<string, number>();
	const priorityCounts = new Map<string, number>();

	// Initialize status counts
	for (const status of statuses) {
		statusCounts.set(status, 0);
	}

	// Initialize priority counts
	priorityCounts.set("high", 0);
	priorityCounts.set("medium", 0);
	priorityCounts.set("low", 0);
	priorityCounts.set("none", 0);

	let completedTasks = 0;
	const now = new Date();
	const oneWeekAgo = new Date(now.getTime() - 7 * 24 * 60 * 60 * 1000);
	const oneMonthAgo = new Date(now.getTime() - 30 * 24 * 60 * 60 * 1000);

	const recentlyCreated: Task[] = [];
	const recentlyUpdated: Task[] = [];
	const staleTasks: Task[] = [];
	const blockedTasks: Task[] = [];
	const doTodayTasks: Task[] = [];
	let totalAge = 0;
	let taskCount = 0;

	// Process each task
	for (const task of tasks) {
		// Skip tasks with empty or undefined status
		if (!task.status || task.status === "") {
			continue;
		}

		// Track "Do Today" tasks
		if (task.doToday) {
			doTodayTasks.push(task);
		}

		// Count by status
		const currentCount = statusCounts.get(task.status) || 0;
		statusCounts.set(task.status, currentCount + 1);

		// Count completed tasks
		if (task.status === "Done") {
			completedTasks++;
		}

		// Count by priority
		const priority = task.priority || "none";
		const priorityCount = priorityCounts.get(priority) || 0;
		priorityCounts.set(priority, priorityCount + 1);

		// Track recent activity
		if (task.createdDate) {
			const createdDate = new Date(task.createdDate);
			if (createdDate >= oneWeekAgo) {
				recentlyCreated.push(task);
			}

			// Calculate task age
			// For completed tasks, use the time from creation to completion
			// For active tasks, use the time from creation to now
			let ageInDays: number;
			if (task.status === "Done" && task.updatedDate) {
				const updatedDate = new Date(task.updatedDate);
				ageInDays = Math.floor((updatedDate.getTime() - createdDate.getTime()) / (24 * 60 * 60 * 1000));
			} else {
				ageInDays = Math.floor((now.getTime() - createdDate.getTime()) / (24 * 60 * 60 * 1000));
			}
			totalAge += ageInDays;
			taskCount++;
		}

		if (task.updatedDate) {
			const updatedDate = new Date(task.updatedDate);
			if (updatedDate >= oneWeekAgo) {
				recentlyUpdated.push(task);
			}
		}

		// Identify stale tasks (not updated in 30 days and not done)
		if (task.status !== "Done") {
			const lastDate = task.updatedDate || task.createdDate;
			if (lastDate) {
				const date = new Date(lastDate);
				if (date < oneMonthAgo) {
					staleTasks.push(task);
				}
			}
		}

		// Identify blocked tasks (has dependencies that are not done)
		if (task.dependencies && task.dependencies.length > 0 && task.status !== "Done") {
			// Check if any dependency is not done
			const hasBlockingDependency = task.dependencies.some((depId) => {
				const dep = tasks.find((t) => t.id === depId);
				return dep && dep.status !== "Done";
			});

			if (hasBlockingDependency) {
				blockedTasks.push(task);
			}
		}
	}

	// Sort recent activity by date
	recentlyCreated.sort((a, b) => {
		const dateA = new Date(a.createdDate || 0);
		const dateB = new Date(b.createdDate || 0);
		return dateB.getTime() - dateA.getTime();
	});

	recentlyUpdated.sort((a, b) => {
		const dateA = new Date(a.updatedDate || 0);
		const dateB = new Date(b.updatedDate || 0);
		return dateB.getTime() - dateA.getTime();
	});

	// Calculate average task age
	const averageTaskAge = taskCount > 0 ? Math.round(totalAge / taskCount) : 0;

	// Calculate completion percentage (only count tasks with valid status)
	const totalTasks = Array.from(statusCounts.values()).reduce((sum, count) => sum + count, 0);
	const completionPercentage = totalTasks > 0 ? Math.round((completedTasks / totalTasks) * 100) : 0;

	// Calculate velocity stats
	const velocity = calculateVelocityStats(tasks);

	return {
		statusCounts,
		priorityCounts,
		totalTasks,
		completedTasks,
		completionPercentage,
		draftCount: drafts.length,
		recentActivity: {
			created: recentlyCreated.slice(0, 5), // Top 5 most recent
			updated: recentlyUpdated.slice(0, 5), // Top 5 most recent
		},
		projectHealth: {
			averageTaskAge,
			staleTasks: staleTasks.slice(0, 5), // Top 5 stale tasks
			blockedTasks: blockedTasks.slice(0, 5), // Top 5 blocked tasks
		},
		velocity,
		doTodayTasks,
	};
}
