import { format, formatDistanceToNow } from "date-fns";
import { ChevronRight, ChessPawn, Hourglass, LayoutGrid, Moon } from "lucide-react";
import { Link } from "react-router";
import { Button } from "~/components/ui/button";
import { Card, CardContent, CardHeader } from "~/components/ui/card";
import { GradientIcon } from "~/components/ui/GradientIcon";

// ─── Types ────────────────────────────────────────────────────────────────────

export interface DraftInfoCardProps {
  draftRounds: number;
  draftTimerMode: "standard" | "chess_clock";
  /** Per-pick time for standard; initial bank for chess clock (seconds) */
  draftInitialTime: number;
  /** Bonus seconds added after each pick (chess clock only; ignored in standard) */
  draftIncrementTime: number;
  sportsCount: number;
  isDraftOrderSet: boolean;
  /** true when season status is pre_draft or draft */
  isDraftOrPreDraft: boolean;
  draftDateTime?: string | Date | null;
  draftBoardHref: string;
  draftRoomHref: string;
  /** Link to the pre-draft queue builder; shown only when draft order is not yet set and user has a team */
  queueBuilderHref?: string;
  /** 1-based draft position for the current user; omit or undefined to hide the panel */
  userDraftPosition?: number;
  /** IANA timezone used to display the draft date and time. */
  draftTimezone?: string | null;
  overnightPauseMode?: "none" | "league" | "per_user";
  overnightPauseStart?: string | null;
  overnightPauseEnd?: string | null;
  overnightPauseTimezone?: string | null;
}

// ─── Sub-components ───────────────────────────────────────────────────────────

function InfoPanel({ label, value, sub }: { label: string; value: React.ReactNode; sub?: React.ReactNode }) {
  return (
    <div className="flex min-w-0 flex-col rounded-lg bg-white/[0.04] px-3 py-3 gap-2">
      <span className="text-xs font-semibold uppercase tracking-wide text-muted-foreground leading-none">
        {label}
      </span>
      <span className="min-w-0 text-xl font-bold leading-none">{value}</span>
      {sub && <span className="text-xs text-muted-foreground leading-none">{sub}</span>}
    </div>
  );
}

// ─── Card variant (pre_draft / draft) ─────────────────────────────────────────

