import { Skeleton } from "@/components/ui/skeleton";
import { cn } from "@/lib/utils";
import { FullWidthBorder } from "./full-width-border";

type ParticipationData = {
	all: number[];
	owner: number[];
};

type ActivityLevel = 0 | 1 | 2 | 3 | 4;

const ACTIVITY_COLORS: Record<ActivityLevel, string> = {
	0: "bg-transparent",
	1: "bg-cossistant-orange/20",
	2: "bg-cossistant-orange/40",
	3: "bg-cossistant-orange/60",
	4: "bg-cossistant-orange/80",
};

function getActivityLevel(count: number, max: number): ActivityLevel {
	if (count === 0) {
		return 0;
	}
	const ratio = count / max;
	if (ratio <= 0.25) {
		return 1;
	}
	if (ratio <= 0.5) {
		return 2;
	}
	if (ratio <= 0.75) {
		return 3;
	}
	return 4;
}

async function fetchGitHubStats(): Promise<{
	weeklyData: number[];
	totalCommits: number;
	prCount: number;
}> {
	const [participationRes, prRes] = await Promise.all([
		fetch(
			"https://api.github.com/repos/cossistantcom/cossistant/stats/participation",
			{
				next: { revalidate: 86_400 },
			}
		),
		fetch(
			"https://api.github.com/search/issues?q=repo:cossistantcom/cossistant+type:pr+created:>2024-01-01",
			{
				next: { revalidate: 86_400 },
			}
		),
	]);

	const participation: ParticipationData = await participationRes.json();
	const prData = await prRes.json();

	const weeklyData = participation.all ?? [];
	const totalCommits = weeklyData.reduce((acc, count) => acc + count, 0);
	const prCount = prData.total_count ?? 0;

	return { weeklyData, totalCommits, prCount };
}

function ActivityCell({
	count,
	maxCount,
	weekIndex,
	dayIndex,
}: {
	count: number;
	maxCount: number;
	weekIndex: number;
	dayIndex: number;
}) {
	const level = getActivityLevel(count, maxCount);

	return (
		<div
			className={cn(
				"aspect-square w-full border-[0.5px] border-background border-dashed",
				ACTIVITY_COLORS[level],
				"hover:bg-cossistant-orange",
				level === 0 && "border-primary/5"
			)}
			title={`Week ${weekIndex + 1}, Day ${dayIndex + 1}: ${count} commits`}
		/>
	);
}

export function GitHubActivityGraphSkeleton() {
	return (
		<div className="flex flex-col gap-6 py-8 md:py-12">
			{/* Header skeleton */}
			<div className="flex flex-col gap-3 px-4 text-center">
				<Skeleton className="h-6 w-48" />
				<Skeleton className="h-5 w-80" />
			</div>

			{/* Grid skeleton */}
			<div className="w-full">
				<div className="w-full p-3 md:p-4">
					<div className="grid w-full grid-flow-col grid-cols-52 grid-rows-7 gap-0.5 md:gap-1">
						{Array.from({ length: 52 * 7 }).map((_, i) => (
							<Skeleton
								className="aspect-square w-full"
								key={`skeleton-${i.toString()}`}
							/>
						))}
					</div>
				</div>
			</div>
		</div>
	);
}

export async function GitHubActivityGraph() {
	try {
		const { weeklyData, totalCommits, prCount } = await fetchGitHubStats();

		// Find max for normalization
		const maxWeeklyCommits = Math.max(...weeklyData, 1);

		// Generate daily data from weekly data
		// GitHub's participation API gives weekly totals, we'll distribute them across days
		// For a more accurate representation, we simulate daily activity
		const dailyData: number[][] = weeklyData.map((weekTotal) => {
			// Distribute weekly commits across 7 days with some variance
			const days: number[] = [];
			let remaining = weekTotal;

			for (let day = 0; day < 7; day++) {
				if (day === 6) {
					days.push(remaining);
				} else {
					// Distribute with slight randomness based on week index for determinism
					const portion = Math.floor(remaining / (7 - day));
					days.push(portion);
					remaining -= portion;
				}
			}
			return days;
		});

		// Calculate max daily commits for activity level normalization
		const maxDailyCommits = Math.max(...dailyData.flat(), 1);

		return (
			<div className="flex flex-col gap-6 pt-3">
				{/* Header */}
				<div className="relative flex flex-col gap-2 px-4">
					<h2 className="font-f37-stout text-xl md:text-2xl">Changelog</h2>
					<p className="text-muted-foreground">
						We&apos;re shipping a lot,{" "}
						<span className="font-medium text-cossistant-orange tabular-nums">
							{totalCommits.toLocaleString()} commits
						</span>{" "}
						and{" "}
						<span className="font-medium text-cossistant-orange tabular-nums">
							{prCount.toLocaleString()} PRs
						</span>{" "}
						in the past year.
					</p>
				</div>

				{/* Activity Grid */}
				<div className="w-full">
					<div className="relative w-full">
						<FullWidthBorder className="top-0" />
						<div className="grid w-full grid-flow-col grid-cols-52 grid-rows-7 gap-0 md:gap-0">
							{dailyData.map((week, weekIndex) =>
								week.map((dayCount, dayIndex) => (
									<ActivityCell
										count={dayCount}
										dayIndex={dayIndex}
										key={`cell-${weekIndex.toString()}-${dayIndex.toString()}`}
										maxCount={maxDailyCommits}
										weekIndex={weekIndex}
									/>
								))
							)}
						</div>
						<FullWidthBorder className="bottom-0" />
						<div className="-bottom-6 absolute right-3 flex items-center justify-center gap-2 text-muted-foreground text-xs">
							<span>Less</span>
							<div className="flex gap-0.5">
								{([0, 1, 2, 3, 4] as ActivityLevel[]).map((level) => (
									<div
										className={cn(
											"size-2 md:size-2.5 lg:size-3",
											"border border-dashed",
											ACTIVITY_COLORS[level]
										)}
										key={level}
									/>
								))}
							</div>
							<span>More</span>
						</div>
					</div>
				</div>
			</div>
		);
	} catch {
		// Fallback on error
		return (
			<div className="flex flex-col items-center gap-2 py-8 md:py-12">
				<h2 className="font-f37-stout text-3xl md:text-4xl">Changelog</h2>
				<p className="text-muted-foreground text-sm">
					Track our latest updates and improvements.
				</p>
			</div>
		);
	}
}
