"use client";

import Link from "next/link";
import { useEffect, useEffectEvent, useRef, useState } from "react";
import { AuthenticatedWorkspaceNavbar } from "@/components/authenticated-workspace-navbar";
import { Button } from "@/components/ui/button";
import { clubVenueDetailResponseSchema, clubVenueMutationResponseSchema } from "@/lib/contracts/club-accounts";
import {
  WeeklyAvailabilityGrid,
  clampWeeklyAvailabilityRanges,
  type WeeklyAvailabilityRange,
} from "@/components/weekly-availability-grid";

type ClubProfile = {
  id: string;
  name: string;
  slug: string;
  contactEmail: string;
};

type VenueCoach = {
  id: string;
  name: string;
  email: string | null;
  affiliation: "independent" | "club";
  venue: {
    id: string;
    name: string;
  } | null;
  court: {
    id: string;
    name: string;
  } | null;
  metrics: {
    classOffers: number;
    requestCount: number;
    availabilityBlocks: number;
    averageReview: number | null;
  };
};

type VenueDetail = {
  id: string;
  name: string;
  slug: string;
  status: "active" | "inactive";
  openingTime: string;
  closingTime: string;
  coachReservationPrice: number;
  clubCoachReservationDiscount: number;
  clubCoachReservationPrice: number;
  coachCancellationWindowHours: number;
  externalCoachesAllowed: boolean;
  coachHours: Array<{
    id: string;
    dayOfWeek: number;
    startTime: string;
    endTime: string;
  }>;
  coachPriceOverrides: Array<{
    id: string;
    dayOfWeek: number;
    startTime: string;
    endTime: string;
    price: number;
  }>;
  coachCount: number;
  classes: number;
  classOffers: number;
  courtSummary: {
    total: number;
    covered: number;
    uncovered: number;
    coachesEnabled: number;
  };
  courts: Array<{
    id: string;
    name: string;
    covered: boolean;
    coachesEnabled: boolean;
  }>;
};

type VenueCourtDraft = {
  clientId: string;
  id?: string;
  name: string;
  covered: boolean;
  coachesEnabled: boolean;
};

type VenuePriceOverrideDraft = {
  clientId: string;
  id?: string;
  dayOfWeek: number;
  startTime: string;
  endTime: string;
  price: number;
};

type VenueDraft = {
  name: string;
  status: "active" | "inactive";
  openingTime: string;
  closingTime: string;
  coachReservationPrice: number;
  clubCoachReservationDiscount: number;
  coachCancellationWindowHours: number;
  externalCoachesAllowed: boolean;
  coachHours: WeeklyAvailabilityRange[];
  coachPriceOverrides: VenuePriceOverrideDraft[];
  courts: VenueCourtDraft[];
};
type VenueSaveState = "idle" | "saving" | "saved" | "error";

const weekdayLabels = ["Domingo", "Lunes", "Martes", "Miercoles", "Jueves", "Viernes", "Sabado"] as const;

function createDraft(venue: VenueDetail): VenueDraft {
  return {
    name: venue.name,
    status: venue.status,
    openingTime: venue.openingTime,
    closingTime: venue.closingTime,
    coachReservationPrice: venue.coachReservationPrice,
    clubCoachReservationDiscount: venue.clubCoachReservationDiscount,
    coachCancellationWindowHours: venue.coachCancellationWindowHours,
    externalCoachesAllowed: venue.externalCoachesAllowed,
    coachHours: venue.coachHours.map((range) => ({
      dayOfWeek: range.dayOfWeek,
      startTime: range.startTime,
      endTime: range.endTime,
    })),
    coachPriceOverrides: venue.coachPriceOverrides.map((override) => ({
      clientId: override.id,
      id: override.id,
      dayOfWeek: override.dayOfWeek,
      startTime: override.startTime,
      endTime: override.endTime,
      price: override.price,
    })),
    courts: venue.courts.map((court) => ({
      clientId: court.id,
      id: court.id,
      name: court.name,
      covered: court.covered,
      coachesEnabled: court.coachesEnabled,
    })),
  };
}

function createLocalId(prefix: string) {
  return `${prefix}-${Math.random().toString(36).slice(2, 10)}`;
}

function parseTimeToMinutes(value: string) {
  const [hours, minutes] = value.split(":").map((part) => Number(part));
  if (!Number.isInteger(hours) || !Number.isInteger(minutes)) return null;
  return hours * 60 + minutes;
}

function buildDailyAvailabilityRanges(startTime: string, endTime: string): WeeklyAvailabilityRange[] {
  const startMinutes = parseTimeToMinutes(startTime);
  const endMinutes = parseTimeToMinutes(endTime);

  if (startMinutes === null || endMinutes === null || endMinutes <= startMinutes) {
    return [];
  }

  return Array.from({ length: 7 }, (_, dayOfWeek) => ({
    dayOfWeek,
    startTime,
    endTime,
  }));
}

function formatAverageReview(value: number | null) {
  return value === null ? "Sin resenas" : `${value.toFixed(1)} / 5`;
}

function summarizeCoachRanges(ranges: WeeklyAvailabilityRange[]) {
  if (ranges.length === 0) {
    return "Sin horarios cargados";
  }

  const days = new Set(ranges.map((range) => range.dayOfWeek));
  return `${days.size} dias configurados`;
}

function summarizePriceOverrides(overrides: VenuePriceOverrideDraft[]) {
  if (overrides.length === 0) {
    return "Sin horarios especiales";
  }

  return `${overrides.length} horarios especiales`;
}

