"use client";

import Link from "next/link";
import { useEffect, useMemo, useState } from "react";
import { Badge } from "@/components/ui/badge";
import { Button } from "@/components/ui/button";
import {
  AlertCard,
  AlertCardSummary,
} from "@/components/ui/alert-card";
import { ALL_ORGANIZATIONS } from "@/lib/sag/entities";
import {
  gatherUpcomingFilings,
  summarizeFilings,
  type UpcomingFiling,
  type UpcomingFilingSeverity,
} from "@/lib/compliance/upcoming-filings";

// ──────────────────────────────────────────────────────────────────────────
// Visual mapping for the severity bands.
// ──────────────────────────────────────────────────────────────────────────

const SEVERITY_BADGE: Record<
  UpcomingFilingSeverity,
  { variant: "destructive" | "warning" | "info" | "outline" | "success"; label: string }
> = {
  overdue: { variant: "destructive", label: "Overdue" },
  critical: { variant: "destructive", label: "≤ 7 days" },
  warning: { variant: "warning", label: "≤ 30 days" },
  advisory: { variant: "info", label: "≤ 60 days" },
  info: { variant: "outline", label: "≤ 90 days" },
};

const SEVERITY_ROW_TONE: Record<UpcomingFilingSeverity, string> = {
  overdue: "border-l-destructive bg-destructive/5",
  critical: "border-l-destructive bg-destructive/[0.03]",
  warning: "border-l-yellow-500 bg-yellow-50/40 dark:bg-yellow-900/10",
  advisory: "border-l-blue-500 bg-blue-50/30 dark:bg-blue-900/10",
  info: "border-l-muted",
};

function describeDays(days: number): string {
  if (days < 0) return `${Math.abs(days)}d past due`;
  if (days === 0) return "due today";
  if (days === 1) return "due tomorrow";
  return `due in ${days}d`;
}

function entityLabel(slug: string): string {
  const org = ALL_ORGANIZATIONS.find((o) => o.slug === slug);
  if (!org) return slug;
  return `${org.emoji ?? ""} ${org.name}`.trim();
}

// ──────────────────────────────────────────────────────────────────────────
// Banner
// ──────────────────────────────────────────────────────────────────────────

export function FilingRemindersBanner() {
  const [hydrated, setHydrated] = useState(false);
  const [filings, setFilings] = useState<UpcomingFiling[]>([]);

  // Recompute on the client only — `gatherUpcomingFilings` reads
  // localStorage, which isn&apos;t available during SSR.
  useEffect(() => {
    // eslint-disable-next-line react-hooks/set-state-in-effect -- one-time hydration from localStorage
    setFilings(gatherUpcomingFilings(new Date()));
    setHydrated(true);
  }, []);

  const summary = useMemo(() => summarizeFilings(filings), [filings]);

  const hasOverdueOrCritical = summary.overdue > 0 || summary.critical > 0;

  // Don&apos;t render anything pre-hydration to avoid a flash + mismatched
  // SSR/CSR markup.
  if (!hydrated) return null;

  // Empty state — quiet green banner.
  if (filings.length === 0) {
    return (
      <AlertCard
        severity="success"
        title="No filings due within the next 90 days. Nice."
        hideChip
        icon={
          <span className="text-xl" aria-hidden>
            ✅
          </span>
        }
      >
        <p className="text-xs text-muted-foreground">
          Reminders surface here as soon as a deadline lands inside the window.
        </p>
      </AlertCard>
    );
  }

  const dominantSeverity: "critical" | "warning" | "advisory" | "info" =
    hasOverdueOrCritical
      ? "critical"
      : summary.warning > 0
        ? "warning"
        : summary.advisory > 0
          ? "advisory"
          : "info";

  const criticalPlusOverdue = summary.overdue + summary.critical;
  const summaryLine = [
    `${summary.total} upcoming filing${summary.total === 1 ? "" : "s"}`,
    criticalPlusOverdue > 0
      ? `${criticalPlusOverdue} critical`
      : summary.warning > 0
        ? `${summary.warning} due in 30d`
        : `${summary.advisory} due in 60d`,
  ].join(" · ");

  const titleNode = (
    <span className="flex flex-col">
      <span className="text-sm font-semibold">Filing reminders</span>
      <span className="text-xs font-normal text-muted-foreground">
        {summaryLine}
      </span>
    </span>
  );

  return (
    <AlertCard
      severity={dominantSeverity}
      title={titleNode}
      hideChip
      defaultOpen={hasOverdueOrCritical}
      icon={
        <span className="text-xl" aria-hidden>
          {summary.overdue > 0 ? "🚨" : summary.critical > 0 ? "⚠️" : "📅"}
        </span>
      }
      trailing={
        <AlertCardSummary>
          <SeverityChip count={summary.overdue} severity="overdue" />
          <SeverityChip count={summary.critical} severity="critical" />
          <SeverityChip count={summary.warning} severity="warning" />
          <SeverityChip count={summary.advisory} severity="advisory" />
        </AlertCardSummary>
      }
    >
      <ul
        id="filing-reminders-list"
        className="mt-2 divide-y rounded-md border bg-card"
      >
        {filings.map((f) => (
          <FilingRow key={f.id} filing={f} />
        ))}
      </ul>
    </AlertCard>
  );
}

// ──────────────────────────────────────────────────────────────────────────
// Subcomponents
// ──────────────────────────────────────────────────────────────────────────

function FilingRow({ filing }: { filing: UpcomingFiling }) {
  const badge = SEVERITY_BADGE[filing.severity];
  const tone = SEVERITY_ROW_TONE[filing.severity];
  return (
    <li className={`border-l-4 ${tone} px-3 py-2 flex items-center gap-3 flex-wrap`}>
      <Badge variant={badge.variant} className="shrink-0">
        {badge.label}
      </Badge>
      <div className="flex-1 min-w-0">
        <div className="text-sm font-medium truncate">{filing.title}</div>
        <div className="text-xs text-muted-foreground truncate">
          {entityLabel(filing.entitySlug)}
          {filing.detail ? <span className="text-muted-foreground/70"> · {filing.detail}</span> : null}
        </div>
      </div>
      <div className="flex items-center gap-2 shrink-0">
        <span className="font-mono text-[11px] text-muted-foreground tabular-nums">
          {filing.dueDate}
        </span>
        <Badge variant="outline" className="text-[10px]">
          {describeDays(filing.daysUntilDue)}
        </Badge>
        <Button asChild size="sm" variant="ghost">
          <Link href={filing.href} aria-label={`Open ${filing.title}`}>
            Open ↗
          </Link>
        </Button>
      </div>
    </li>
  );
}

function SeverityChip({
  count,
  severity,
}: {
  count: number;
  severity: UpcomingFilingSeverity;
}) {
  if (count <= 0) return null;
  const badge = SEVERITY_BADGE[severity];
  return (
    <Badge variant={badge.variant} className="text-[10px]">
      {count} {badge.label.replace("≤ ", "≤")}
    </Badge>
  );
}
