"use client";

import { useEffect, useState, type ReactNode } from "react";
import Link from "next/link";
import { FacebookLogo, InstagramLogo } from "@phosphor-icons/react";
import ReviewForm from "@/components/account/ReviewForm";
import SaveButton from "@/components/account/SaveButton";
import Organizers from "@/components/events/Organizers";
import { listReviews } from "@/lib/api/auth";
import Icon from "@/components/ui/Icon";
import Photo from "@/components/ui/Photo";
import { mediaUrl } from "@/lib/api/config";
import type { EventDetail } from "@/lib/api/events";
import type { PlaceDetailExtras, PlaceItem, PlaceMedia, PlaceReview } from "@/lib/api/places";
import type { DetailState } from "@/store/createDetailStore";

const TZ = "Asia/Damascus";
const dateTime = new Intl.DateTimeFormat("en-GB", { weekday: "short", day: "numeric", month: "short", year: "numeric", hour: "2-digit", minute: "2-digit", timeZone: TZ });
const dateOnly = new Intl.DateTimeFormat("en-GB", { day: "numeric", month: "short", year: "numeric", timeZone: TZ });
const dayNum = new Intl.DateTimeFormat("en-GB", { day: "numeric", timeZone: TZ });
const monthYear = new Intl.DateTimeFormat("en-GB", { month: "long", year: "numeric", timeZone: TZ });
const time = new Intl.DateTimeFormat("en-GB", { hour: "2-digit", minute: "2-digit", timeZone: TZ });

const STATUS_LABEL: Record<string, string> = { upcoming: "Upcoming", ongoing: "Ongoing", ended: "Ended" };

export type SocialLink = { kind: "instagram" | "facebook"; label: string; href: string };
const SOCIAL = { instagram: InstagramLogo, facebook: FacebookLogo };

/**
 * Loads one item by the `id` query parameter and renders it. Handles the no-id, loading, not-found and error states.
 * Every detail page has the same header and back link; `render` supplies the body.
 */
export default function DetailShell<T extends { name: string; reviewable_id?: number | null }>({
  id,
  detail,
  eyebrow,
  backHref,
  backLabel,
  render,
}: {
  id: string | null;
  detail: DetailState<T>;
  eyebrow: string;
  backHref: string;
  backLabel: string;
  render: (item: T) => ReactNode;
}) {
  const { load } = detail;
  useEffect(() => {
    if (id) void load(id);
  }, [id, load]);

  const back = (
    <Link className="lf-back" href={backHref}>
      <Icon name="arrow_back" />
      {backLabel}
    </Link>
  );

  if (!id) {
    return (
      <div className="lf-empty">
        <p>Choose a place from the list to see its details.</p>
        {back}
      </div>
    );
  }

  if (detail.status === "idle" || detail.status === "loading") {
    return (
      <div className="lf-detail-skel" aria-busy="true" aria-label="Loading">
        <div className="lf-skel" />
      </div>
    );
  }

  if (detail.status === "error" || !detail.item) {
    const notFound = detail.errorStatus === 404;
    return (
      <div className="lf-empty" role={notFound ? undefined : "alert"}>
        <p>{notFound ? "We could not find this item." : "The details could not be loaded."}</p>
        {!notFound && (
          <button type="button" className="lf-chip" onClick={() => void load(id)}>
            Try again
          </button>
        )}
        {back}
      </div>
    );
  }

  const item = detail.item;
  return (
    <article className="lfd">
      {back}
      <header className="lfd-head">
        <span className="eyebrow">{eyebrow}</span>
        <div className="lfd-title-row">
          <h1 className="lfd-title">{item.name}</h1>
          {item.reviewable_id ? <SaveButton reviewableId={item.reviewable_id} name={item.name} /> : null}
        </div>
      </header>
      {render(item)}
    </article>
  );
}

