import { format } from "date-fns";
import { ChevronRight, Clock } from "lucide-react";
import { useMemo } from "react";
import { Link } from "react-router";
import { Badge } from "~/components/ui/badge";
import { LeagueAvatar } from "~/components/league/LeagueAvatar";
import { GradientIcon } from "~/components/ui/GradientIcon";
import { formatEventDate } from "~/lib/date-utils";
import { BRACKT_GRADIENT } from "~/lib/brand";
import type { CalendarPanelEvent } from "./UpcomingCalendarPanel";

interface Props {
  events: CalendarPanelEvent[];
  title?: string;
  limit?: number;
  viewAllUrl?: string;
  emptyMessage?: string;
  /** Whether to show the league avatar next to participants. Default true. */
  showLeagueAvatar?: boolean;
}

export interface LeagueParticipants {
  leagueId: string;
  leagueName: string;
  participants: Array<{ id: string; name: string }>;
}

export interface GroupedEvent {
  id: string;
  name: string;
  matchLabel?: string | null;
  eventDate: string | null;
  earliestGameTime: string | null;
  eventType: string;
  sportName: string;
  sportSeasonName: string;
  sportsSeasonPageUrl?: string;
  leagues: LeagueParticipants[];
  totalParticipants: number;
  isAllCompete: boolean;
}

function groupEvents(events: CalendarPanelEvent[]): GroupedEvent[] {
  const map = new Map<string, GroupedEvent>();

  for (const event of events) {
    const existing = map.get(event.id);
    const isAllCompete = event.eventType !== "playoff_game";

    const leagueEntry: LeagueParticipants = {
      leagueId: event.leagueId ?? "unknown",
      leagueName: event.leagueName ?? "League",
      participants: event.relevantParticipants,
    };

    if (existing) {
      existing.leagues.push(leagueEntry);
      existing.totalParticipants += event.relevantParticipants.length;
    } else {
      map.set(event.id, {
        id: event.id,
        name: event.name,
        matchLabel: event.matchLabel,
        eventDate: event.eventDate,
        earliestGameTime: event.earliestGameTime,
        eventType: event.eventType,
        sportName: event.sportName,
        sportSeasonName: event.sportSeasonName,
        sportsSeasonPageUrl: event.sportsSeasonPageUrl,
        leagues: [leagueEntry],
        totalParticipants: event.relevantParticipants.length,
        isAllCompete,
      });
    }
  }

  return Array.from(map.values());
}

function TimelineDot({ isFirst }: { isFirst: boolean }) {
  if (isFirst) {
    return (
      <div
        className="relative z-10 mt-1 h-2.5 w-2.5 shrink-0 rounded-full"
        style={{ background: BRACKT_GRADIENT }}
      />
    );
  }
  return (
    <div className="relative z-10 mt-1 h-2.5 w-2.5 shrink-0 rounded-full border-2 border-border bg-background" />
  );
}

function ParticipantsByLeague({
  leagues,
  isAllCompete,
  showLeagueAvatar = true,
}: {
  leagues: LeagueParticipants[];
  isAllCompete: boolean;
  showLeagueAvatar?: boolean;
}) {
  return (
    <div className="space-y-1">
      {leagues.map((league) => {
        const content =
          isAllCompete && league.participants.length > 1 ? (
            <span className="text-xs text-muted-foreground">
              {league.participants.length} of your picks
            </span>
          ) : (
            <span className="flex flex-wrap gap-1">
              {league.participants.slice(0, 3).map((p) => (
                <Badge key={p.id} variant="secondary" className="text-xs font-normal">
                  {p.name}
                </Badge>
              ))}
              {league.participants.length > 3 && (
                <Badge variant="outline" className="text-xs text-muted-foreground">
                  +{league.participants.length - 3} more
                </Badge>
              )}
            </span>
          );

        if (!showLeagueAvatar) {
          return <div key={league.leagueId}>{content}</div>;
        }

        return (
          <div key={league.leagueId} className="flex items-center gap-1.5">
            <LeagueAvatar
              leagueId={league.leagueId}
              leagueName={league.leagueName}
              className="h-5 w-5"
              textClassName="text-[8px]"
            />
            {content}
          </div>
        );
      })}
    </div>
  );
}

