"use client";

import type { ComponentType } from "react";
import Link from "next/link";
import {
  AlertTriangle,
  ArrowUpRight,
  CheckCircle2,
  CircleDot,
  Clock3,
  RefreshCw,
} from "lucide-react";

import type { ForgejoIssueMetrics, ForgejoRepository } from "@/lib/api-forgejo";
import { formatRelativeTimestamp } from "@/lib/formatters";
import { cn } from "@/lib/utils";

type ForgejoIssueMetricCardsProps = {
  metrics: ForgejoIssueMetrics | null;
  repositories: ForgejoRepository[];
  isLoading?: boolean;
  error?: string | null;
};

type MetricTone = "accent" | "success" | "warning" | "danger" | "muted";

type MetricCard = {
  title: string;
  value: string;
  caption: string;
  href: string;
  tone: MetricTone;
  icon: ComponentType<{ className?: string }>;
};

const numberFormatter = new Intl.NumberFormat("en-US");
const STALE_SYNC_THRESHOLD_MS = 24 * 60 * 60 * 1000;

const formatCount = (value: number | null | undefined): string =>
  numberFormatter.format(Math.max(0, Math.round(Number(value ?? 0))));

const parseDate = (value: string | null | undefined): Date | null => {
  if (!value) return null;
  const date = new Date(value);
  return Number.isNaN(date.getTime()) ? null : date;
};

const toneClasses: Record<MetricTone, string> = {
  accent:
    "border-[color:var(--accent)]/30 bg-[color:var(--accent-soft)] text-[color:var(--accent)]",
  success:
    "border-[color:var(--success)]/30 bg-[color:rgba(52,211,153,0.12)] text-[color:var(--success)]",
  warning:
    "border-[color:var(--warning)]/30 bg-[color:rgba(251,191,36,0.12)] text-[color:var(--warning)]",
  danger:
    "border-[color:var(--danger)]/30 bg-[color:rgba(248,113,113,0.12)] text-[color:var(--danger)]",
  muted:
    "border-[color:var(--border)] bg-[color:var(--surface-muted)] text-muted",
};

const newestDate = (dates: Date[]): Date | null => {
  if (dates.length === 0) return null;
  return dates.reduce((latest, date) =>
    date.getTime() > latest.getTime() ? date : latest,
  );
};

function buildSyncHealthCard(
  metrics: ForgejoIssueMetrics | null,
  repositories: ForgejoRepository[],
): MetricCard {
  const repositoryCount = repositories.length;
  const syncErrorCount = Object.values(metrics?.sync_error_counts ?? {}).filter(
    (count) => Number(count) > 0,
  ).length;
  const metricSyncDates = Object.values(
    metrics?.last_sync_timestamps ?? {},
  ).flatMap((value) => {
    const date = parseDate(value);
    return date ? [date] : [];
  });
  const repositorySyncDates = repositories.flatMap((repository) => {
    const date = parseDate(repository.last_sync_at);
    return date ? [date] : [];
  });
  const latestSync = newestDate(
    metricSyncDates.length > 0 ? metricSyncDates : repositorySyncDates,
  );
  const latestSyncAge = latestSync
    ? Date.now() - latestSync.getTime()
    : Number.POSITIVE_INFINITY;

  if (repositoryCount === 0) {
    return {
      title: "Last Sync Health",
      value: "No repos",
      caption: "Add repositories to track sync status.",
      href: "/git-projects/repositories",
      tone: "muted",
      icon: RefreshCw,
    };
  }

  if (syncErrorCount > 0) {
    return {
      title: "Last Sync Health",
      value: `${formatCount(syncErrorCount)} repo${syncErrorCount === 1 ? "" : "s"}`,
      caption: "Repository sync needs attention.",
      href: "/git-projects/repositories",
      tone: "danger",
      icon: AlertTriangle,
    };
  }

  if (!latestSync) {
    return {
      title: "Last Sync Health",
      value: "Waiting",
      caption: "Repositories have not synced yet.",
      href: "/git-projects/repositories",
      tone: "warning",
      icon: Clock3,
    };
  }

  if (latestSyncAge > STALE_SYNC_THRESHOLD_MS) {
    return {
      title: "Last Sync Health",
      value: "Stale",
      caption: `Last sync ${formatRelativeTimestamp(latestSync.toISOString())}.`,
      href: "/git-projects/repositories",
      tone: "warning",
      icon: Clock3,
    };
  }

  return {
    title: "Last Sync Health",
    value: "Healthy",
    caption: `Last sync ${formatRelativeTimestamp(latestSync.toISOString())}.`,
    href: "/git-projects/repositories",
    tone: "success",
    icon: CheckCircle2,
  };
}

function MetricSkeleton() {
  return (
    <div className="rounded-xl border border-[color:var(--border)] bg-[color:var(--surface-muted)] p-4">
      <div className="h-4 w-28 animate-pulse rounded bg-[color:var(--surface-strong)]" />
      <div className="mt-4 h-8 w-16 animate-pulse rounded bg-[color:var(--surface-strong)]" />
      <div className="mt-3 h-3 w-36 animate-pulse rounded bg-[color:var(--surface-strong)]" />
    </div>
  );
}