function DraftInfoCardVariant({
  draftRounds,
  draftTimerMode,
  draftInitialTime,
  draftIncrementTime,
  sportsCount,
  isDraftOrderSet,
  draftDateTime,
  draftTimezone,
  draftRoomHref,
  queueBuilderHref,
  userDraftPosition,
  overnightPauseMode,
  overnightPauseStart,
  overnightPauseEnd,
  overnightPauseTimezone,
}: DraftInfoCardProps) {
  const flexSpots = Math.max(0, draftRounds - sportsCount);

  const timerLabel = draftTimerMode === "chess_clock" ? "Chess Clock" : "Standard Timer";
  const draftDate = draftDateTime ? new Date(draftDateTime) : null;
  const timerValue = draftTimerMode === "chess_clock"
    ? `${formatHumanTime(draftInitialTime, { attributive: true })} time bank`
    : formatHumanTime(draftInitialTime);
  const timerSub = draftTimerMode === "chess_clock"
    ? `+${formatHumanTime(draftIncrementTime, { attributive: true })} increment`
    : "per pick";

  const roundsSub = [
    `${sportsCount} sport${sportsCount !== 1 ? "s" : ""}`,
    flexSpots > 0 ? `${flexSpots} flex` : null,
  ].filter(Boolean).join(" + ");

  const hasPosition = userDraftPosition !== null && userDraftPosition !== undefined;
  const hasOvernight = !!(overnightPauseMode && overnightPauseMode !== "none" && overnightPauseStart && overnightPauseEnd);

  // Mechanics row: Rounds + (Your Pick?) + Timer
  // When overnight is shown, Draft Date moves to the top row so mechanics has 2–3 items.
  // When no overnight, Draft Date stays in this row giving 3–4 items.
  const mechanicsColsClass = hasOvernight
    ? (hasPosition ? "grid-cols-2 sm:grid-cols-3" : "grid-cols-2")
    : (hasPosition ? "grid-cols-2 sm:grid-cols-4" : "grid-cols-2 sm:grid-cols-3");

  const timerPanel = (
    <InfoPanel
      label={timerLabel}
      value={
        <span className="flex items-center gap-1.5">
          {draftTimerMode === "chess_clock"
            ? <ChessPawn className="h-4 w-4 shrink-0 text-muted-foreground" />
            : <Hourglass className="h-4 w-4 shrink-0 text-muted-foreground" />}
          {timerValue}
        </span>
      }
      sub={timerSub}
    />
  );

  return (
    <Card>
      <CardHeader className="pb-4">
        <div className="flex items-center justify-between">
          <div className="flex items-center gap-2">
            <GradientIcon icon={LayoutGrid} className="h-5 w-5 shrink-0" />
            <h2 className="text-xl font-bold leading-none tracking-tight">Draft Info</h2>
          </div>
          {isDraftOrderSet ? (
            <Button asChild>
              <Link to={draftRoomHref}>Enter Draft Room</Link>
            </Button>
          ) : queueBuilderHref ? (
            <Button asChild variant="outline">
              <Link to={queueBuilderHref}>Set Pre-Draft Queue</Link>
            </Button>
          ) : null}
        </div>
      </CardHeader>

      <CardContent className="space-y-2">
        {/* Scheduling row: Draft Date + Overnight Pause side-by-side when overnight is configured */}
        {hasOvernight && (
          <div className="grid grid-cols-1 gap-2 sm:grid-cols-2">
            <InfoPanel
              label="Draft Date & Time"
              value={draftDate ? <span className="block leading-tight" suppressHydrationWarning>{formatDraftDateTime(draftDate, draftTimezone)}</span> : "TBD"}
              sub={draftDate ? <span suppressHydrationWarning>{formatRelativeDate(draftDate)}</span> : undefined}
            />
            <InfoPanel
              label="Overnight Pause"
              value={
                <span className="flex items-center gap-1.5">
                  <Moon className="h-4 w-4 shrink-0 text-muted-foreground" />
                  {formatHHMM(overnightPauseStart ?? "")} – {formatHHMM(overnightPauseEnd ?? "")}
                </span>
              }
              sub={overnightPauseMode === "league" && overnightPauseTimezone
                ? overnightPauseTimezone
                : "per-user timezone"}
            />
          </div>
        )}

        {/* Mechanics row: Rounds + Your Pick? + Timer (+ Draft Date when no overnight) */}
        <div className={`grid gap-2 ${mechanicsColsClass}`}>
          {!hasOvernight && (
            <InfoPanel
              label="Draft Date & Time"
              value={draftDate ? <span className="block leading-tight" suppressHydrationWarning>{formatDraftDateTime(draftDate, draftTimezone)}</span> : "TBD"}
              sub={draftDate ? <span suppressHydrationWarning>{formatRelativeDate(draftDate)}</span> : undefined}
            />
          )}
          <InfoPanel label="Rounds" value={draftRounds} sub={roundsSub} />
          {hasPosition && (
            <InfoPanel label="Your Pick" value={`#${userDraftPosition}`} sub="round 1 position" />
          )}
          {timerPanel}
          {/* placeholder to keep grid balanced on mobile when only 2 items */}
          {hasOvernight && !hasPosition && <div />}
        </div>
      </CardContent>
    </Card>
  );
}

// ─── Helpers ──────────────────────────────────────────────────────────────────

/** Formats "23:00" → "11 PM", "07:00" → "7 AM". */
function formatHHMM(hhmm: string): string {
  const [hStr, mStr] = hhmm.split(":");
  const h = parseInt(hStr, 10);
  const m = parseInt(mStr, 10);
  const period = h < 12 ? "AM" : "PM";
  const h12 = h % 12 === 0 ? 12 : h % 12;
  return m === 0 ? `${h12} ${period}` : `${h12}:${String(m).padStart(2, "0")} ${period}`;
}

