import { format } from "date-fns";
import { Calendar, ChevronRight, Users } from "lucide-react";
import { useState, useEffect } from "react";
import { Link } from "react-router";
import { Badge } from "~/components/ui/badge";
import {
  Card,
  CardContent,
  CardHeader,
  CardTitle,
} from "~/components/ui/card";
import { formatEventDate } from "~/lib/date-utils";
import type { UpcomingParticipantEvent } from "~/models/scoring-event";

export interface CalendarPanelEvent extends UpcomingParticipantEvent {
  sportName: string;
  sportSeasonName: string;
  /** Present when showing events across multiple leagues (home page) */
  leagueName?: string;
  leagueId?: string;
  sportsSeasonPageUrl?: string;
}

interface Props {
  events: CalendarPanelEvent[];
  /** When true, renders a league name badge on each row */
  showLeague?: boolean;
  /** If provided, only the first N events are rendered */
  limit?: number;
  /** If provided and events.length > limit, renders a "View all" footer link */
  viewAllUrl?: string;
  /** Override the default empty state message */
  emptyMessage?: string;
}

function ParticipantList({ participants }: { participants: Array<{ id: string; name: string }> }) {
  const MAX_SHOWN = 3;
  const shown = participants.slice(0, MAX_SHOWN);
  const overflow = participants.length - MAX_SHOWN;

  return (
    <span className="flex flex-wrap items-center gap-1">
      {shown.map((p) => (
        <Badge key={p.id} variant="secondary" className="text-xs font-normal">
          {p.name}
        </Badge>
      ))}
      {overflow > 0 && (
        <Badge variant="outline" className="text-xs text-muted-foreground">
          +{overflow} more
        </Badge>
      )}
    </span>
  );
}

function EventRow({ event, showLeague }: { event: CalendarPanelEvent; showLeague: boolean }) {
  // Prefer game-level scheduledAt over event-level eventDate for display
  const gameDate = event.earliestGameTime ? new Date(event.earliestGameTime) : null;
  const dateStr = gameDate
    ? format(gameDate, "MMM d")
    : formatEventDate(event.eventDate);
  const participantCount = event.relevantParticipants.length;
  const isAllCompete = event.eventType !== "playoff_game";
  const displayName = event.matchLabel
    ? `${event.name} — ${event.matchLabel}`
    : event.name;

  const content = (
    <div className="flex items-start gap-3 py-2.5 border-b last:border-0 group">
      {/* Date pill */}
      <div className="w-14 shrink-0 text-center">
        <span className="text-xs font-semibold text-electric" suppressHydrationWarning>
          {dateStr ?? "TBD"}
        </span>
        {gameDate && (
          <p
            className="text-xs text-muted-foreground leading-tight"
            suppressHydrationWarning
          >
            {gameDate.toLocaleTimeString(undefined, {
              hour: "numeric",
              minute: "2-digit",
            })}
          </p>
        )}
      </div>

      {/* Event details */}
      <div className="flex-1 min-w-0 space-y-1">
        <div className="flex items-center flex-wrap gap-2">
          <span className="text-sm font-medium truncate">{displayName}</span>
          {showLeague && event.leagueName && (
            <Badge variant="outline" className="text-xs shrink-0">
              {event.leagueName}
            </Badge>
          )}
        </div>
        <div className="flex items-center gap-1.5 text-xs text-muted-foreground">
          <span className="truncate">{event.sportName} · {event.sportSeasonName}</span>
        </div>
        <div className="flex items-center gap-1.5">
          <Users className="h-3 w-3 text-muted-foreground shrink-0" />
          {isAllCompete && participantCount > 1 ? (
            <span className="text-xs text-muted-foreground">
              {participantCount} of your picks
            </span>
          ) : (
            <ParticipantList participants={event.relevantParticipants} />
          )}
        </div>
      </div>
    </div>
  );

  if (event.sportsSeasonPageUrl) {
    return (
      <Link to={event.sportsSeasonPageUrl} className="block hover:bg-muted/40 -mx-2 px-2 rounded transition-colors">
        {content}
      </Link>
    );
  }

  return content;
}

export function UpcomingCalendarPanel({ events, showLeague = false, limit, viewAllUrl, emptyMessage }: Props) {
  // Filter out past events client-side using local timezone. Server sends events
  // starting from yesterday UTC as a buffer; useEffect trims to today-and-forward
  // after hydration so the correct local date is used.
  const [localFilteredEvents, setLocalFilteredEvents] = useState(events);
  useEffect(() => {
    const todayStr = new Intl.DateTimeFormat("en-CA").format(new Date());
    setLocalFilteredEvents(events.filter((e) => (e.earliestGameTime ?? e.eventDate ?? "9999-12-31") >= todayStr));
  }, [events]);

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

  return (
    <Card>
      <CardHeader className="pb-3">
        <CardTitle className="flex items-center gap-2 text-base">
          <Calendar className="h-4 w-4 text-electric" />
          Upcoming Events
        </CardTitle>
      </CardHeader>
      <CardContent>
        {localFilteredEvents.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) => (
              <EventRow key={event.id} event={event} showLeague={showLeague} />
            ))}
            {viewAllUrl && (
              <div className="mt-3 pt-2 border-t">
                <Link
                  to={viewAllUrl}
                  className="flex items-center gap-1 text-sm text-electric hover:underline"
                >
                  {hiddenCount > 0
                    ? `View all ${localFilteredEvents.length} upcoming events`
                    : "View all upcoming events"}
                  <ChevronRight className="h-3.5 w-3.5" />
                </Link>
              </div>
            )}
          </div>
        )}
      </CardContent>
    </Card>
  );
}
