"use client";

import Link from "next/link";
import { useMemo, useState } from "react";
import { addDays, startOfDay } from "date-fns";
import { Button } from "@/components/ui/button";
import { formatBallboxDateTime, formatBallboxShortDateLabel, formatBallboxTime } from "@/lib/ballbox-datetime";
import type { CoachAvailabilityCalendar, CoachAvailabilitySlot, CoachAvailabilitySlotCoach } from "@/lib/coach-availability-matching";

type ClassesByDatePageClientProps = {
  calendar: CoachAvailabilityCalendar;
};

type SlotSelection = {
  slot: CoachAvailabilitySlot;
  coach: CoachAvailabilitySlotCoach | null;
};

function buildDateKeys(startIso: string, days: number) {
  const start = startOfDay(new Date(startIso));
  return Array.from({ length: days }, (_, index) => addDays(start, index).toISOString().slice(0, 10));
}

function buildSlotHref(slot: CoachAvailabilitySlot, coach: CoachAvailabilitySlotCoach, clubId: string, calendar: CoachAvailabilityCalendar) {
  if (!coach.offerId) return null;
  const details = calendar.slotDetailsByClub[clubId]?.[slot.start] ?? null;
  const params = new URLSearchParams({
    slotStart: slot.start,
    slotDurationMinutes: String(slot.durationMinutes),
  });

  if (details?.priceMinor !== null && details?.priceMinor !== undefined) {
    params.set("slotPriceMinor", String(details.priceMinor));
  }
  if (details?.currency) {
    params.set("slotCurrency", details.currency);
  }
  if (details?.courtId) {
    params.set("slotCourtId", details.courtId);
  }
  if (details?.courtName) {
    params.set("slotCourtName", details.courtName);
  }
  if (details?.sportclubId) {
    params.set("slotSportclubId", details.sportclubId);
  }

  return `/classes/${coach.offerId}?${params.toString()}#request-form`;
}