function MetricCardLink({ card }: { card: MetricCard }) {
  const Icon = card.icon;

  return (
    <Link
      href={card.href}
      className="group flex min-w-0 flex-col justify-between rounded-xl border border-[color:var(--border)] bg-[color:var(--surface-muted)] p-4 transition hover:-translate-y-0.5 hover:border-[color:var(--accent)] focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[color:var(--accent)]"
    >
      <div className="flex items-start justify-between gap-3">
        <div className="min-w-0">
          <p className="text-xs font-semibold uppercase tracking-[0.14em] text-muted">
            {card.title}
          </p>
          <p className="mt-3 break-words font-heading text-3xl font-semibold text-strong">
            {card.value}
          </p>
        </div>
        <div
          className={cn(
            "shrink-0 rounded-lg border p-2 transition group-hover:scale-105",
            toneClasses[card.tone],
          )}
        >
          <Icon className="h-4 w-4" />
        </div>
      </div>
      <div className="mt-4 flex items-center justify-between gap-3">
        <p className="min-w-0 text-sm text-muted">{card.caption}</p>
        <ArrowUpRight className="h-4 w-4 shrink-0 text-muted transition group-hover:text-[color:var(--accent)]" />
      </div>
    </Link>
  );
}

export function ForgejoIssueMetricCards({
  metrics,
  repositories,
  isLoading = false,
  error,
}: ForgejoIssueMetricCardsProps) {
  const openIssues = metrics?.open_issues ?? 0;
  const recentlyClosed = metrics?.closed_last_7_days ?? 0;
  const staleOpen = metrics?.stale_open_issues ?? 0;
  const repositoriesSynced =
    metrics?.repositories_synced ?? repositories.length;
  const cards: MetricCard[] = [
    {
      title: "Open Issues",
      value: formatCount(openIssues),
      caption:
        openIssues === 0
          ? "No open Git Project issues."
          : "Review open issues across Git Projects.",
      href: "/git-projects/issues?state=open",
      tone: openIssues > 0 ? "accent" : "muted",
      icon: CircleDot,
    },
    {
      title: "Recently Closed",
      value: formatCount(recentlyClosed),
      caption: "Closed in the last 7 days.",
      href: "/git-projects/issues?state=closed&recent=7d",
      tone: recentlyClosed > 0 ? "success" : "muted",
      icon: CheckCircle2,
    },
    {
      title: "Stale Open Issues",
      value: formatCount(staleOpen),
      caption:
        staleOpen === 0
          ? "No stale open issues detected."
          : "Open issues without recent movement.",
      href: "/git-projects/issues?state=open&stale=1",
      tone: staleOpen > 0 ? "warning" : "success",
      icon: Clock3,
    },
    buildSyncHealthCard(metrics, repositories),
  ];

  return (
    <section className="rounded-xl border border-[color:var(--border)] bg-[color:var(--surface)] p-4 shadow-lush md:p-6">
      <div className="mb-4 flex flex-col gap-3 sm:flex-row sm:items-start sm:justify-between">
        <div className="min-w-0">
          <h3 className="text-lg font-semibold text-strong">
            Git Project Issue Tracking
          </h3>
          <p className="mt-1 text-sm text-muted">
            High-level Forgejo issue health across repositories synced into
            Pipeline.
          </p>
        </div>
        <Link
          href="/git-projects/issues"
          className="inline-flex w-fit items-center gap-1 text-sm font-medium text-[color:var(--accent)] transition hover:text-[color:var(--accent-strong)]"
        >
          Open issues
          <ArrowUpRight className="h-4 w-4" />
        </Link>
      </div>

      {error ? (
        <div className="mb-4 flex items-start gap-2 rounded-lg border border-[color:var(--warning)]/35 bg-[color:rgba(251,191,36,0.12)] p-3 text-sm text-[color:var(--warning)]">
          <AlertTriangle className="mt-0.5 h-4 w-4 shrink-0" />
          <span>{error}</span>
        </div>
      ) : null}

      <div className="grid grid-cols-1 gap-3 sm:grid-cols-2 xl:grid-cols-4">
        {isLoading
          ? Array.from({ length: 4 }).map((_, index) => (
              <MetricSkeleton key={index} />
            ))
          : cards.map((card) => (
              <MetricCardLink key={card.title} card={card} />
            ))}
      </div>

      {!isLoading && !error && repositories.length === 0 ? (
        <div className="mt-4 rounded-lg border border-dashed border-[color:var(--border)] bg-[color:var(--surface-muted)] p-3 text-sm text-muted">
          No Git Project repositories are configured yet. Metrics will populate
          after repositories are added and synced.
        </div>
      ) : !isLoading && !error && repositoriesSynced === 0 ? (
        <div className="mt-4 rounded-lg border border-dashed border-[color:var(--border)] bg-[color:var(--surface-muted)] p-3 text-sm text-muted">
          Git Project repositories are configured, but Pipeline has not synced
          issue metrics yet.
        </div>
      ) : null}

    </section>
  );
}