/** Cover photo, then a row of thumbnails under it. Falls back to the striped placeholder when there are no photos. */
export function Gallery({ name, media }: { name: string; media?: PlaceMedia[] }) {
  const urls = [...(media ?? [])]
    .filter((m) => m.path)
    .sort((a, b) => Number(b.is_cover) - Number(a.is_cover))
    .map((m) => mediaUrl(m.path as string));

  if (urls.length === 0) {
    return (
      <figure className="lfd-hero">
        <Photo src={null} label={name} alt={name} />
      </figure>
    );
  }

  return (
    <div className="lfd-gallery">
      <figure className="lfd-hero">
        <img src={urls[0]} alt={name} decoding="async" />
      </figure>
      {urls.length > 1 && (
        <ul className="lfd-thumbs" aria-label="More photos">
          {urls.slice(1).map((src, i) => (
            <li key={src}>
              <img src={src} alt={`${name}, photo ${i + 2}`} loading="lazy" decoding="async" />
            </li>
          ))}
        </ul>
      )}
    </div>
  );
}

export function InfoRow({ icon, children }: { icon: string; children: ReactNode }) {
  return (
    <li>
      <Icon name={icon} />
      <div>{children}</div>
    </li>
  );
}

function Social({ links }: { links: SocialLink[] }) {
  if (links.length === 0) return null;
  return (
    <div className="lfd-social" aria-label="Social media">
      {links.map((l) => {
        const Brand = SOCIAL[l.kind];
        return (
          <a key={l.kind} href={l.href} target="_blank" rel="noopener noreferrer" aria-label={`${l.label} (opens in a new tab)`}>
            <Brand size={20} weight="regular" aria-hidden="true" />
            {l.label}
          </a>
        );
      })}
    </div>
  );
}

const reviewerIds = (r: PlaceDetailExtras["reviews"]) => (r?.items ?? []).flatMap((x) => (x.user ? [x.user.id] : []));

function ReviewList({ reviews }: { reviews: PlaceDetailExtras["reviews"] }) {
  if (!reviews) return null;
  return (
    <section className="lfd-reviews" aria-labelledby="lfd-reviews-h">
      <h2 id="lfd-reviews-h" className="lfd-h2">
        Reviews
      </h2>
      {reviews.count === 0 ? (
        <p className="lf-muted">No reviews yet.</p>
      ) : (
        <>
          <p className="lf-muted">
            <span className="lf-rating">
              <Icon name="star" filled />
              {reviews.avg_rating?.toFixed(1)}
            </span>{" "}
            from {reviews.count} {reviews.count === 1 ? "review" : "reviews"}
          </p>
          <ul className="lfd-review-list">
            {reviews.items.map((r: PlaceReview) => (
              <li key={r.id}>
                <p className="lfd-review-head">
                  <span className="lf-rating">
                    <Icon name="star" filled />
                    {r.rating}
                  </span>
                  {r.user && <span>{r.user.name}</span>}
                  {r.created_at && <time dateTime={r.created_at}>{dateOnly.format(new Date(r.created_at))}</time>}
                </p>
                {r.comment && <p>{r.comment}</p>}
              </li>
            ))}
          </ul>
        </>
      )}
    </section>
  );
}

