"use client";

import type { ComponentType } from "react";
import Link from "next/link";
import {
  AlertCircle,
  AlertTriangle,
  ArrowUpRight,
  CheckCircle2,
  Clock3,
  RefreshCw,
  ShieldAlert,
  ShieldCheck,
} 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;
};

// Extended tone set — covers every semantic state
type MetricTone = "amber" | "success" | "danger" | "cyan" | "slate" | "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 newestDate = (dates: Date[]): Date | null => {
  if (dates.length === 0) return null;
  return dates.reduce((latest, date) =>
    date.getTime() > latest.getTime() ? date : latest,
  );
};

// ── Tone → icon badge (background + text color) ────────────────────────────
const toneIconClasses: Record<MetricTone, string> = {
  amber:   "border-[color:rgba(245,158,11,0.35)] bg-[color:rgba(245,158,11,0.14)] text-[color:#F59E0B]",
  success: "border-[color:rgba(16,185,129,0.35)] bg-[color:rgba(16,185,129,0.14)] text-[color:#10B981]",
  danger:  "border-[color:rgba(248,113,113,0.35)] bg-[color:rgba(248,113,113,0.14)] text-[color:var(--danger)]",
  cyan:    "border-[color:rgba(6,182,212,0.35)]   bg-[color:rgba(6,182,212,0.14)]   text-[color:#06B6D4]",
  slate:   "border-[color:rgba(100,116,139,0.35)] bg-[color:rgba(100,116,139,0.12)] text-[color:#64748B]",
  muted:   "border-[color:var(--border)]           bg-[color:var(--surface-muted)]   text-muted",
};

// ── Tone → card (full background + border + hover glow) ───────────────────
const toneCardClasses: Record<MetricTone, string> = {
  amber:   "border-[color:rgba(245,158,11,0.28)]  bg-[color:rgba(245,158,11,0.06)]  hover:border-[color:rgba(245,158,11,0.55)]  hover:shadow-[0_4px_24px_rgba(245,158,11,0.18)]",
  success: "border-[color:rgba(16,185,129,0.28)]  bg-[color:rgba(16,185,129,0.06)]  hover:border-[color:rgba(16,185,129,0.55)]  hover:shadow-[0_4px_24px_rgba(16,185,129,0.18)]",
  danger:  "border-[color:rgba(248,113,113,0.28)] bg-[color:rgba(248,113,113,0.06)] hover:border-[color:rgba(248,113,113,0.55)] hover:shadow-[0_4px_24px_rgba(248,113,113,0.18)]",
  cyan:    "border-[color:rgba(6,182,212,0.28)]   bg-[color:rgba(6,182,212,0.06)]   hover:border-[color:rgba(6,182,212,0.55)]   hover:shadow-[0_4px_24px_rgba(6,182,212,0.18)]",
  slate:   "border-[color:rgba(100,116,139,0.22)] bg-[color:rgba(100,116,139,0.05)] hover:border-[color:rgba(100,116,139,0.40)] hover:shadow-[0_4px_16px_rgba(100,116,139,0.12)]",
  muted:   "border-[color:var(--border)]           bg-[color:var(--surface-muted)]   hover:border-[color:var(--border-strong)]   hover:shadow-sm",
};

// ── Tone → value text color ────────────────────────────────────────────────
const toneValueClasses: Record<MetricTone, string> = {
  amber:   "text-[color:#F59E0B]",
  success: "text-[color:#10B981]",
  danger:  "text-[color:var(--danger)]",
  cyan:    "text-[color:#06B6D4]",
  slate:   "text-[color:#64748B]",
  muted:   "text-strong",
};

// ── Card builder: Last Sync Health ─────────────────────────────────────────
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(
    (v) => { const d = parseDate(v); return d ? [d] : []; },
  );
  const repositorySyncDates = repositories.flatMap(
    (r) => { const d = parseDate(r.last_sync_at); return d ? [d] : []; },
  );
  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: ShieldAlert,
    };
  }
  if (!latestSync) {
    return {
      title: "Last Sync Health",
      value: "Waiting",
      caption: "Repositories have not synced yet.",
      href: "/git-projects/repositories",
      tone: "slate",
      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: "amber",
      icon: Clock3,
    };
  }
  return {
    title: "Last Sync Health",
    value: "Healthy",
    caption: `Last sync ${formatRelativeTimestamp(latestSync.toISOString())}.`,
    href: "/git-projects/repositories",
    tone: "cyan",
    icon: ShieldCheck,
  };
}

// ── Skeleton ───────────────────────────────────────────────────────────────
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>
  );
}

// ── Card renderer ──────────────────────────────────────────────────────────
function MetricCardLink({ card }: { card: MetricCard }) {
  const Icon = card.icon;

  return (
    <Link
      href={card.href}
      className={cn(
        "group flex min-w-0 flex-col justify-between rounded-xl border p-4 transition-all duration-200 hover:-translate-y-0.5 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[color:var(--accent)]",
        toneCardClasses[card.tone],
      )}
    >
      <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={cn("mt-3 break-words font-heading text-3xl font-semibold", toneValueClasses[card.tone])}>
            {card.value}
          </p>
        </div>
        <div
          className={cn(
            "shrink-0 rounded-lg border p-2 transition-transform duration-200 group-hover:scale-110",
            toneIconClasses[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>
  );
}

// ── Main export ────────────────────────────────────────────────────────────
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;

  // Stale: 0 → slate, 1–5 → amber, >5 → danger
  const staleTone: MetricTone =
    staleOpen === 0 ? "slate" :
    staleOpen <= 5  ? "amber" :
    "danger";

  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 ? "amber" : "muted",
      icon: openIssues > 0 ? AlertCircle : CheckCircle2,
    },
    {
      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
          ? "Nothing abandoned right now."
          : "Open issues without recent movement.",
      href: "/git-projects/issues?state=open&stale=1",
      tone: staleTone,
      icon: staleOpen === 0 ? CheckCircle2 : 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>

      {/* Warning banner — left accent border, brighter amber */}
      {error ? (
        <div className="mb-4 flex items-start gap-3 rounded-lg border border-[color:rgba(245,158,11,0.45)] bg-[color:rgba(245,158,11,0.10)] p-3 text-sm text-[color:#F59E0B] [border-left:3px_solid_#F59E0B]">
          <AlertTriangle className="mt-0.5 h-4 w-4 shrink-0 text-[color:#F59E0B]" />
          <span className="font-medium">{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((_, i) => <MetricSkeleton key={i} />)
          : 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>
  );
}
