import type { Metadata } from "next";
import { notFound } from "next/navigation";
import { getServerSession } from "next-auth";
import Link from "next/link";
import Image from "next/image";
import { authOptions } from "@/lib/auth";
import { tripService } from "@/server/services/trip.service";
import { bookingService } from "@/server/services/booking.service";
import { bookingRepo } from "@/server/repositories/booking.repo";
import { trustService } from "@/server/services/trust.service";
import { formatRupiah } from "@/lib/utils";
import { formatTripCalendarDateRangeLong } from "@/lib/trip-dates";
import { siteConfig, siteUrl, absoluteUrl } from "@/lib/site";
import { JoinTripButton } from "@/features/trip/components/join-trip-button";
import { CancelTripButton } from "@/features/trip/components/cancel-trip-button";
import { CancelBookingButton } from "@/features/booking/components/cancel-booking-button";
import { OrganizerJoinRequests } from "@/features/trip/components/organizer-join-requests";
import { OrganizerTrustPanel } from "@/features/trip/components/organizer-trust-panel";
import { TripProgramBlock } from "@/features/trip/components/trip-program-block";
import { ImageGallery } from "@/features/trip/components/image-gallery";
import { TripReviewSection } from "@/features/review/components/trip-review-section";
import { RefundPolicySection } from "@/features/refund/components/refund-policy-section";
import { categoryMeta } from "@/lib/activity-category";
import { vibeMeta } from "@/lib/vibe";
import { isFreeTrip } from "@/lib/trip-pricing";
import {
  isPastTripLastDayForReview,
  isTripDepartureDayPast,
} from "@/lib/trip-dates";
import { previewRefund } from "@/lib/refund-policy";
import {
  MapPin,
  CalendarDays,
  Wallet,
  UserRound,
  Zap,
  Users,
} from "lucide-react";

export async function generateMetadata({
  params,
}: {
  params: Promise<{ id: string }>;
}): Promise<Metadata> {
  const { id } = await params;
  let trip;
  try {
    trip = await tripService.getTripById(id);
  } catch {
    return {
      title: "Trip tidak ditemukan",
      robots: { index: false, follow: false },
    };
  }

  const title = `${trip.title} — ${trip.destination}`;
  const fallbackDescription = `Open trip ${trip.destination} di ${trip.location}, ${formatTripCalendarDateRangeLong(trip.date, trip.endDate)}. Harga ${formatRupiah(trip.price)}/orang, max ${trip.maxParticipants} peserta. Gabung di ${siteConfig.name}.`;
  const description =
    trip.description?.replace(/\s+/g, " ").trim().slice(0, 160) ||
    fallbackDescription;

  // OG/Twitter image otomatis di-inject dari `opengraph-image.tsx` colocated.
  return {
    title,
    description,
    alternates: { canonical: `/trips/${id}` },
    openGraph: {
      type: "article",
      title,
      description,
      url: `/trips/${id}`,
    },
    twitter: {
      card: "summary_large_image",
      title,
      description,
    },
  };
}