function formatReservationPrice(value: number) {
  return `$ ${value}`;
}

function getVenueSaveLabel(state: VenueSaveState) {
  if (state === "saving") return "Guardando...";
  if (state === "saved") return "Guardado";
  if (state === "error") return "Error al guardar";
  return "Se guarda automatico";
}

function createDraftSignature(draft: VenueDraft) {
  return JSON.stringify({
    name: draft.name,
    status: draft.status,
    openingTime: draft.openingTime,
    closingTime: draft.closingTime,
    coachReservationPrice: draft.coachReservationPrice,
    clubCoachReservationDiscount: draft.clubCoachReservationDiscount,
    coachCancellationWindowHours: draft.coachCancellationWindowHours,
    externalCoachesAllowed: draft.externalCoachesAllowed,
    coachHours: draft.coachHours,
    coachPriceOverrides: draft.coachPriceOverrides.map((override) => ({
      dayOfWeek: override.dayOfWeek,
      startTime: override.startTime,
      endTime: override.endTime,
      price: override.price,
    })),
    courts: draft.courts.map((court) => ({
      id: court.id ?? null,
      name: court.name,
      covered: court.covered,
      coachesEnabled: court.coachesEnabled,
    })),
  });
}

type ClubVenuePageClientProps = {
  venueId: string;
};