function formatDraftDateTime(date: Date, timezone: string | null | undefined): string {
  const parts = new Intl.DateTimeFormat("en-US", {
    timeZone: getDisplayTimezone(timezone),
    month: "long",
    day: "numeric",
    year: "numeric",
    hour: "numeric",
    minute: "2-digit",
    hour12: true,
    timeZoneName: "shortGeneric",
  }).formatToParts(date);
  const getPart = (type: Intl.DateTimeFormatPartTypes) => (
    parts.find((part) => part.type === type)?.value ?? ""
  );

  return `${getPart("month")} ${getPart("day")}, ${getPart("year")} ${getPart("hour")}:${getPart("minute")}${getPart("dayPeriod")} ${getPart("timeZoneName")}`;
}

function getDisplayTimezone(timezone: string | null | undefined): string {
  if (!timezone) return "UTC";
  try {
    new Intl.DateTimeFormat("en-US", { timeZone: timezone }).format();
    return timezone;
  } catch {
    return "UTC";
  }
}

function formatRelativeDate(date: Date): string {
  const value = formatDistanceToNow(date, { addSuffix: true });
  return value.charAt(0).toUpperCase() + value.slice(1);
}

/** Converts a seconds value to a short human-readable string, e.g. "1 minute", "10 seconds", "2 hours". */
function formatHumanTime(seconds: number, options: { attributive?: boolean } = {}): string {
  const h = Math.floor(seconds / 3600);
  const m = Math.floor((seconds % 3600) / 60);
  const s = seconds % 60;
  const parts: string[] = [];
  const plural = (value: number) => (!options.attributive && value !== 1 ? "s" : "");
  if (h > 0) parts.push(`${h} hour${plural(h)}`);
  if (m > 0) parts.push(`${m} minute${plural(m)}`);
  if (s > 0) parts.push(`${s} second${plural(s)}`);
  return parts.join(" ") || "0 seconds";
}

// ─── Bare variant (active / completed) ────────────────────────────────────────

function DraftInfoBareVariant({
  draftRounds,
  draftTimerMode,
  draftInitialTime,
  draftIncrementTime,
  sportsCount,
  draftDateTime,
  draftBoardHref,
}: DraftInfoCardProps) {
  const flexSpots = Math.max(0, draftRounds - sportsCount);

  return (
    <div>
      <div className="flex items-center justify-between mb-4">
        <div className="flex items-center gap-2">
          <GradientIcon icon={LayoutGrid} className="h-5 w-5 shrink-0" />
          <span className="text-xl font-bold leading-none tracking-tight">Draft</span>
        </div>
        <Link
          to={draftBoardHref}
          className="flex items-center gap-0.5 text-xs font-semibold uppercase tracking-wide text-electric hover:underline"
        >
          View Draft Board
          <ChevronRight className="h-3.5 w-3.5" />
        </Link>
      </div>

      <div className="flex gap-3">
        {/* Mode icon */}
        <div className="flex size-16 shrink-0 items-center justify-center bg-black">
          {draftTimerMode === "chess_clock"
            ? <ChessPawn className="h-6 w-6 text-white" />
            : <Hourglass className="h-6 w-6 text-white" />}
        </div>

        <div className="min-w-0">
          {draftDateTime && (
            <div className="flex items-center gap-2 mb-0.5" suppressHydrationWarning>
              <span className="text-xs font-semibold uppercase tracking-wide text-electric">
                {format(new Date(draftDateTime), "MMM d, yyyy")}
              </span>
              <span className="text-border">|</span>
              <span className="text-xs text-muted-foreground">
                {format(new Date(draftDateTime), "p")}
              </span>
            </div>
          )}

          <div className="text-sm font-bold uppercase tracking-wide leading-tight">
            {draftRounds} rounds ({sportsCount} sport{sportsCount !== 1 ? "s" : ""}
            {flexSpots > 0 && ` + ${flexSpots} flex`})
          </div>

          <div className="text-xs text-muted-foreground mt-0.5">
            {draftTimerMode === "standard"
              ? `Standard — ${formatHumanTime(draftInitialTime)}/pick`
              : `Chess Clock — ${formatHumanTime(draftInitialTime)} + ${formatHumanTime(draftIncrementTime)} increment`}
          </div>
        </div>
      </div>
    </div>
  );
}

// ─── Public API ───────────────────────────────────────────────────────────────

export function DraftInfoCard(props: DraftInfoCardProps) {
  if (props.isDraftOrPreDraft) {
    return <DraftInfoCardVariant {...props} />;
  }
  return <DraftInfoBareVariant {...props} />;
}