/** Restaurant, café and activity details. Photos on the left stay in place; details scroll on the right. `tags` are cuisines, categories or service flags. */
export function PlaceDetailBody({ item, tags, links = [], email }: { item: PlaceItem & PlaceDetailExtras; tags: string[]; links?: SocialLink[]; email?: string | null }) {
  const mapHref = item.latitude && item.longitude ? `https://www.google.com/maps?q=${item.latitude},${item.longitude}` : null;

  return (
    <div className="lfd-split">
      <div className="lfd-media">
        <Gallery name={item.name} media={item.media} />
      </div>
      <div className="lfd-body">
        <section className="lfd-card" aria-label="Contact and location">
          <ul className="lfd-info">
            {item.address && <InfoRow icon="location_on">{item.address}</InfoRow>}
            {item.city && <InfoRow icon="apartment">{item.city.name}</InfoRow>}
            {item.phones.map((p) => (
              <InfoRow key={p.id} icon="call">
                <a href={`tel:${p.phone}`}>{p.phone}</a>
                {p.label && <small>{p.label}</small>}
              </InfoRow>
            ))}
            {email && (
              <InfoRow icon="mail">
                <a href={`mailto:${email}`}>{email}</a>
              </InfoRow>
            )}
            {item.website_url && (
              <InfoRow icon="language">
                <a href={item.website_url} target="_blank" rel="noopener noreferrer">
                  {item.website_url.replace(/^https?:\/\//, "").replace(/\/$/, "")}
                </a>
              </InfoRow>
            )}
          </ul>
          <Social links={links} />
          {mapHref && (
            <a className="btn btn-rose lfd-map" href={mapHref} target="_blank" rel="noopener noreferrer">
              <Icon name="map" />
              Open in Google Maps
            </a>
          )}
        </section>
        {item.description && <p className="lfd-lead">{item.description}</p>}
        {tags.length > 0 && (
          <ul className="lf-tags" aria-label="Details">
            {tags.map((t) => (
              <li key={t}>{t}</li>
            ))}
          </ul>
        )}
        <ReviewList reviews={item.reviews} />
        {item.reviewable_id ? <ReviewForm reviewableId={item.reviewable_id} reviewerIds={reviewerIds(item.reviews)} /> : null}
      </div>
    </div>
  );
}

export function EventDetailBody({ item }: { item: EventDetail }) {
  const start = item.starts_at ? new Date(item.starts_at) : null;
  const end = item.ends_at ? new Date(item.ends_at) : null;
  const price = item.is_free ? "Free" : item.price_from ? `From ${item.price_from}${item.currency ? ` ${item.currency}` : ""}` : "Price on request";
  const when = start && end ? `${time.format(start)} to ${time.format(end)}` : start ? time.format(start) : null;

  return (
    <div className="lfd-split">
      <div className="lfd-media">
        <Gallery name={item.name} media={item.media} />
      </div>
      <div className="lfd-body">
        <section className="lfd-card" aria-label="Event details">
          {start && (
            <div className="lfd-date">
              <b>{dayNum.format(start)}</b>
              <span>{monthYear.format(start)}</span>
            </div>
          )}
          <ul className="lfd-info">
            {when && <InfoRow icon="schedule">{when}{end && <small>{dateOnly.format(end) === dateOnly.format(start!) ? "" : `Ends ${dateTime.format(end)}`}</small>}</InfoRow>}
            {item.venue_name && <InfoRow icon="place">{item.venue_name}</InfoRow>}
            {item.city && <InfoRow icon="apartment">{item.city.name}</InfoRow>}
            {item.category && <InfoRow icon="sell">{item.category.name}</InfoRow>}
            <InfoRow icon="confirmation_number">{price}</InfoRow>
          </ul>
          <span className="lfd-status" data-status={item.status}>
            {STATUS_LABEL[item.status] ?? item.status}
          </span>
        </section>
        {item.description && <p className="lfd-lead">{item.description}</p>}
        <Organizers organizers={item.organizers} />
        {item.reviewable_id ? <EventReviews reviewableId={item.reviewable_id} /> : null}
      </div>
    </div>
  );
}

/** Event payloads carry no reviews, so they are fetched by reviewable id. A failed fetch just hides the list. */
function EventReviews({ reviewableId }: { reviewableId: number }) {
  const [reviews, setReviews] = useState<PlaceDetailExtras["reviews"]>(null);
  useEffect(() => {
    const ctl = new AbortController();
    listReviews(reviewableId, ctl.signal)
      .then(({ items, meta }) => {
        const count = meta?.total ?? items.length;
        // ponytail: average of the first 20 reviews; ask the API for avg_rating if events get more.
        const avg = items.length ? items.reduce((sum, r) => sum + r.rating, 0) / items.length : null;
        setReviews({ count, avg_rating: avg, items });
      })
      .catch(() => {});
    return () => ctl.abort();
  }, [reviewableId]);
  return (
    <>
      <ReviewList reviews={reviews ?? { count: 0, avg_rating: null, items: [] }} />
      <ReviewForm reviewableId={reviewableId} reviewerIds={reviewerIds(reviews)} />
    </>
  );
}