export default async function TripDetailPage({
  params,
}: {
  params: Promise<{ id: string }>;
}) {
  const { id } = await params;
  const session = await getServerSession(authOptions);

  let trip;
  try {
    trip = await tripService.getTripById(id);
  } catch {
    notFound();
  }

  const organizerTrust = await trustService.getOrganizerTrust(
    trip.organizerId
  );

  const activeParticipants = trip.participants.filter(
    (p) => p.status !== "CANCELLED"
  );
  const confirmedParticipants = activeParticipants.filter(
    (p) => p.status === "CONFIRMED"
  );
  const pendingParticipants = activeParticipants.filter(
    (p) => p.status === "PENDING"
  );
  const participantCount = activeParticipants.length;
  const confirmedCount = confirmedParticipants.length;
  const spotsLeft = trip.maxParticipants - participantCount;
  const fillPercent = Math.min(
    (participantCount / trip.maxParticipants) * 100,
    100
  );
  const isOrganizer = session?.user?.id === trip.organizerId;
  const currentParticipation = session?.user
    ? trip.participants.find(
        (p) => p.userId === session.user.id && p.status !== "CANCELLED"
      )
    : null;

  const isDeparturePast = isTripDepartureDayPast(trip.date);
  const canReview =
    !!session?.user &&
    !isOrganizer &&
    currentParticipation?.status === "CONFIRMED" &&
    isPastTripLastDayForReview(trip.date, trip.endDate);

  const myReview = session?.user
    ? trip.reviews.find((r) => r.userId === session.user.id) ?? null
    : null;

  const averageRating =
    trip.reviews.length > 0
      ? Math.round(
          (trip.reviews.reduce((s, r) => s + r.rating, 0) /
            trip.reviews.length) *
            10
        ) / 10
      : null;

  const tripIsFree = isFreeTrip(trip);

  // Booking peserta saat ini — dipakai untuk render CancelBookingButton vs
  // tombol "Batal Ikut" biasa. Hanya untuk non-organizer yang ikut trip.
  const myBooking =
    session?.user && !isOrganizer && currentParticipation
      ? await bookingService.getByTripAndUser(trip.id, session.user.id)
      : null;

  // Untuk CancelTripButton: jumlah booking PAID/PARTIALLY_REFUNDED (yang akan
  // auto-refund). Hanya dihitung saat organizer mengakses trip yang masih
  // bisa dibatalkan.
  const canOrganizerCancel =
    isOrganizer &&
    (trip.status === "OPEN" || trip.status === "FULL") &&
    !isDeparturePast;
  const paidBookingCount = canOrganizerCancel
    ? await bookingRepo.countSettledForTrip(trip.id)
    : 0;

  // Preview refund untuk CancelBookingButton (server-side supaya konsisten
  // dengan service yang juga pakai policy yang sama).
  const refundPreview =
    myBooking && myBooking.status === "PAID" && !isDeparturePast
      ? previewRefund(myBooking.amount, trip.date)
      : null;

  const catMeta = categoryMeta(trip.category);

  const tripUrl = absoluteUrl(`/trips/${trip.id}`);
  const eventStatus =
    trip.status === "OPEN"
      ? "https://schema.org/EventScheduled"
      : trip.status === "CLOSED"
      ? "https://schema.org/EventCancelled"
      : "https://schema.org/EventScheduled";
  const offerAvailability =
    trip.status === "OPEN"
      ? "https://schema.org/InStock"
      : trip.status === "FULL"
      ? "https://schema.org/SoldOut"
      : "https://schema.org/Discontinued";

  const jsonLd = {
    "@context": "https://schema.org",
    "@graph": [
      {
        "@type": "Event",
        "@id": `${tripUrl}#event`,
        name: trip.title,
        description: trip.description ?? undefined,
        startDate: trip.date.toISOString(),
        endDate: (trip.endDate ?? trip.date).toISOString(),
        eventStatus,
        eventAttendanceMode: "https://schema.org/OfflineEventAttendanceMode",
        location: {
          "@type": "Place",
          name: trip.destination,
          address: {
            "@type": "PostalAddress",
            addressLocality: trip.location,
            addressCountry: "ID",
          },
        },
        image: trip.images.length
          ? trip.images.map((i) => i.url)
          : [absoluteUrl("/images/SeTrip.png")],
        organizer: {
          "@type": "Person",
          name: trip.organizer.name,
        },
        offers: {
          "@type": "Offer",
          url: tripUrl,
          price: trip.price,
          priceCurrency: "IDR",
          availability: offerAvailability,
          validFrom: trip.createdAt.toISOString(),
        },
        maximumAttendeeCapacity: trip.maxParticipants,
        ...(averageRating && trip.reviews.length > 0
          ? {
              aggregateRating: {
                "@type": "AggregateRating",
                ratingValue: averageRating,
                reviewCount: trip.reviews.length,
                bestRating: 5,
                worstRating: 1,
              },
            }
          : {}),
        isAccessibleForFree: false,
        inLanguage: "id-ID",
      },
      {
        "@type": "BreadcrumbList",
        "@id": `${tripUrl}#breadcrumbs`,
        itemListElement: [
          { "@type": "ListItem", position: 1, name: "Beranda", item: siteUrl },
          {
            "@type": "ListItem",
            position: 2,
            name: "Open Trip",
            item: absoluteUrl("/trips"),
          },
          {
            "@type": "ListItem",
            position: 3,
            name: trip.destination,
            item: tripUrl,
          },
        ],
      },
    ],
  };

  return (
    <div className="mx-auto max-w-3xl px-4 py-4 sm:py-8">
      <script
        type="application/ld+json"
        dangerouslySetInnerHTML={{ __html: JSON.stringify(jsonLd) }}
      />
      {/* Breadcrumb */}
      <div className="mb-3 flex items-center gap-2 text-xs text-neutral-500 sm:mb-4 sm:text-sm">
        <Link href="/trips" className="hover:text-primary-600">
          Open Trip
        </Link>
        <span>/</span>
        <span className="truncate text-neutral-700">{trip.destination}</span>
      </div>

      <div className="overflow-hidden rounded-2xl border border-neutral-200 bg-white shadow-sm">
        {/* Image Gallery */}
        <ImageGallery images={trip.images} />

        {/* Title bar */}
        <div className="border-b border-neutral-100 px-4 py-3 sm:px-6 sm:py-4">
          <div className="flex items-start justify-between gap-2">
            <div className="min-w-0">
              <h1 className="text-lg font-bold text-neutral-800 sm:text-xl">
                {trip.title}
              </h1>
              <p className="mt-0.5 flex flex-wrap items-center gap-1.5 text-sm text-neutral-500">
                <span aria-hidden>{catMeta.icon}</span>
                <span className="rounded-full bg-neutral-100 px-1.5 py-0.5 text-[10px] font-semibold uppercase tracking-wide text-neutral-600">
                  {catMeta.label}
                </span>
                {trip.vibe && (
                  <span
                    className="inline-flex items-center gap-0.5 rounded-full bg-secondary-100 px-1.5 py-0.5 text-[10px] font-semibold uppercase tracking-wide text-secondary-700"
                    title={vibeMeta(trip.vibe).description}
                  >
                    <span aria-hidden>{vibeMeta(trip.vibe).icon}</span>
                    <span>{vibeMeta(trip.vibe).label}</span>
                  </span>
                )}
                <span className="truncate">{trip.destination}</span>
              </p>
            </div>
            <span
              className={`shrink-0 rounded-full px-2.5 py-0.5 text-xs font-bold sm:px-3 sm:py-1 ${
                trip.status === "OPEN"
                  ? "bg-primary-100 text-primary-700"
                  : trip.status === "FULL"
                  ? "bg-amber-100 text-amber-700"
                  : "bg-neutral-100 text-neutral-500"
              }`}
            >
              {trip.status}
            </span>
          </div>
        </div>

        <div className="space-y-5 p-4 sm:space-y-6 sm:p-6">
          {/* Info Grid */}
          <div className="grid grid-cols-2 gap-2 sm:gap-3">
            <div className="flex items-center gap-2 rounded-xl bg-neutral-50 p-3 sm:gap-3 sm:p-4">
              <span className="flex h-8 w-8 shrink-0 items-center justify-center rounded-lg bg-secondary-100 sm:h-10 sm:w-10">
                <MapPin
                  size={18}
                  strokeWidth={1.75}
                  aria-hidden
                  className="text-secondary-700"
                />
              </span>
              <div className="min-w-0">
                <p className="text-[10px] font-medium text-neutral-400 sm:text-xs">Lokasi</p>
                <p className="truncate text-xs font-semibold text-neutral-800 sm:text-sm">{trip.location}</p>
              </div>
            </div>

            <div className="flex items-center gap-2 rounded-xl bg-neutral-50 p-3 sm:gap-3 sm:p-4">
              <span className="flex h-8 w-8 shrink-0 items-center justify-center rounded-lg bg-secondary-100 sm:h-10 sm:w-10">
                <CalendarDays
                  size={18}
                  strokeWidth={1.75}
                  aria-hidden
                  className="text-secondary-700"
                />
              </span>
              <div className="min-w-0">
                <p className="text-[10px] font-medium text-neutral-400 sm:text-xs">Tanggal</p>
                <p className="truncate text-xs font-semibold text-neutral-800 sm:text-sm">
                  {formatTripCalendarDateRangeLong(trip.date, trip.endDate)}
                </p>
              </div>
            </div>

            <div className="flex items-center gap-2 rounded-xl bg-primary-50 p-3 sm:gap-3 sm:p-4">
              <span className="flex h-8 w-8 shrink-0 items-center justify-center rounded-lg bg-primary-100 sm:h-10 sm:w-10">
                <Wallet
                  size={18}
                  strokeWidth={1.75}
                  aria-hidden
                  className="text-primary-700"
                />
              </span>
              <div className="min-w-0">
                <p className="text-[10px] font-medium text-primary-600 sm:text-xs">Harga</p>
                <p className="text-base font-bold text-primary-700 sm:text-xl">
                  {formatRupiah(trip.price)}
                </p>
              </div>
            </div>

            <div className="flex items-center gap-2 rounded-xl bg-neutral-50 p-3 sm:gap-3 sm:p-4">
              <span className="flex h-8 w-8 shrink-0 items-center justify-center rounded-lg bg-neutral-200 sm:h-10 sm:w-10">
                <UserRound
                  size={18}
                  strokeWidth={1.75}
                  aria-hidden
                  className="text-neutral-600"
                />
              </span>
              <div className="min-w-0">
                <p className="text-[10px] font-medium text-neutral-400 sm:text-xs">Organizer</p>
                <Link
                  href={`/u/${trip.organizer.id}`}
                  className="truncate text-xs font-semibold text-neutral-800 hover:text-primary-700 sm:text-sm"
                >
                  {trip.organizer.name}
                </Link>
              </div>
            </div>
          </div>

          <OrganizerTrustPanel
            name={trip.organizer.name}
            image={trip.organizer.image}
            trust={organizerTrust}
          />

          {/* Participant Progress */}
          <div className="rounded-xl border border-neutral-200 p-3 sm:p-4">
            <div className="mb-2 flex items-center justify-between gap-2">
              <div className="flex items-center gap-2">
                <span className="text-xs font-semibold text-neutral-700 sm:text-sm">
                  Peserta
                </span>
                {spotsLeft > 0 && spotsLeft <= 3 && (
                  <span className="inline-flex items-center gap-1 rounded-full bg-amber-100 px-2 py-0.5 text-[10px] font-bold text-amber-800 sm:text-[11px]">
                    <Zap size={11} strokeWidth={2} aria-hidden />
                    Tinggal {spotsLeft} spot!
                  </span>
                )}
                {spotsLeft <= 0 && (
                  <span className="rounded-full bg-neutral-200 px-2 py-0.5 text-[10px] font-bold text-neutral-700 sm:text-[11px]">
                    Penuh
                  </span>
                )}
              </div>
              <span className="text-xs font-bold text-neutral-800 sm:text-sm">
                {participantCount}{" "}
                <span className="font-normal text-neutral-400">
                  / {trip.maxParticipants}
                </span>
              </span>
            </div>
            <div className="h-2 overflow-hidden rounded-full bg-neutral-100 sm:h-2.5">
              <div
                className={`h-full rounded-full transition-all ${
                  fillPercent >= 100
                    ? "bg-amber-500"
                    : fillPercent >= 70
                    ? "bg-secondary-500"
                    : "bg-primary-500"
                }`}
                style={{ width: `${fillPercent}%` }}
              />
            </div>
            <p className="mt-1.5 text-[11px] text-neutral-500 sm:text-xs">
              Maksimal {trip.maxParticipants} orang. Saat ini {participantCount}{" "}
              mendaftar, {confirmedCount} sudah disetujui organizer.
            </p>
            <p className="mt-1 text-[11px] text-neutral-500 sm:text-xs">
              {spotsLeft > 0
                ? `Masih ada ${spotsLeft} tempat — yuk gabung!`
                : "Trip sudah penuh"}
              {confirmedCount < participantCount && (
                <>
                  {" "}
                  · {participantCount - confirmedCount} menunggu persetujuan
                  organizer
                </>
              )}
            </p>
            {confirmedCount > 0 && (
              <p className="mt-2 flex flex-wrap items-center gap-x-1 gap-y-0.5 text-[11px] text-neutral-600 sm:text-xs">
                <Users
                  size={13}
                  strokeWidth={1.75}
                  aria-hidden
                  className="text-neutral-400"
                />
                Sudah join:{" "}
                <span className="font-medium text-neutral-800">
                  {confirmedParticipants
                    .slice(0, 3)
                    .map((p) => p.user.name.split(" ")[0])
                    .join(", ")}
                </span>
                {confirmedCount > 3 && (
                  <span className="text-neutral-500">
                    {" "}
                    +{confirmedCount - 3} lainnya
                  </span>
                )}
              </p>
            )}
          </div>

          <TripProgramBlock
            meetingPoint={trip.meetingPoint}
            itinerary={trip.itinerary}
            itineraryItems={trip.itineraryItems.map((i) => ({
              day: i.day,
              startTime: i.startTime,
              endTime: i.endTime,
              activity: i.activity,
              order: i.order,
            }))}
            whatsIncluded={trip.whatsIncluded}
            whatsExcluded={trip.whatsExcluded}
          />

          {/* Description */}
          {trip.description && (
            <div>
              <h2 className="mb-2 text-xs font-bold text-neutral-700 sm:text-sm">
                Deskripsi Trip
              </h2>
              <p className="whitespace-pre-wrap text-xs leading-relaxed text-neutral-600 sm:text-sm">
                {trip.description}
              </p>
            </div>
          )}

          {isOrganizer && pendingParticipants.length > 0 && (
            <OrganizerJoinRequests
              tripId={trip.id}
              pending={pendingParticipants.map((p) => ({
                id: p.id,
                user: p.user,
              }))}
            />
          )}

          {/* Action */}
          <JoinTripButton
            tripId={trip.id}
            isLoggedIn={!!session?.user}
            isOrganizer={isOrganizer}
            isJoined={!!currentParticipation}
            isFree={tripIsFree}
            participationStatus={
              currentParticipation?.status === "PENDING" ||
              currentParticipation?.status === "CONFIRMED"
                ? currentParticipation.status
                : null
            }
            bookingStatus={myBooking?.status ?? null}
            isFull={spotsLeft <= 0}
            tripStatus={trip.status}
            isDeparturePast={isDeparturePast}
            hideCancelButton={!!refundPreview}
          />

          {/* Peserta PAID: cancel + request refund (lewat policy default). */}
          {refundPreview && (
            <CancelBookingButton
              tripId={trip.id}
              preview={{
                days: refundPreview.days,
                refundAmount: refundPreview.refundAmount,
                bookingAmount: refundPreview.bookingAmount,
                tierLabel: refundPreview.tier.label,
              }}
            />
          )}

          {/* Organizer: batalkan trip (auto-refund peserta PAID). */}
          {canOrganizerCancel && (
            <CancelTripButton
              tripId={trip.id}
              paidParticipantCount={paidBookingCount}
            />
          )}

          {/* Kebijakan refund — transparency sebelum user cancel. */}
          {!tripIsFree && <RefundPolicySection />}

          <TripReviewSection
            tripId={trip.id}
            reviews={trip.reviews.map((r) => ({
              id: r.id,
              rating: r.rating,
              comment: r.comment,
              createdAt: r.createdAt,
              user: r.user,
            }))}
            averageRating={averageRating}
            canReview={canReview}
            myReview={
              myReview
                ? { rating: myReview.rating, comment: myReview.comment }
                : null
            }
          />

          {/* Peserta yang sudah disetujui organizer (publik) */}
          <div>
            <h2 className="mb-1 text-xs font-bold text-neutral-700 sm:text-sm">
              Peserta terkonfirmasi ({confirmedCount})
            </h2>
            <p className="mb-3 text-[11px] text-neutral-500 sm:text-xs">
              Kenalan dulu sebelum berangkat — klik kartu untuk lihat profil.
            </p>
            {confirmedCount === 0 ? (
              <p className="text-xs text-neutral-400 sm:text-sm">
                Belum ada peserta yang dikonfirmasi.{" "}
                {pendingParticipants.length > 0
                  ? "Cek permintaan join di atas untuk menyetujui peserta."
                  : "Jadilah yang pertama mendaftar!"}
              </p>
            ) : (
              <ul className="grid gap-2 sm:grid-cols-2">
                {confirmedParticipants.map((p) => {
                  const interests = p.user.profile?.interests ?? [];
                  const city = p.user.profile?.city;
                  return (
                    <li key={p.id}>
                      <Link
                        href={`/u/${p.user.id}`}
                        className="flex items-start gap-3 rounded-xl border border-neutral-200 bg-white px-3 py-2.5 transition-colors hover:border-primary-300 hover:bg-primary-50/30"
                      >
                        {p.user.image ? (
                          <Image
                            src={p.user.image}
                            alt=""
                            width={40}
                            height={40}
                            className="h-10 w-10 shrink-0 rounded-full object-cover"
                          />
                        ) : (
                          <div className="flex h-10 w-10 shrink-0 items-center justify-center rounded-full bg-primary-600 text-sm font-bold text-white">
                            {p.user.name.charAt(0).toUpperCase()}
                          </div>
                        )}
                        <div className="min-w-0 flex-1">
                          <p className="truncate text-sm font-semibold text-neutral-800">
                            {p.user.name}
                          </p>
                          {city && (
                            <p className="flex items-center gap-1 truncate text-[11px] text-neutral-500 sm:text-xs">
                              <MapPin
                                size={11}
                                strokeWidth={1.75}
                                aria-hidden
                                className="shrink-0"
                              />
                              {city}
                            </p>
                          )}
                          {interests.length > 0 && (
                            <div className="mt-1 flex flex-wrap gap-1">
                              {interests.slice(0, 3).map((tag) => (
                                <span
                                  key={tag}
                                  className="rounded-full bg-secondary-50 px-1.5 py-0.5 text-[10px] font-medium text-secondary-700"
                                >
                                  #{tag}
                                </span>
                              ))}
                              {interests.length > 3 && (
                                <span className="text-[10px] text-neutral-400">
                                  +{interests.length - 3}
                                </span>
                              )}
                            </div>
                          )}
                        </div>
                      </Link>
                    </li>
                  );
                })}
              </ul>
            )}
          </div>
        </div>
      </div>
    </div>
  );
}