export function EventRow({
  event,
  isFirst,
  isLast,
  showLeagueAvatar = true,
}: {
  event: GroupedEvent;
  isFirst: boolean;
  isLast: boolean;
  showLeagueAvatar?: boolean;
}) {
  const gameDate = event.earliestGameTime ? new Date(event.earliestGameTime) : null;
  const dateStr = gameDate ? format(gameDate, "MMM d") : formatEventDate(event.eventDate);
  const timeStr = gameDate
    ? gameDate.toLocaleTimeString(undefined, { hour: "numeric", minute: "2-digit" })
    : null;
  const displayName = event.matchLabel ? `${event.name} — ${event.matchLabel}` : event.name;

  const content = (
    <div className="flex gap-3 min-w-0">
      {/* Timeline spine */}
      <div className="flex flex-col items-center">
        <TimelineDot isFirst={isFirst} />
        {!isLast && <div className="w-px flex-1 bg-border mt-1" />}
      </div>

      {/* Content */}
      <div className={`flex flex-1 min-w-0 flex-col sm:flex-row sm:items-center gap-2 sm:gap-3 ${isLast ? "" : "pb-10"}`}>
        {/* Left: date + name */}
        <div className="flex-1 min-w-0">
          <div className="flex items-center gap-2 mb-0.5" suppressHydrationWarning>
            <span
              className={`text-xs font-semibold uppercase tracking-wide ${isFirst ? "text-electric" : "text-muted-foreground"}`}
            >
              {dateStr ?? "TBD"}
            </span>
            {timeStr && (
              <>
                <span className="text-border">|</span>
                <span className="text-xs text-muted-foreground">{timeStr}</span>
              </>
            )}
          </div>
          <div
            className={`text-sm font-bold uppercase tracking-wide leading-tight ${isFirst ? "text-foreground" : "text-muted-foreground"}`}
          >
            {displayName}
          </div>
          <div className="text-xs text-muted-foreground mt-0.5">
            {event.sportName}
          </div>
        </div>

        {/* Divider — hidden on mobile where layout is stacked */}
        <div className="hidden sm:block w-px self-stretch bg-border shrink-0" />

        {/* Right: participants per league */}
        <div className="sm:shrink-0 min-w-0">
          <ParticipantsByLeague
            leagues={event.leagues}
            isAllCompete={event.isAllCompete}
            showLeagueAvatar={showLeagueAvatar}
          />
        </div>
      </div>
    </div>
  );

  if (event.sportsSeasonPageUrl) {
    return (
      <Link to={event.sportsSeasonPageUrl} className="block hover:opacity-80 transition-opacity">
        {content}
      </Link>
    );
  }
  return <div>{content}</div>;
}

export function UpcomingEventsCard({
  events,
  title = "My Upcoming Events",
  limit,
  viewAllUrl,
  emptyMessage,
  showLeagueAvatar = true,
}: Props) {
  const localFilteredEvents = useMemo(() => {
    const todayStr = new Intl.DateTimeFormat("en-CA").format(new Date());
    return events.filter(
      (e) => (e.earliestGameTime ?? e.eventDate ?? "9999-12-31") >= todayStr
    );
  }, [events]);

  const grouped = groupEvents(localFilteredEvents);
  const displayedEvents = limit !== undefined ? grouped.slice(0, limit) : grouped;
  const hiddenCount = limit !== undefined ? Math.max(0, grouped.length - limit) : 0;

  return (
    <div>
      {/* Header */}
      <div className="flex items-center justify-between mb-6">
        <div className="flex items-center gap-2">
          <GradientIcon icon={Clock} className="h-5 w-5 shrink-0" />
          <span className="text-xl font-bold leading-none tracking-tight">{title}</span>
        </div>
        {viewAllUrl && (
          <Link
            to={viewAllUrl}
            className="flex items-center gap-0.5 text-xs font-semibold uppercase tracking-wide text-electric hover:underline"
          >
            View All
            <ChevronRight className="h-3.5 w-3.5" />
          </Link>
        )}
      </div>

      {/* Timeline */}
      {grouped.length === 0 ? (
        <p className="text-sm text-muted-foreground py-2">
          {emptyMessage ?? "No upcoming events in the next 30 days."}
        </p>
      ) : (
        <div>
          {displayedEvents.map((event, index) => (
            <EventRow
              key={event.id}
              event={event}
              isFirst={index === 0}
              isLast={index === displayedEvents.length - 1}
              showLeagueAvatar={showLeagueAvatar}
            />
          ))}
          {viewAllUrl && hiddenCount > 0 && (
            <Link
              to={viewAllUrl}
              className="flex items-center gap-1 text-sm text-electric hover:underline mt-1"
            >
              View all {grouped.length} upcoming events
              <ChevronRight className="h-3.5 w-3.5" />
            </Link>
          )}
        </div>
      )}
    </div>
  );
}
