import type { BlockOf } from "@/lib/blocks/schema";
import { getPublicSchedule, listPublishedEntries, str } from "@/lib/public/content";
import { cn } from "@/lib/utils";
import { Heading, Section, SafeLink } from "./section";
import { MediaImage } from "./media-image";
import { messagesForSite } from "@/lib/services/org-translations";
import type { RenderContext } from "./types";

function Empty({ ctx, what }: { ctx: RenderContext; what: string }) {
  if (!ctx.preview) return null;
  return <p className="rounded-md border border-dashed border-border p-4 text-sm opacity-70">No published {what} yet. This note only shows in preview.</p>;
}

/** Only https/path links from library data are linked; anything else is shown as text. */
function safeHref(v: unknown): string {
  const s = str(v);
  return s.startsWith("/") || s.startsWith("https://") ? s : "";
}

export async function ContentListBlock({ block, ctx }: { block: BlockOf<"contentList">; ctx: RenderContext }) {
  const { props, style } = block;
  const entries = await listPublishedEntries(ctx.siteId, props.typeKey, props.limit);
  return (
    <Section style={style} label={props.heading || props.typeKey}>
      <Heading>{props.heading}</Heading>
      {entries.length === 0 ? (
        <Empty ctx={ctx} what={props.typeKey} />
      ) : (
        <ul className={cn(props.layout === "grid" ? "grid gap-6 md:grid-cols-3" : "space-y-4")}>
          {entries.map((e) => {
            const href = safeHref(e.data.url);
            const summary = str(e.data.summary) || str(e.data.excerpt) || str(e.data.answer) || str(e.data.quote);
            return (
              <li key={e.id} className="blk-card overflow-hidden">
                <MediaImage id={e.featuredMediaId} media={ctx.media} className="aspect-[16/9] w-full object-cover" />
                <div className="p-5">
                  <h3 className="text-lg font-semibold">{href ? <SafeLink href={href} className="hover:underline">{e.title}</SafeLink> : e.title}</h3>
                  {summary && <p className="mt-2 line-clamp-3 text-sm opacity-80">{summary}</p>}
                </div>
              </li>
            );
          })}
        </ul>
      )}
    </Section>
  );
}

export async function PeopleListBlock({ block, ctx }: { block: BlockOf<"speakerList"> | BlockOf<"exhibitorList">; ctx: RenderContext }) {
  const { props, style } = block;
  const typeKey = block.type === "speakerList" ? "speakers" : (block as BlockOf<"exhibitorList">).props.kind;
  const entries = await listPublishedEntries(ctx.siteId, typeKey, props.limit);
  return (
    <Section style={style} label={props.heading || typeKey}>
      <Heading>{props.heading}</Heading>
      {entries.length === 0 ? (
        <Empty ctx={ctx} what={typeKey} />
      ) : (
        <ul className="grid grid-cols-2 gap-6 md:grid-cols-4">
          {entries.map((e) => {
            const sub = str(e.data.jobTitle) || str(e.data.tagline) || str(e.data.company) || str(e.data.tier);
            const org = str(e.data.company);
            const href = safeHref(e.data.website);
            return (
              <li key={e.id} className="text-center">
                <MediaImage id={e.featuredMediaId} media={ctx.media} className="mx-auto aspect-square w-full max-w-[160px] rounded-full object-cover" />
                <p className="mt-3 font-semibold">{href ? <SafeLink href={href} className="hover:underline">{e.title}</SafeLink> : e.title}</p>
                {sub && <p className="text-sm opacity-75">{sub}</p>}
                {org && org !== sub && <p className="text-sm opacity-75">{org}</p>}
              </li>
            );
          })}
        </ul>
      )}
    </Section>
  );
}

export async function SessionScheduleBlock({ block, ctx }: { block: BlockOf<"sessionSchedule">; ctx: RenderContext }) {
  const { props, style } = block;
  const event = props.eventId ? await getPublicSchedule(ctx.siteId, props.eventId) : null;
  if (!event || event.sessions.length === 0) {
    return (
      <Section style={style} label={props.heading}>
        <Heading>{props.heading}</Heading>
        <Empty ctx={ctx} what="sessions" />
      </Section>
    );
  }
  const text = await messagesForSite(ctx.siteId);
  const trackName = new Map(event.tracks.map((t) => [t.id, t.name]));
  const day = (d: Date) => new Intl.DateTimeFormat("en-GB", { dateStyle: "full", timeZone: event.timezone }).format(d);
  const time = (d: Date) => new Intl.DateTimeFormat("en-GB", { timeStyle: "short", timeZone: event.timezone }).format(d);
  const keyOf = (s: (typeof event.sessions)[number]) =>
    props.groupBy === "day" ? day(s.startsAt) : props.groupBy === "track" ? (s.trackId ? trackName.get(s.trackId) ?? text["schedule.other"]! : text["schedule.noTrack"]!) : s.venue || text["schedule.noVenue"]!;
  const groups = new Map<string, typeof event.sessions>();
  for (const s of event.sessions) groups.set(keyOf(s), [...(groups.get(keyOf(s)) ?? []), s]);
  return (
    <Section style={style} label={props.heading}>
      <Heading>{props.heading}</Heading>
      <div className="space-y-8">
        {[...groups.entries()].map(([name, sessions]) => (
          <div key={name}>
            <h3 className="mb-3 text-lg font-semibold">{name}</h3>
            <ul className="blk-card divide-y divide-border">
              {sessions.map((s) => (
                <li key={s.id} className="grid gap-1 p-4 sm:grid-cols-[9rem_1fr]">
                  <p className="text-sm font-medium tabular-nums">{time(s.startsAt)} – {time(s.endsAt)}</p>
                  <div>
                    <p className="font-medium">{s.title}</p>
                    <p className="text-sm opacity-75">
                      {[props.groupBy !== "track" && s.trackId ? trackName.get(s.trackId) : null, props.groupBy !== "venue" ? s.venue : null].filter(Boolean).join(" · ")}
                    </p>
                    {s.speakers.length > 0 && <p className="text-sm opacity-75">{s.speakers.map((x) => x.speaker.title).join(", ")}</p>}
                    {s.description && <p className="mt-1 text-sm opacity-85">{s.description}</p>}
                  </div>
                </li>
              ))}
            </ul>
          </div>
        ))}
      </div>
    </Section>
  );
}