export function ClubVenuePageClient({ venueId }: ClubVenuePageClientProps) {
  const venueErrorId = "club-venue-error";
  const venueSaveStatusId = "club-venue-save-status";
  const [club, setClub] = useState<ClubProfile | null>(null);
  const [venue, setVenue] = useState<VenueDetail | null>(null);
  const [assignedCoaches, setAssignedCoaches] = useState<VenueCoach[]>([]);
  const [availableCoaches, setAvailableCoaches] = useState<VenueCoach[]>([]);
  const [draft, setDraft] = useState<VenueDraft | null>(null);
  const [loading, setLoading] = useState(true);
  const [saveState, setSaveState] = useState<VenueSaveState>("idle");
  const [assigningCoachId, setAssigningCoachId] = useState<string | null>(null);
  const [assigningCoachCourtId, setAssigningCoachCourtId] = useState<string | null>(null);
  const [removingCoachId, setRemovingCoachId] = useState<string | null>(null);
  const [error, setError] = useState<string | null>(null);
  const lastSavedDraftSignature = useRef<string | null>(null);
  const saveTimer = useRef<ReturnType<typeof setTimeout> | null>(null);
  const pendingSaveRef = useRef<{ draft: VenueDraft; signature: string } | null>(null);

  async function loadVenue() {
    try {
      const response = await fetch(`/api/clubs/venues/${venueId}`, { cache: "no-store" });
      const payload = await response.json().catch(() => null);

      if (!response.ok) {
        setClub(null);
        setVenue(null);
        setAssignedCoaches([]);
        setAvailableCoaches([]);
        setDraft(null);
        setError(response.status === 404 ? "No encontramos la sede." : "No pudimos cargar la sede.");
        return;
      }

      const parsed = clubVenueDetailResponseSchema.parse(payload);
      const nextDraft = createDraft(parsed.venue);
      setClub(parsed.club);
      setVenue(parsed.venue);
      setAssignedCoaches(parsed.assignedCoaches);
      setAvailableCoaches(parsed.availableCoaches);
      setDraft(nextDraft);
      lastSavedDraftSignature.current = createDraftSignature(nextDraft);
      setSaveState("idle");
      setError(null);
    } catch {
      setClub(null);
      setVenue(null);
      setAssignedCoaches([]);
      setAvailableCoaches([]);
      setDraft(null);
      setError("No pudimos cargar la sede.");
    } finally {
      setLoading(false);
    }
  }

  const loadVenueEffect = useEffectEvent(loadVenue);

  useEffect(() => {
    void loadVenueEffect();
  }, [venueId]);

  async function saveDraft(nextDraft: VenueDraft, signature: string, options?: { background?: boolean }) {
    const background = options?.background ?? false;

    if (!background) {
      setSaveState("saving");
      setError(null);
    }

    try {
      const response = await fetch(`/api/clubs/venues/${venueId}`, {
        method: "PATCH",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({
          name: nextDraft.name,
          status: nextDraft.status,
          openingTime: nextDraft.openingTime,
          closingTime: nextDraft.closingTime,
          coachReservationPrice: nextDraft.coachReservationPrice,
          clubCoachReservationDiscount: nextDraft.clubCoachReservationDiscount,
          coachCancellationWindowHours: nextDraft.coachCancellationWindowHours,
          externalCoachesAllowed: nextDraft.externalCoachesAllowed,
          coachHours: nextDraft.coachHours,
          coachPriceOverrides: nextDraft.coachPriceOverrides.map((override) => ({
            dayOfWeek: override.dayOfWeek,
            startTime: override.startTime,
            endTime: override.endTime,
            price: override.price,
          })),
          courts: nextDraft.courts.map((court) => ({
            ...(court.id ? { id: court.id } : {}),
            name: court.name,
            covered: court.covered,
            coachesEnabled: court.coachesEnabled,
          })),
        }),
      });

      const payload = await response.json().catch(() => null);
      if (!response.ok) {
        if (!background) {
          setError(payload?.details?.message ?? "No pudimos guardar la sede.");
          setSaveState("error");
        }
        return;
      }

      lastSavedDraftSignature.current = signature;
      pendingSaveRef.current = null;

      if (!background) {
        const parsed = clubVenueMutationResponseSchema.parse(payload);
        const savedDraft = createDraft(parsed.item);
        setVenue(parsed.item);
        setDraft((current) => {
          if (!current || createDraftSignature(current) !== signature) {
            return current;
          }

          lastSavedDraftSignature.current = createDraftSignature(savedDraft);
          return savedDraft;
        });
        setSaveState("saved");
      }
    } catch {
      if (!background) {
        setError("No pudimos guardar la sede.");
        setSaveState("error");
      }
    }
  }

  const saveDraftEffect = useEffectEvent(saveDraft);

  useEffect(
    () => () => {
      if (saveTimer.current) {
        clearTimeout(saveTimer.current);
        saveTimer.current = null;
      }

      if (pendingSaveRef.current) {
        const pending = pendingSaveRef.current;
        pendingSaveRef.current = null;
        void saveDraftEffect(pending.draft, pending.signature, { background: true });
      }
    },
    []
  );

  useEffect(() => {
    if (!draft || loading) return;

    const signature = createDraftSignature(draft);
    if (signature === lastSavedDraftSignature.current) {
      pendingSaveRef.current = null;
      return;
    }

    setSaveState("saving");
    pendingSaveRef.current = { draft, signature };

    if (saveTimer.current) {
      clearTimeout(saveTimer.current);
    }

    saveTimer.current = setTimeout(() => {
      saveTimer.current = null;
      pendingSaveRef.current = null;
      void saveDraftEffect(draft, signature);
    }, 750);
  }, [draft, loading]);

  function updateDraft(patch: Partial<VenueDraft>) {
    setDraft((current) => (current ? { ...current, ...patch } : current));
  }

  function updateCourt(clientId: string, patch: Partial<VenueCourtDraft>) {
    setDraft((current) =>
      current
        ? {
            ...current,
            courts: current.courts.map((court) => (court.clientId === clientId ? { ...court, ...patch } : court)),
          }
        : current
    );
  }

  function updatePriceOverride(clientId: string, patch: Partial<VenuePriceOverrideDraft>) {
    setDraft((current) =>
      current
        ? {
            ...current,
            coachPriceOverrides: current.coachPriceOverrides.map((override) =>
              override.clientId === clientId ? { ...override, ...patch } : override
            ),
          }
        : current
    );
  }

  function addPriceOverride() {
    setDraft((current) =>
      current
        ? {
            ...current,
            coachPriceOverrides: [
              ...current.coachPriceOverrides,
              {
                clientId: createLocalId("price-override"),
                dayOfWeek: 1,
                startTime: current.openingTime,
                endTime: current.closingTime,
                price: current.coachReservationPrice,
              },
            ],
          }
        : current
    );
  }

  function removePriceOverride(clientId: string) {
    setDraft((current) =>
      current
        ? {
            ...current,
            coachPriceOverrides: current.coachPriceOverrides.filter((override) => override.clientId !== clientId),
          }
        : current
    );
  }

  function updateVenueHours(patch: Partial<Pick<VenueDraft, "openingTime" | "closingTime">>) {
    setDraft((current) =>
      current
        ? (() => {
            const next = { ...current, ...patch };
            const availableRanges = buildDailyAvailabilityRanges(next.openingTime, next.closingTime);

            return {
              ...next,
              coachHours:
                availableRanges.length > 0 ? clampWeeklyAvailabilityRanges(current.coachHours, availableRanges) : current.coachHours,
            };
          })()
        : current
    );
  }

  function addCourt(covered: boolean) {
    setDraft((current) =>
      current
        ? {
            ...current,
            courts: [
              ...current.courts,
              {
                clientId: createLocalId("court"),
                name: `Cancha ${current.courts.length + 1}`,
                covered,
                coachesEnabled: true,
              },
            ],
          }
        : current
    );
  }

  function removeCourt(clientId: string) {
    setDraft((current) =>
      current
        ? {
            ...current,
            courts: current.courts.filter((court) => court.clientId !== clientId),
          }
        : current
    );
  }

  async function assignCoach(coachId: string) {
    setAssigningCoachId(coachId);
    setError(null);

    try {
      const response = await fetch(`/api/clubs/coaches/${coachId}`, {
        method: "PATCH",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({
          affiliation: "club",
          venueId,
          courtId: null,
        }),
      });

      const payload = await response.json().catch(() => null);
      if (!response.ok) {
        setError(payload?.details?.message ?? "No pudimos asignar el coach.");
        return;
      }

      await loadVenue();
    } catch {
      setError("No pudimos asignar el coach.");
    } finally {
      setAssigningCoachId(null);
    }
  }

  async function updateCoachCourt(coachId: string, courtId: string | null) {
    setAssigningCoachCourtId(coachId);
    setError(null);

    try {
      const response = await fetch(`/api/clubs/coaches/${coachId}`, {
        method: "PATCH",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({
          affiliation: "club",
          venueId,
          courtId,
        }),
      });

      const payload = await response.json().catch(() => null);
      if (!response.ok) {
        setError(payload?.details?.message ?? "No pudimos guardar la cancha del coach.");
        return;
      }

      await loadVenue();
    } catch {
      setError("No pudimos guardar la cancha del coach.");
    } finally {
      setAssigningCoachCourtId(null);
    }
  }

  async function removeCoach(coachId: string) {
    setRemovingCoachId(coachId);
    setError(null);

    try {
      const response = await fetch(`/api/clubs/coaches/${coachId}`, {
        method: "PATCH",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({
          affiliation: "club",
          venueId: null,
        }),
      });

      const payload = await response.json().catch(() => null);
      if (!response.ok) {
        setError(payload?.details?.message ?? "No pudimos quitar el coach de la sede.");
        return;
      }

      await loadVenue();
    } catch {
      setError("No pudimos quitar el coach de la sede.");
    } finally {
      setRemovingCoachId(null);
    }
  }

  if (loading) {
    return <p className="mt-8 text-sm text-white/70">Cargando sede...</p>;
  }

  if (!club || !venue || !draft) {
    return (
      <div className="mt-8 max-w-xl rounded-[1.75rem] border border-white/10 bg-[#0f140f]/80 p-6 text-white" role="alert" aria-live="assertive">
        <h2 className="text-2xl font-semibold">Sede no disponible</h2>
        <p id={venueErrorId} className="mt-2 text-sm text-white/65">{error ?? "No encontramos esta sede."}</p>
        <Link
          href="/clubs/coaches"
          className="mt-5 inline-flex h-11 items-center justify-center rounded-xl bg-[#c4d600] px-5 text-sm font-medium text-[#10150d] transition hover:bg-[#d2e63e]"
        >
          Volver al panel del club
        </Link>
      </div>
    );
  }

  const unassignedOrOtherVenueCoaches = availableCoaches.filter((coach) => coach.venue?.id !== venueId);
  const availableCoachRanges = buildDailyAvailabilityRanges(draft.openingTime, draft.closingTime);
  const enabledCourtOptions = draft.courts.filter((court) => court.coachesEnabled && court.id);

  return (
    <section className="space-y-6 text-white">
      <AuthenticatedWorkspaceNavbar
        email={club.contactEmail}
        sections={[
          {
            label: "Calendario",
            href: "/clubs/coaches",
          },
          {
            label: "Analiticas",
            href: "/clubs/coaches?view=analytics",
          },
          {
            label: "Sedes",
            href: "/clubs/coaches?view=venues",
            active: true,
          },
          {
            label: "Profesores",
            href: "/clubs/coaches?view=coaches",
          },
        ]}
        onSignOut={async () => {
          await fetch("/api/clubs/logout", { method: "POST" });
          window.location.href = "/coaches";
        }}
      />

      <div className="rounded-[1.5rem] border border-white/10 bg-[#0f140f]/80 p-6">
        <div>
          <p className="text-xs uppercase tracking-[0.2em] text-[#c4d600]">Sede</p>
          <h2 className="mt-2 text-2xl font-semibold">{venue.name}</h2>
          <p className="mt-2 text-sm text-white/65">{club.name}</p>
        </div>
      </div>

      <article className="rounded-[1.75rem] border border-white/10 bg-[#0f140f]/80 p-6">
        <div className="flex flex-wrap items-center justify-between gap-3">
          <div>
            <p className="text-xs uppercase tracking-[0.2em] text-[#c4d600]">Configuracion</p>
            <h3 className="mt-2 text-xl font-semibold">Configura la sede paso a paso</h3>
            <p className="mt-2 text-sm text-white/65">
              Todo lo importante queda visible de entrada: base, horarios, reservas, canchas y entrenadores. Los cambios se guardan solos.
            </p>
          </div>
          <span
            id={venueSaveStatusId}
            role="status"
            aria-live="polite"
            className={`rounded-full border px-3 py-1 text-xs ${
              saveState === "error"
                ? "border-red-500/30 bg-red-500/10 text-red-200"
                : saveState === "saved"
                  ? "border-[#c4d600]/30 bg-[#c4d600]/10 text-[#d9ef31]"
                  : "border-white/10 bg-black/20 text-white/55"
            }`}
          >
            {getVenueSaveLabel(saveState)}
          </span>
        </div>

        <div className="mt-5 grid gap-3 sm:grid-cols-2 xl:grid-cols-5">
          {[
            { href: "#base-sede", step: "01", title: "Base", detail: "Nombre, estado y externos" },
            { href: "#horarios-sede", step: "02", title: "Horarios", detail: "Apertura y bloques coach" },
            { href: "#reservas-sede", step: "03", title: "Reservas", detail: "Precios y reglas" },
            { href: "#canchas-sede", step: "04", title: "Canchas", detail: "Listado y habilitadas" },
            { href: "#coaches-sede", step: "05", title: "Entrenadores", detail: "Asignaciones y cancha fija" },
          ].map((item) => (
            <a
              key={item.href}
              href={item.href}
              className="rounded-[1.15rem] border border-white/10 bg-black/20 p-4 transition hover:border-[#c4d600]/35 hover:bg-[#c4d600]/7"
            >
              <p className="text-xs uppercase tracking-[0.16em] text-[#c4d600]">{item.step}</p>
              <p className="mt-2 text-base font-medium text-white">{item.title}</p>
              <p className="mt-1 text-xs text-white/55">{item.detail}</p>
            </a>
          ))}
        </div>

        <div id="base-sede" className="mt-5 grid gap-4 lg:grid-cols-[1fr_0.75fr] scroll-mt-24">
          <label className="block text-sm text-white/70">
            Nombre de la sede
            <input
              value={draft.name}
              onChange={(event) => updateDraft({ name: 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"
            />
          </label>
          <div className="grid gap-4 sm:grid-cols-2">
            <label className="block text-sm text-white/70">
              Estado
              <select
                value={draft.status}
                onChange={(event) => updateDraft({ status: event.target.value as "active" | "inactive" })}
                className="mt-2 h-11 w-full rounded-xl border border-white/15 bg-black/30 px-3 text-sm text-white"
              >
                <option value="active">Activa</option>
                <option value="inactive">Inactiva</option>
              </select>
            </label>
            <div className="rounded-[1rem] border border-white/10 bg-black/20 p-4">
              <p className="text-sm text-white/70">Disponible para coaches externos</p>
              <div className="mt-3 flex flex-wrap gap-3">
                <button
                  type="button"
                  onClick={() => updateDraft({ externalCoachesAllowed: true })}
                  className={`rounded-full border px-4 py-2 text-sm transition ${
                    draft.externalCoachesAllowed
                      ? "border-[#c4d600]/40 bg-[#c4d600]/15 text-white"
                      : "border-white/10 bg-black/20 text-white/55 hover:border-white/20 hover:text-white"
                  }`}
                >
                  Si, aceptar externos
                </button>
                <button
                  type="button"
                  onClick={() => updateDraft({ externalCoachesAllowed: false })}
                  className={`rounded-full border px-4 py-2 text-sm transition ${
                    !draft.externalCoachesAllowed
                      ? "border-[#c4d600]/40 bg-[#c4d600]/15 text-white"
                      : "border-white/10 bg-black/20 text-white/55 hover:border-white/20 hover:text-white"
                  }`}
                >
                  No, solo club
                </button>
              </div>
              <p className="mt-3 text-xs text-white/50">
                Si esta prendido, estos horarios aplican para coaches del club y externos. Si esta apagado, solo para los del club.
              </p>
            </div>
          </div>
        </div>

        <div id="horarios-sede" className="mt-6 rounded-[1.5rem] border border-white/10 bg-black/20 p-5 scroll-mt-24">
          <div>
            <div>
              <p className="text-sm font-medium text-white">Horario de apertura y cierre</p>
              <p className="mt-1 text-xs text-white/55">Define una hora de apertura y una de cierre para la sede. La grilla de coaches solo habilita bloques dentro de esa ventana.</p>
            </div>
          </div>
          <div className="mt-4 grid gap-4 sm:grid-cols-2">
            <label className="block text-sm text-white/70">
              Apertura
              <input
                type="time"
                step={1800}
                value={draft.openingTime}
                onChange={(event) => updateVenueHours({ openingTime: 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"
              />
            </label>
            <label className="block text-sm text-white/70">
              Cierre
              <input
                type="time"
                step={1800}
                value={draft.closingTime}
                onChange={(event) => updateVenueHours({ closingTime: 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"
              />
            </label>
          </div>
        </div>

        <div className="mt-6 rounded-[1.5rem] border border-[#c4d600]/25 bg-black/20 p-5">
          <div className="flex flex-wrap items-center justify-between gap-3">
            <div>
              <p className="text-sm font-medium text-white">Horarios disponibles para coaches</p>
              <p className="mt-1 text-xs text-white/55">
                Esto aplica a coaches del club y, si activaste la opcion, tambien a coaches externos. En rojo se marca cuando la sede esta cerrada.
              </p>
            </div>
            <div className="flex flex-wrap items-center gap-2">
              <span className="rounded-full border border-white/10 px-3 py-1 text-xs text-white/60">{summarizeCoachRanges(draft.coachHours)}</span>
              <span className="rounded-full border border-[#c4d600]/35 bg-[#c4d600]/10 px-3 py-1 text-xs font-medium text-[#d9ef31]">
                Visible siempre
              </span>
            </div>
          </div>

          <div className="mt-4 flex flex-wrap gap-3">
            <button
              type="button"
              className="rounded-full border border-[#c4d600]/25 bg-[#c4d600]/8 px-4 py-2 text-sm text-[#d9ef31] transition hover:border-[#c4d600]/55 hover:bg-[#c4d600]/14"
              onClick={() =>
                updateDraft({
                  coachHours: availableCoachRanges.map((range) => ({
                    dayOfWeek: range.dayOfWeek,
                    startTime: range.startTime,
                    endTime: range.endTime,
                  })),
                })
              }
            >
              Copiar horario de apertura
            </button>
            <button
              type="button"
              className="rounded-full border border-white/15 px-4 py-2 text-sm text-white/75 transition hover:border-white/30 hover:text-white"
              onClick={() => updateDraft({ coachHours: [] })}
            >
              Limpiar
            </button>
          </div>

          <div className="mt-4">
            <WeeklyAvailabilityGrid
              value={draft.coachHours}
              onChange={(next) => updateDraft({ coachHours: clampWeeklyAvailabilityRanges(next, availableCoachRanges) })}
              blockedRanges={availableCoachRanges}
              selectedLabel="Horario para coaches"
              openLabel="Horario abierto"
              blockedLabel="La sede esta cerrada"
            />
          </div>
        </div>

        <div id="reservas-sede" className="mt-6 rounded-[1.5rem] border border-white/10 bg-black/20 p-5 scroll-mt-24">
          <div>
            <p className="text-sm font-medium text-white">Reservas de profes</p>
            <p className="mt-1 text-xs text-white/55">
              Configura el precio base de reserva, el descuento para coaches del club y la politica de cancelacion tardia.
            </p>
          </div>

          <div className="mt-4 grid gap-4 lg:grid-cols-3">
            <label className="block text-sm text-white/70">
              Precio base por reserva para clases
              <input
                type="number"
                min={0}
                step={1}
                value={draft.coachReservationPrice}
                onChange={(event) => {
                  const nextBase = Math.max(0, Number(event.target.value || 0));
                  updateDraft({
                    coachReservationPrice: nextBase,
                    clubCoachReservationDiscount: Math.min(draft.clubCoachReservationDiscount, nextBase),
                  });
                }}
                className="mt-2 h-11 w-full rounded-xl border border-white/15 bg-black/30 px-3 text-sm text-white"
              />
            </label>
            <label className="block text-sm text-white/70">
              Descuento para coaches del club
              <input
                type="number"
                min={0}
                max={draft.coachReservationPrice}
                step={1}
                value={draft.clubCoachReservationDiscount}
                onChange={(event) =>
                  updateDraft({
                    clubCoachReservationDiscount: Math.min(Math.max(0, Number(event.target.value || 0)), draft.coachReservationPrice),
                  })
                }
                className="mt-2 h-11 w-full rounded-xl border border-white/15 bg-black/30 px-3 text-sm text-white"
              />
            </label>
            <label className="block text-sm text-white/70">
              Cancelacion tardia desde
              <div className="mt-2 flex items-center gap-3 rounded-xl border border-white/15 bg-black/30 px-3">
                <input
                  type="number"
                  min={0}
                  step={1}
                  value={draft.coachCancellationWindowHours}
                  onChange={(event) =>
                    updateDraft({ coachCancellationWindowHours: Math.max(0, Number(event.target.value || 0)) })
                  }
                  className="h-11 w-full bg-transparent text-sm text-white outline-none"
                />
                <span className="text-sm text-white/45">horas</span>
              </div>
            </label>
          </div>

          <div className="mt-4 rounded-[1.25rem] border border-white/10 bg-[#0d110d] p-4 text-sm text-white/65">
            Coaches externos pagan {formatReservationPrice(draft.coachReservationPrice)}. Coaches del club pagan{" "}
            {formatReservationPrice(Math.max(0, draft.coachReservationPrice - draft.clubCoachReservationDiscount))} despues del descuento.
          </div>

          <div className="mt-4 rounded-[1.25rem] border border-white/10 bg-[#0d110d] p-4">
            <div className="flex flex-wrap items-center justify-between gap-3">
              <div>
                <p className="text-sm font-medium text-white">Precio por horario</p>
                <p className="mt-1 text-xs text-white/55">
                  El precio base aplica a toda la sede. Aqui puedes marcar horarios especiales con otro valor.
                </p>
              </div>
              <div className="flex items-center gap-2">
                <span className="rounded-full border border-white/10 px-3 py-1 text-xs text-white/60">
                  {summarizePriceOverrides(draft.coachPriceOverrides)}
                </span>
                <button
                  type="button"
                  onClick={addPriceOverride}
                  className="rounded-full border border-[#c4d600]/30 bg-[#c4d600]/10 px-4 py-2 text-sm text-[#d9ef31] transition hover:border-[#c4d600]/55 hover:bg-[#c4d600]/15"
                >
                  Agregar horario especial
                </button>
              </div>
            </div>

            {draft.coachPriceOverrides.length === 0 ? (
              <div className="mt-4 rounded-[1rem] border border-dashed border-white/10 bg-black/10 p-4 text-sm text-white/50">
                Sin overrides cargados. El calendario mostrara {formatReservationPrice(draft.coachReservationPrice)} en todos los bloques abiertos.
              </div>
            ) : (
              <div className="mt-4 space-y-3">
                {draft.coachPriceOverrides.map((override) => (
                  <div
                    key={override.clientId}
                    className="grid gap-3 rounded-[1rem] border border-white/10 bg-black/20 p-4 lg:grid-cols-[1.1fr_0.8fr_0.8fr_1fr_auto]"
                  >
                    <label className="block text-sm text-white/70">
                      Dia
                      <select
                        value={override.dayOfWeek}
                        onChange={(event) =>
                          updatePriceOverride(override.clientId, { dayOfWeek: Number(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"
                      >
                        {weekdayLabels.map((label, index) => (
                          <option key={label} value={index}>
                            {label}
                          </option>
                        ))}
                      </select>
                    </label>
                    <label className="block text-sm text-white/70">
                      Desde
                      <input
                        type="time"
                        step={1800}
                        value={override.startTime}
                        onChange={(event) => updatePriceOverride(override.clientId, { startTime: 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"
                      />
                    </label>
                    <label className="block text-sm text-white/70">
                      Hasta
                      <input
                        type="time"
                        step={1800}
                        value={override.endTime}
                        onChange={(event) => updatePriceOverride(override.clientId, { endTime: 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"
                      />
                    </label>
                    <label className="block text-sm text-white/70">
                      Precio para ese horario
                      <input
                        type="number"
                        min={0}
                        step={1}
                        value={override.price}
                        onChange={(event) =>
                          updatePriceOverride(override.clientId, { price: Math.max(0, Number(event.target.value || 0)) })
                        }
                        className="mt-2 h-11 w-full rounded-xl border border-white/15 bg-black/30 px-3 text-sm text-white"
                      />
                    </label>
                    <div className="flex items-end">
                      <button
                        type="button"
                        onClick={() => removePriceOverride(override.clientId)}
                        className="h-11 rounded-xl border border-red-500/25 px-4 text-sm text-red-200 transition hover:bg-red-500/10"
                      >
                        Quitar
                      </button>
                    </div>
                  </div>
                ))}
              </div>
            )}
          </div>

          <div className="mt-4 rounded-[1.25rem] border border-white/10 bg-[#0d110d] p-4 text-sm text-white/65">
            Si cancelan dentro de ese plazo, la reserva se puede mover pero no se devuelve el dinero.
          </div>

          <div className="mt-4 rounded-[1.25rem] border border-dashed border-white/10 bg-black/10 p-4">
            <p className="text-sm font-medium text-white">Espacio para mas configuraciones</p>
            <p className="mt-1 text-xs text-white/50">
              Aqui despues podemos sumar reglas extra de senas, reembolsos, limites o politicas especiales.
            </p>
          </div>
        </div>

        <div id="canchas-sede" className="mt-6 rounded-[1.5rem] border border-[#c4d600]/25 bg-black/20 p-5 scroll-mt-24">
          <div className="flex flex-wrap items-center justify-between gap-3">
            <div>
              <p className="text-sm font-medium text-white">Canchas de la sede</p>
              <p className="mt-1 text-xs text-white/55">Edita las canchas y define cuales quedan disponibles para profes.</p>
            </div>
            <div className="flex flex-wrap items-center gap-2">
              <span className="rounded-full border border-white/10 px-3 py-1 text-xs text-white/60">
                {draft.courts.length} canchas · {draft.courts.filter((court) => court.coachesEnabled).length} para coaches
              </span>
              <span className="rounded-full border border-[#c4d600]/35 bg-[#c4d600]/10 px-3 py-1 text-xs font-medium text-[#d9ef31]">
                Visible siempre
              </span>
            </div>
          </div>

          <div className="mt-4 flex flex-wrap gap-3">
            <button
              type="button"
              className="rounded-full border border-[#c4d600]/25 bg-[#c4d600]/8 px-4 py-2 text-sm text-[#d9ef31] transition hover:border-[#c4d600]/55 hover:bg-[#c4d600]/14"
              onClick={() => addCourt(true)}
            >
              Agregar techada
            </button>
            <button
              type="button"
              className="rounded-full border border-[#c4d600]/25 bg-[#c4d600]/8 px-4 py-2 text-sm text-[#d9ef31] transition hover:border-[#c4d600]/55 hover:bg-[#c4d600]/14"
              onClick={() => addCourt(false)}
            >
              Agregar no techada
            </button>
          </div>

          <div className="mt-4 space-y-3">
            {draft.courts.map((court) => (
              <div key={court.clientId} className="rounded-[1.25rem] border border-white/10 bg-[#0d110d] p-4">
                <div className="grid gap-4 lg:grid-cols-[1fr_0.5fr_auto]">
                  <label className="block text-sm text-white/70">
                    Nombre
                    <input
                      value={court.name}
                      onChange={(event) => updateCourt(court.clientId, { name: 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"
                    />
                  </label>
                  <label className="block text-sm text-white/70">
                    Tipo
                    <select
                      value={court.covered ? "covered" : "open"}
                      onChange={(event) => updateCourt(court.clientId, { covered: event.target.value === "covered" })}
                      className="mt-2 h-11 w-full rounded-xl border border-white/15 bg-black/30 px-3 text-sm text-white"
                    >
                      <option value="covered">Techada</option>
                      <option value="open">No techada</option>
                    </select>
                  </label>
                  <button
                    type="button"
                    className="rounded-xl border border-red-500/25 px-4 py-2 text-sm text-red-200 transition hover:bg-red-500/10"
                    onClick={() => removeCourt(court.clientId)}
                    disabled={draft.courts.length <= 1}
                  >
                    Quitar
                  </button>
                </div>
              </div>
            ))}
          </div>

          <div className="mt-5 rounded-[1.25rem] border border-white/10 bg-[#0d110d] p-4">
            <div className="flex flex-wrap items-center justify-between gap-3">
              <div>
                <p className="text-sm font-medium text-white">Canchas disponibles para coaches</p>
                <p className="mt-1 text-xs text-white/55">Marca las canchas que los profes pueden usar. Por default arrancan todas activas.</p>
              </div>
              <button
                type="button"
                className="rounded-full border border-white/10 px-4 py-2 text-sm text-white/70 transition hover:border-white/20 hover:text-white"
                onClick={() =>
                  setDraft((current) =>
                    current
                      ? {
                          ...current,
                          courts: current.courts.map((court) => ({
                            ...court,
                            coachesEnabled: true,
                          })),
                        }
                      : current
                  )
                }
              >
                Activar todas
              </button>
            </div>

            <div className="mt-4 flex flex-wrap gap-3">
              {draft.courts.map((court) => (
                <button
                  key={`coach-court-${court.clientId}`}
                  type="button"
                  onClick={() => updateCourt(court.clientId, { coachesEnabled: !court.coachesEnabled })}
                  className={`rounded-full border px-4 py-2 text-sm transition ${
                    court.coachesEnabled
                      ? "border-[#c4d600]/35 bg-[#c4d600]/15 text-white"
                      : "border-white/10 bg-black/20 text-white/55 hover:border-white/20 hover:text-white"
                  }`}
                >
                  {court.name}
                </button>
              ))}
            </div>
          </div>
        </div>
      </article>

      <article id="coaches-sede" className="rounded-[1.75rem] border border-white/10 bg-[#0f140f]/80 p-6 scroll-mt-24">
        <div className="flex flex-wrap items-center justify-between gap-3">
          <div>
            <p className="text-xs uppercase tracking-[0.2em] text-[#c4d600]">Entrenadores</p>
            <h3 className="mt-2 text-xl font-semibold">Coaches de esta sede</h3>
            <p className="mt-2 text-sm text-white/65">Cada coach del club pertenece a una sede. Puede trabajar con todas las canchas habilitadas o quedar fijo en una cancha puntual.</p>
          </div>
          <span className="rounded-full border border-white/10 bg-black/20 px-3 py-1 text-xs text-white/60">
            {assignedCoaches.length} en esta sede
          </span>
        </div>

        <div className="mt-5 space-y-3">
          {assignedCoaches.length === 0 ? <p className="text-sm text-white/55">Todavia no hay coaches asignados a esta sede.</p> : null}
          {assignedCoaches.map((coach) => (
            <div key={coach.id} className="rounded-[1.25rem] border border-white/10 bg-black/20 p-5">
              <div className="flex flex-wrap items-start justify-between gap-4">
                <div>
                  <p className="text-lg font-medium text-white">{coach.name}</p>
                  <p className="mt-1 text-sm text-white/60">{coach.email ?? "Sin email"}</p>
                  <div className="mt-3 max-w-xs">
                    <label className="block text-xs uppercase tracking-[0.16em] text-white/45">
                      Cancha asignada
                      <select
                        value={coach.court?.id ?? ""}
                        onChange={(event) => void updateCoachCourt(coach.id, event.target.value || null)}
                        disabled={assigningCoachCourtId === coach.id || enabledCourtOptions.length === 0}
                        className="mt-2 h-11 w-full rounded-xl border border-white/15 bg-black/30 px-3 text-sm text-white disabled:cursor-not-allowed disabled:text-white/40"
                      >
                        <option value="">Asignar todas las canchas</option>
                        {enabledCourtOptions.map((court) => (
                          <option key={court.id} value={court.id}>
                            {court.name}
                          </option>
                        ))}
                      </select>
                    </label>
                    <p className="mt-2 text-xs text-white/50">
                      {enabledCourtOptions.length === 0
                        ? "Primero deja al menos una cancha habilitada para coaches."
                        : coach.court
                          ? "Ese coach solo contara cobertura en la cancha que le asignes."
                          : "Sin cancha fija: el calendario lo ubica en una cancha libre de la sede por cada horario."}
                    </p>
                  </div>
                </div>
                <div className="grid gap-3 sm:grid-cols-4">
                  <div className="rounded-xl border border-white/10 bg-black/20 p-3">
                    <p className="text-xs uppercase tracking-[0.16em] text-white/45">Clases</p>
                    <p className="mt-2 text-lg font-semibold text-white">{coach.metrics.classOffers}</p>
                  </div>
                  <div className="rounded-xl border border-white/10 bg-black/20 p-3">
                    <p className="text-xs uppercase tracking-[0.16em] text-white/45">Solicitudes</p>
                    <p className="mt-2 text-lg font-semibold text-white">{coach.metrics.requestCount}</p>
                  </div>
                  <div className="rounded-xl border border-white/10 bg-black/20 p-3">
                    <p className="text-xs uppercase tracking-[0.16em] text-white/45">Disponibilidad</p>
                    <p className="mt-2 text-lg font-semibold text-white">{coach.metrics.availabilityBlocks}</p>
                  </div>
                  <div className="rounded-xl border border-white/10 bg-black/20 p-3">
                    <p className="text-xs uppercase tracking-[0.16em] text-white/45">Resenas</p>
                    <p className="mt-2 text-lg font-semibold text-white">{formatAverageReview(coach.metrics.averageReview)}</p>
                  </div>
                </div>
                <Button
                  type="button"
                  variant="outline"
                  className="h-10 rounded-xl border-white/15 bg-transparent px-4 text-sm text-white hover:bg-white/5"
                  disabled={removingCoachId === coach.id}
                  onClick={() => void removeCoach(coach.id)}
                >
                  {removingCoachId === coach.id ? "Quitando..." : "Quitar de esta sede"}
                </Button>
              </div>
            </div>
          ))}
        </div>

        <div className="mt-6 rounded-[1.5rem] border border-white/10 bg-black/20 p-5">
          <p className="text-sm font-medium text-white">Otros coaches del club</p>
          <p className="mt-1 text-xs text-white/55">Puedes traer coaches sin sede o moverlos desde otra sede a esta. Al traerlos, se intenta asignar la primera cancha habilitada.</p>

          <div className="mt-4 space-y-3">
            {unassignedOrOtherVenueCoaches.length === 0 ? <p className="text-sm text-white/55">No hay otros coaches disponibles para mover.</p> : null}
            {unassignedOrOtherVenueCoaches.map((coach) => (
              <div key={coach.id} className="flex flex-wrap items-center justify-between gap-3 rounded-[1.25rem] border border-white/10 bg-[#0d110d] p-4">
                <div>
                  <p className="text-base font-medium text-white">{coach.name}</p>
                  <p className="mt-1 text-sm text-white/60">
                    {coach.venue ? `Hoy esta en ${coach.venue.name}` : "Sin sede asignada"} · {coach.email ?? "Sin email"}
                  </p>
                </div>
                <Button
                  type="button"
                  className="h-10 rounded-xl px-4 text-sm font-medium"
                  disabled={assigningCoachId === coach.id}
                  onClick={() => void assignCoach(coach.id)}
                >
                  {assigningCoachId === coach.id ? "Moviendo..." : "Asignar a esta sede"}
                </Button>
              </div>
            ))}
          </div>
        </div>
      </article>

      {error ? <p id={venueErrorId} role="alert" aria-live="assertive" aria-describedby={venueSaveStatusId} className="rounded-xl border border-red-500/40 bg-red-500/10 px-4 py-3 text-sm text-red-200">{error}</p> : null}
    </section>
  );
}