export function ClassesByDatePageClient({ calendar }: ClassesByDatePageClientProps) {
  const [selectedZone, setSelectedZone] = useState<string>("");
  const [selectedCoachId, setSelectedCoachId] = useState<string>("all");
  const [selectedClubId, setSelectedClubId] = useState<string>("all");
  const [selection, setSelection] = useState<SlotSelection | null>(null);

  const dateKeys = useMemo(() => buildDateKeys(calendar.range.start, 14), [calendar.range.start]);
  const zoneOptions = useMemo(
    () => Array.from(new Set(calendar.clubs.map((club) => club.zoneLabel))).sort((left, right) => left.localeCompare(right, "es")),
    [calendar.clubs]
  );
  const clubsInSelectedZone = useMemo(
    () => calendar.clubs.filter((club) => (selectedZone ? club.zoneLabel === selectedZone : true)),
    [calendar.clubs, selectedZone]
  );

  const filteredSlots = useMemo(() => {
    return calendar.slots.filter((slot) => {
      if (!selectedZone) {
        return false;
      }

      if (selectedCoachId !== "all" && !slot.coaches.some((coach) => coach.id === selectedCoachId)) {
        return false;
      }

      const clubsMatchingZone = slot.coaches.some((coach) =>
        coach.clubs.some((club) => club.zoneLabel === selectedZone && (selectedClubId === "all" || club.id === selectedClubId))
      );
      if (!clubsMatchingZone) {
        return false;
      }

      if (selectedClubId !== "all") {
        return slot.coaches.some((coach) => coach.clubs.some((club) => club.id === selectedClubId));
      }

      return true;
    });
  }, [calendar.slots, selectedClubId, selectedCoachId, selectedZone]);

  const slotsByDate = useMemo(() => {
    const grouped = new Map<string, CoachAvailabilitySlot[]>();
    for (const dateKey of dateKeys) {
      grouped.set(dateKey, []);
    }
    for (const slot of filteredSlots) {
      const group = grouped.get(slot.dateKey);
      if (group) {
        group.push(slot);
      }
    }
    for (const group of grouped.values()) {
      group.sort((left, right) => new Date(left.start).getTime() - new Date(right.start).getTime());
    }
    return grouped;
  }, [filteredSlots, dateKeys]);

  const weekGroups = useMemo(() => {
    const groups: string[][] = [];
    for (let i = 0; i < dateKeys.length; i += 7) {
      groups.push(dateKeys.slice(i, i + 7));
    }
    return groups;
  }, [dateKeys]);

  const selectedSlot = selection?.slot ?? null;
  const selectedSlotCoach = selection?.coach ?? null;
  const visibleSelectionCoaches = useMemo(() => {
    if (!selectedSlot || !selectedZone) return [];

    return selectedSlot.coaches.filter((coach) => {
      if (selectedCoachId !== "all" && coach.id !== selectedCoachId) {
        return false;
      }

      return coach.clubs.some((club) => club.zoneLabel === selectedZone && (selectedClubId === "all" || club.id === selectedClubId));
    });
  }, [selectedClubId, selectedCoachId, selectedSlot, selectedZone]);
  const activeSelectionCoach =
    (selectedSlotCoach ? visibleSelectionCoaches.find((coach) => coach.id === selectedSlotCoach.id) : null) ?? null;
  const detailPanelId = selectedSlot ? `slot-detail-${selectedSlot.key}` : "slot-detail";

  return (
    <section className="mt-8 space-y-6" aria-labelledby="classes-by-date-filters-heading">
      <div className="grid gap-4 rounded-[1.5rem] border border-white/10 bg-[#0f140f]/80 p-5 text-white shadow-[0_20px_60px_-40px_rgba(0,0,0,0.45)] lg:grid-cols-[1.4fr_1fr]">
        <div>
          <p className="text-xs uppercase tracking-[0.2em] text-[#c4d600]">Reservas</p>
          <h2 id="classes-by-date-filters-heading" className="sr-only">Filtros para buscar horarios</h2>
          <p className="mt-3 text-sm text-white/70">
            Primero elige tu zona. Despues Ballbox te muestra solo los horarios y clubes que hoy tienen opcion real para reservar.
          </p>
        </div>
        <fieldset className="grid gap-3 sm:grid-cols-3">
          <legend className="sr-only">Filtros de horarios</legend>
          <label className="text-sm text-white/70">
            Zona
            <select
              value={selectedZone}
              onChange={(event) => {
                setSelectedZone(event.target.value);
                setSelectedClubId("all");
                setSelection(null);
              }}
              className="mt-2 h-11 w-full rounded-xl border border-white/15 bg-black/30 px-3 text-sm text-white"
            >
              <option value="">Selecciona tu zona</option>
              {zoneOptions.map((zone) => (
                <option key={zone} value={zone}>
                  {zone}
                </option>
              ))}
            </select>
          </label>
          <label className="text-sm text-white/70">
            Coach
            <select
              value={selectedCoachId}
              onChange={(event) => setSelectedCoachId(event.target.value)}
              className="mt-2 h-11 w-full rounded-xl border border-white/15 bg-black/30 px-3 text-sm text-white"
            >
              <option value="all">Todos los coaches</option>
              {calendar.coaches.map((coach) => (
                <option key={coach.id} value={coach.id}>
                  {coach.name}
                </option>
              ))}
            </select>
          </label>
          <label className="text-sm text-white/70">
            Club
            <select
              value={selectedClubId}
              onChange={(event) => setSelectedClubId(event.target.value)}
              disabled={!selectedZone}
              className="mt-2 h-11 w-full rounded-xl border border-white/15 bg-black/30 px-3 text-sm text-white"
            >
              <option value="all">{selectedZone ? "Todos los clubes" : "Primero elige zona"}</option>
              {clubsInSelectedZone.map((club) => (
                <option key={club.id} value={club.id}>
                  {club.name ?? "ATC no disponible"}
                </option>
              ))}
            </select>
          </label>
        </fieldset>
      </div>

      {!selectedZone ? (
        <div className="rounded-[1.5rem] border border-dashed border-white/10 bg-black/10 p-6 text-sm text-white/60">
          Selecciona una zona para ver los clubes y horarios disponibles.
        </div>
      ) : null}

      {selectedZone && filteredSlots.length === 0 ? (
        <div className="rounded-[1.5rem] border border-white/10 bg-[#0f140f]/70 p-6 text-sm text-white/60">
          No encontramos horarios abiertos en esta zona con los filtros elegidos.
        </div>
      ) : null}

      {selectedZone
        ? weekGroups.map((week, index) => (
        <section key={`week-${index}`} className="grid gap-4 lg:grid-cols-7" aria-label={`Semana ${index + 1} de horarios`}>
          {week.map((dateKey) => {
            const slots = slotsByDate.get(dateKey) ?? [];

            return (
              <div key={dateKey} className="rounded-[1.5rem] border border-white/10 bg-[#0f140f]/70 p-4">
                <div className="flex items-center justify-between text-xs uppercase tracking-[0.2em] text-white/60">
                  <span>{formatBallboxShortDateLabel(dateKey)}</span>
                  <span className="text-[#c4d600]">{slots.length}</span>
                </div>

                <div className="mt-4 space-y-3">
                  {slots.length === 0 ? (
                    <p className="text-xs text-white/45">Sin rangos detectados.</p>
                  ) : (
                    slots.map((slot) => (
                      <button
                        key={slot.key}
                        type="button"
                        onClick={() => {
                          const visibleCoaches = slot.coaches.filter((coach) => {
                            if (selectedCoachId !== "all" && coach.id !== selectedCoachId) {
                              return false;
                            }

                            return coach.clubs.some(
                              (club) => club.zoneLabel === selectedZone && (selectedClubId === "all" || club.id === selectedClubId)
                            );
                          });
                          const defaultCoach =
                            selectedCoachId !== "all"
                              ? visibleCoaches.find((coach) => coach.id === selectedCoachId) ?? null
                              : visibleCoaches[0] ?? null;
                          setSelection({ slot, coach: defaultCoach });
                        }}
                        aria-expanded={selectedSlot?.key === slot.key}
                        aria-controls={detailPanelId}
                        className={`w-full rounded-2xl border px-3 py-3 text-left text-sm transition ${
                          slot.hasCourts ? "border-white/10 bg-black/30 text-white" : "border-[#f6c453]/40 bg-[#3a2c14]/40 text-[#f6c453]"
                        }`}
                      >
                        <div className="flex items-center justify-between gap-2">
                          <span className="text-lg font-semibold">{formatBallboxTime(slot.start)}</span>
                          <span className="text-xs uppercase tracking-[0.2em] text-white/45">{slot.durationMinutes}m</span>
                        </div>
                        <p className="mt-1 text-xs text-white/60">{slot.coaches.length} coaches disponibles</p>
                        {!slot.hasCourts ? (
                          <p className="mt-2 text-xs font-semibold">Coach disponible, pero sin canchas.</p>
                        ) : null}
                      </button>
                    ))
                  )}
                </div>
              </div>
            );
          })}
        </section>
          ))
        : null}

      <div aria-live="polite" className="sr-only">
        {selectedSlot ? `Horario seleccionado ${formatBallboxDateTime(selectedSlot.start)}` : "Ningun horario seleccionado"}
      </div>

      {selection && selectedSlot ? (
        <section
          id={detailPanelId}
          className="rounded-[1.75rem] border border-white/10 bg-[#0f140f] p-6 text-white shadow-[0_30px_90px_-45px_rgba(0,0,0,0.7)]"
          aria-labelledby="selected-slot-heading"
        >
          <div className="flex items-start justify-between gap-4">
            <div>
              <p className="text-xs uppercase tracking-[0.2em] text-[#c4d600]">Seleccion de horario</p>
              <h2 id="selected-slot-heading" className="mt-2 text-2xl font-semibold">{formatBallboxDateTime(selectedSlot.start)}</h2>
              <p className="mt-2 text-sm text-white/65">Elige un coach y luego el club con canchas disponibles.</p>
            </div>
            <button
              type="button"
              onClick={() => setSelection(null)}
              className="rounded-full border border-white/10 px-3 py-1 text-xs uppercase tracking-[0.2em] text-white/70"
            >
              Limpiar
            </button>
          </div>

          <div className="mt-6 grid gap-4 lg:grid-cols-2">
            <section className="rounded-2xl border border-white/10 bg-black/20 p-4" aria-labelledby="selected-slot-coach-heading">
              <h3 id="selected-slot-coach-heading" className="text-xs uppercase tracking-[0.2em] text-white/60">Paso 1: Coach</h3>
              {visibleSelectionCoaches.length === 0 ? (
                <p className="mt-4 text-sm text-white/60">No hay coaches visibles para esa zona con los filtros elegidos.</p>
              ) : (
                <div className="mt-4 space-y-3">
                  {visibleSelectionCoaches.map((coach) => {
                    const hasCourts = coach.clubs.some((club) => club.hasCourts);
                    const active = activeSelectionCoach?.id === coach.id;

                    return (
                      <button
                        key={coach.id}
                        type="button"
                        onClick={() => setSelection({ slot: selectedSlot, coach })}
                        aria-pressed={active}
                        className={`w-full rounded-xl border px-3 py-2 text-left text-sm ${
                          active ? "border-[#c4d600]/50 bg-[#c4d600]/10" : "border-white/10 bg-black/30"
                        }`}
                      >
                        <div className="flex items-center justify-between gap-2">
                          <span className="font-medium">{coach.name}</span>
                          <span className={`text-xs ${hasCourts ? "text-[#c4d600]" : "text-[#f6c453]"}`}>
                            {hasCourts ? "Con canchas" : "Sin canchas"}
                          </span>
                        </div>
                      </button>
                    );
                  })}
                </div>
              )}
            </section>

            <section className="rounded-2xl border border-white/10 bg-black/20 p-4" aria-labelledby="selected-slot-club-heading">
              <h3 id="selected-slot-club-heading" className="text-xs uppercase tracking-[0.2em] text-white/60">Paso 2: Club</h3>
              {activeSelectionCoach ? (
                <div className="mt-4 space-y-3">
                  {activeSelectionCoach.clubs.length === 0 ? (
                    <p className="text-sm text-white/60">Este coach no tiene clubes habilitados.</p>
                  ) : activeSelectionCoach.clubs.filter((club) => club.hasCourts && club.zoneLabel === selectedZone).length === 0 ? (
                    <p className="text-sm text-white/60">Coach disponible, pero sin canchas en este horario.</p>
                  ) : (
                    activeSelectionCoach.clubs
                      .filter((club) => club.hasCourts && club.zoneLabel === selectedZone && (selectedClubId === "all" || club.id === selectedClubId))
                      .map((club) => {
                        const href = buildSlotHref(selectedSlot, activeSelectionCoach, club.id, calendar);

                        return (
                          <article key={club.id} className="rounded-xl border border-white/10 bg-black/30 px-3 py-3">
                            <p className="text-sm font-medium text-white">{club.name ?? "ATC no disponible"}</p>
                            <div className="mt-3 flex flex-wrap gap-2">
                              {href ? (
                                <Button asChild className="h-9 rounded-lg text-xs">
                                  <Link href={href}>Solicitar con este club</Link>
                                </Button>
                              ) : (
                                <span className="text-xs text-white/50">Sin oferta activa para este coach</span>
                              )}
                            </div>
                          </article>
                        );
                      })
                  )}
                </div>
              ) : (
                <p className="mt-4 text-sm text-white/60">Elige un coach para continuar.</p>
              )}
            </section>
          </div>
        </section>
      ) : null}
    </section>
  );
}
