"use client";

import { useQuery } from "@tanstack/react-query";
import { apiClient } from "@/lib/api-client";
import { useParams, useRouter } from "next/navigation";
import Image from "next/image";
import { useState } from "react";
import { useBookingStore } from "@/lib/booking-store";
import {
  ChevronLeft,
  Calendar,
  MapPin,
  Clock,
  Train,
  Bus,
  Check,
  AlertCircle,
  Loader2,
  ArrowRight,
  Shield,
  X,
  Star,
  Bed,
  Armchair,
} from "lucide-react";

// ─── Types ────────────────────────────────────────────────────────────────────

interface Station {
  id: string;
  code: string;
  name: string;
  city: string;
  countryCode: string;
}

interface TrainInfo {
  id: string;
  number: string;
  name: string;
  operatorName: string;
}

interface RouteStop {
  sequence: number;
  station: Station;
}

interface Schedule {
  id: string;
  departureAt: string;
  arrivalAt: string;
  durationMinutes: number;
  status: string;
  stopsCount: number;
  originStation: Station;
  destinationStation: Station;
  train: TrainInfo;
  routeStops?: RouteStop[];
}

interface CoachTypeInfo {
  id: string;
  name: string;
  code: string;
  type: string; // 'passenger' | 'sleeper' | 'dining' | 'baggage'
}

interface PriceTier {
  id: string;
  packageId: string;
  seatType: string;
  label: string;
  priceMinor: number;
  currency: string;
  availableSeats: number;
  bookedSeats: number;
  seatClass?: { coachType?: CoachTypeInfo };
}

interface PackageDetail {
  id: string;
  code: string;
  name: string;
  description: string | null;
  status: string;
  boardingTime: string;
  departureTime: string;
  arrivalTime: string;
  totalCapacity: number;
  bookedCount: number;
  includedServices: string[];
  coachConfiguration: string;
  busTransferIncluded: boolean;
  busTransferRoute: string | null;
  validFrom: string;
  validUntil: string;
  journeyType: 'ONE_WAY' | 'ROUND_TRIP';
  priceTiers: PriceTier[];
  outboundSchedule: Schedule;
  returnSchedule: Schedule | null;
}

// ─── Helpers ──────────────────────────────────────────────────────────────────

// Train schedules are stored/computed server-side in Ethiopian time (EAT - UTC+3) —
// pinning display to the same zone keeps this page consistent with every other
// booking page and the voucher PDF, regardless of the viewing device's own timezone.
function fmt(iso: string, opts?: Intl.DateTimeFormatOptions): string {
  try {
    return new Date(iso).toLocaleDateString("en-US", {
      weekday: "short", month: "short", day: "numeric",
      ...opts,
      timeZone: "Africa/Addis_Ababa",
    });
  } catch { return iso; }
}

function fmtTime(iso: string): string {
  try {
    return new Date(iso).toLocaleTimeString("en-US", { hour: "numeric", minute: "2-digit", hour12: true, timeZone: "Africa/Addis_Ababa" });
  } catch { return iso; }
}

function durationLabel(minutes: number): string {
  const h = Math.floor(minutes / 60);
  const m = minutes % 60;
  return m ? `${h}h ${m}m` : `${h}h`;
}

function stripBullet(s: string): string {
  return s.replace(/^[••\-\t\s]+/, "").trim();
}

function formatPrice(minor: number, currency: string): string {
  return `${currency} ${(minor / 100).toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 2 })}`;
}

// ─── Journey Card ─────────────────────────────────────────────────────────────

function JourneyCard({ schedule, label }: { schedule: Schedule; label: string }) {
  const dep = new Date(schedule.departureAt);
  const arr = new Date(schedule.arrivalAt);
  const isSameDay = dep.toDateString() === arr.toDateString();

  return (
    <div className="bg-white dark:bg-gray-900 rounded-2xl border border-gray-100 dark:border-gray-800 overflow-hidden">
      <div className="flex items-center gap-2 px-5 py-3 bg-gray-50 dark:bg-gray-800/60 border-b border-gray-100 dark:border-gray-800">
        <Train className="w-4 h-4 text-primary" />
        <span className="text-sm font-bold text-gray-800 dark:text-white">{label}</span>
        <span className="ml-auto text-xs text-gray-400">{schedule.train.number}</span>
      </div>

      <div className="p-5">
        {/* Route row */}
        <div className="flex items-center gap-3">
          {/* Origin */}
          <div className="flex-1 min-w-0">
            <p className="text-[10px] font-semibold text-gray-400 uppercase tracking-wide">From</p>
            <p className="text-xl font-extrabold text-gray-900 dark:text-white truncate">
              {schedule.originStation.code}
            </p>
            <p className="text-xs text-gray-500 truncate">{schedule.originStation.name.trim()}</p>
          </div>

          {/* Center: duration + arrow */}
          <div className="flex flex-col items-center gap-1 flex-shrink-0">
            <span className="text-[10px] text-gray-400 font-medium">
              {durationLabel(schedule.durationMinutes)}
            </span>
            <div className="relative w-16 flex items-center">
              <div className="h-px w-full bg-gray-200 dark:bg-gray-700" />
              <ArrowRight className="w-3 h-3 text-primary absolute -right-1" />
            </div>
            <span className="text-[10px] text-gray-400">{schedule.stopsCount} stops</span>
          </div>

          {/* Destination */}
          <div className="flex-1 min-w-0 text-right">
            <p className="text-[10px] font-semibold text-gray-400 uppercase tracking-wide">To</p>
            <p className="text-xl font-extrabold text-gray-900 dark:text-white truncate">
              {schedule.destinationStation.code}
            </p>
            <p className="text-xs text-gray-500 truncate">{schedule.destinationStation.name.trim()}</p>
          </div>
        </div>

        {/* Times */}
        <div className="flex items-end justify-between mt-4 pt-4 border-t border-gray-100 dark:border-gray-800">
          <div>
            <p className="text-lg font-bold text-primary">{fmtTime(schedule.departureAt)}</p>
            <p className="text-xs text-gray-400">{fmt(schedule.departureAt, { weekday: "short", month: "short", day: "numeric" })}</p>
          </div>
          <div className="text-right">
            <p className="text-lg font-bold text-primary">
              {fmtTime(schedule.arrivalAt)}
              {!isSameDay && <sup className="text-[10px] text-orange-400 ml-0.5">+1</sup>}
            </p>
            <p className="text-xs text-gray-400">{fmt(schedule.arrivalAt, { weekday: "short", month: "short", day: "numeric" })}</p>
          </div>
        </div>
      </div>
    </div>
  );
}

// ─── Coach Type Group Panel (Step 1 + Step 2 inline) ─────────────────────────

function groupTiersByCoachType(tiers: PriceTier[]): Array<{
  coachTypeId: string;
  coachTypeName: string;
  coachTypeCode: string;
  coachTypeType: string;
  tiers: PriceTier[];
  minPrice: number;
  currency: string;
}> {
  const map = new Map<string, { coachTypeId: string; coachTypeName: string; coachTypeCode: string; coachTypeType: string; tiers: PriceTier[] }>();
  for (const tier of tiers) {
    const ct = tier.seatClass?.coachType;
    const key = ct?.id ?? `__ungrouped__${tier.seatType}`;
    if (!map.has(key)) {
      map.set(key, {
        coachTypeId: ct?.id ?? key,
        coachTypeName: ct?.name ?? tier.label ?? tier.seatType,
        coachTypeCode: ct?.code ?? '',
        coachTypeType: ct?.type ?? 'passenger',
        tiers: [],
      });
    }
    map.get(key)!.tiers.push(tier);
  }
  return Array.from(map.values()).map((g) => ({
    ...g,
    minPrice: Math.min(...g.tiers.map((t) => t.priceMinor)),
    currency: g.tiers[0]?.currency ?? 'ETB',
  }));
}

function getCoachIcon(coachTypeType: string) {
  const lower = coachTypeType.toLowerCase();
  if (lower.includes('sleeper')) return Star;
  if (lower.includes('bed') || lower.includes('sleep')) return Bed;
  return Armchair;
}

// Capitalise first letter of each word, replace underscores with spaces
function formatCoachTypeLabel(type: string): string {
  return type.replace(/_/g, ' ').replace(/\b\w/g, (c) => c.toUpperCase());
}

function PriceTiersPanel({
  tiers,
  onBookNow,
  isRoundTrip,
}: {
  tiers: PriceTier[];
  onBookNow: (coachTypeId: string) => void;
  isRoundTrip: boolean;
}) {
  const [selectedId, setSelectedId] = useState<string | null>(null);
  const priceMultiplier = isRoundTrip ? 2 : 1;
  const groups = groupTiersByCoachType(tiers ?? []);

  if (!tiers?.length) {
    return (
      <div className="bg-white dark:bg-gray-900 rounded-2xl p-5 border border-gray-100 dark:border-gray-800">
        <p className="text-sm text-gray-400 text-center py-4">No price tiers available</p>
      </div>
    );
  }

  return (
    <div className="bg-white dark:bg-gray-900 rounded-2xl p-5 border border-gray-100 dark:border-gray-800">
      <h2 className="text-base font-bold text-gray-900 dark:text-white mb-4">Choose Coach Type</h2>
      <div className="grid grid-cols-1 gap-4">
        {groups.map((group, index) => {
          const CoachIcon = getCoachIcon(group.coachTypeType);
          const allSoldOut = group.tiers.every((t) => t.availableSeats === 0);
          const isSelected = selectedId === group.coachTypeId;
          return (
            <div
              key={group.coachTypeId}
              role="button"
              tabIndex={allSoldOut ? -1 : 0}
              onClick={() => !allSoldOut && setSelectedId(isSelected ? null : group.coachTypeId)}
              onKeyDown={(e) => {
                if (!allSoldOut && (e.key === 'Enter' || e.key === ' ')) {
                  e.preventDefault();
                  setSelectedId(isSelected ? null : group.coachTypeId);
                }
              }}
              className={`group relative w-full p-2 rounded-2xl border-2 text-left transition-all duration-200 ${allSoldOut
                  ? 'border-gray-200 dark:border-gray-700 opacity-50 cursor-not-allowed'
                  : isSelected
                    ? 'border-primary bg-gradient-to-br from-primary/8 to-primary/3 dark:from-primary/15 dark:to-primary/5 shadow-lg shadow-primary/20 scale-[1.02] cursor-pointer'
                    : 'border-gray-200 dark:border-gray-700 shadow-sm hover:border-primary/40 hover:shadow-md hover:scale-[1.01] bg-white dark:bg-gray-800/50 cursor-pointer'
                }`}
              style={{ animation: `fade-in-up 0.3s ease-out ${index * 0.08}s both` }}
            >
              {/* Radio indicator */}
              {!allSoldOut && (
                <span className={`absolute top-4 right-4 w-5 h-5 rounded-full border-2 flex items-center justify-center flex-shrink-0 transition-all ${isSelected ? 'border-primary' : 'border-gray-300 dark:border-gray-600 group-hover:border-primary/50'
                  }`}>
                  {isSelected && <span className="w-2.5 h-2.5 rounded-full bg-primary" />}
                </span>
              )}

              <div className="flex flex-col">
                <div className="flex items-start gap-2 pr-2">
                  <div className={`w-10 h-10 rounded-xl flex items-center justify-center flex-shrink-0 transition-all ${isSelected
                      ? 'bg-primary/15 dark:bg-primary/25 shadow-inner'
                      : 'bg-gray-100 dark:bg-gray-700 group-hover:bg-primary/10'
                    }`}>
                    <CoachIcon className={`w-4 h-4 transition-colors ${isSelected ? 'text-primary' : 'text-gray-600 dark:text-gray-400 group-hover:text-primary'
                      }`} />
                  </div>

                  <div className="flex-1 min-w-0">
                    <p className="text-sm font-bold text-gray-700 dark:text-gray-300 tracking-wider">
                      {formatCoachTypeLabel(group.coachTypeType)}
                    </p>
                    {allSoldOut && (
                      <span className="text-xs font-bold text-red-500 mt-0.5 block">Sold out</span>
                    )}
                    <div className="mt-1 flex items-baseline gap-1">
                      <span className="text-xs text-gray-500 dark:text-gray-400 font-medium">From</span>
                      <span className={`text-sm font-bold tracking-tight ${isSelected ? 'text-primary' : 'text-gray-900 dark:text-white'
                        }`}>
                        {((group.minPrice * priceMultiplier) / 100).toFixed(2)}
                      </span>
                      <span className="text-sm font-semibold text-gray-600 dark:text-gray-400">{group.currency}</span>
                    </div>
                  </div>
                </div>

                {/* Class options — always visible, matching results page style */}
                {group.tiers.length > 0 && (
                  <div className="mt-2 pt-2 border-t border-gray-200/60 dark:border-gray-700/60">
                    <div className="space-y-1.5">
                      {group.tiers.map((tier) => {
                        const soldOut = tier.availableSeats === 0;
                        return (
                          <div
                            key={tier.id}
                            className={`flex flex-col py-1 px-1 rounded-lg bg-gray-50/80 dark:bg-gray-800/40 ${soldOut ? 'opacity-50' : ''}`}
                          >
                            <span className="text-sm font-medium text-gray-700 dark:text-gray-300">{tier.seatType.trim()}</span>
                            {soldOut ? (
                              <span className="text-xs font-bold text-red-500 mt-0.5">Sold out</span>
                            ) : (
                              <div className="flex items-baseline gap-1 mt-0.5">
                                <span className="text-sm font-bold tabular-nums text-primary">
                                  {((tier.priceMinor * priceMultiplier) / 100).toFixed(2)}
                                </span>
                                <span className="text-xs text-gray-500 dark:text-gray-400 font-medium">{tier.currency}</span>
                              </div>
                            )}
                          </div>
                        );
                      })}
                    </div>
                  </div>
                )}

                {!isSelected && !allSoldOut && (
                  <p className="mt-4 pt-3 border-t border-gray-200/60 dark:border-gray-700/60 text-xs text-gray-400 dark:text-gray-500 italic text-center">
                    Click to select this coach
                  </p>
                )}

                {isSelected && !allSoldOut && (
                  <button
                    type="button"
                    onClick={(e) => { e.stopPropagation(); onBookNow(group.coachTypeId); }}
                    className="mt-3 w-full flex items-center justify-center gap-2 px-4 py-2.5 bg-gradient-to-r from-[rgb(20,113,76)] to-[rgb(16,95,65)] hover:from-[rgb(16,89,60)] hover:to-[rgb(12,75,50)] text-white font-bold text-sm rounded-xl transition-all shadow-md shadow-primary/30 hover:shadow-lg active:scale-[0.98]"
                  >
                    Book Now <ArrowRight className="w-4 h-4" />
                  </button>
                )}
              </div>
            </div>
          );
        })}
      </div>
      <style>{`
        @keyframes fade-in-up{from{opacity:0;transform:translateY(10px)}to{opacity:1;transform:translateY(0)}}
      `}</style>
    </div>
  );
}

// ─── Passenger count picker ──────────────────────────────────────────────────

const PKG_MAX_ADULTS = 5;
const PKG_CHILDREN_PER_ADULT = 5;

function PassengerCountModal({
  tier,
  onClose,
  onConfirm,
  loading,
  error,
  priceMultiplier,
  stations,
}: {
  tier: PriceTier;
  onClose: () => void;
  onConfirm: (adultCount: number, childCount: number, departureStationId: string, departureStationName: string) => void;
  loading: boolean;
  error: string | null;
  priceMultiplier: number;
  stations: Station[];
}) {
  const [adultCount, setAdultCount] = useState(1);
  const [childCount, setChildCount] = useState(0);
  const [departureStationId, setDepartureStationId] = useState('');
  const [showStationError, setShowStationError] = useState(false);
  const remaining = tier.availableSeats - tier.bookedSeats;
  const freeChildren = Math.min(childCount, adultCount);
  const paidChildren = Math.max(0, childCount - adultCount);
  const totalMinor = (adultCount * tier.priceMinor + paidChildren * tier.priceMinor) * priceMultiplier;

  return (
    <>
      <div className="fixed inset-0 z-[90] bg-black/50 backdrop-blur-sm" onClick={onClose} />
      <div className="fixed inset-0 z-[100] flex items-end sm:items-center justify-center p-0 sm:p-4">
        <div className="w-full sm:max-w-sm bg-white dark:bg-gray-900 rounded-t-3xl sm:rounded-2xl shadow-2xl overflow-hidden">
          <div className="flex items-center justify-between px-6 py-4 border-b border-gray-100 dark:border-gray-800">
            <h2 className="text-base font-bold text-gray-900 dark:text-white">Number of passengers & boarding station selection</h2>
            <button type="button" onClick={onClose} className="w-8 h-8 flex items-center justify-center rounded-full hover:bg-gray-100 dark:hover:bg-gray-800">
              <X className="w-4 h-4 text-gray-500" />
            </button>
          </div>

          <div className="px-6 py-3 bg-primary/5 border-b border-primary/10">
            <p className="text-xs text-gray-400 uppercase tracking-wide font-semibold">Coach type</p>
            <p className="text-sm font-bold text-gray-900 dark:text-white mt-0.5">{tier.seatClass?.coachType?.name ?? tier.label.trim()}</p>
            <p className="text-xs text-gray-400 mt-0.5">{remaining} seats remaining · from {formatPrice(tier.priceMinor * priceMultiplier, tier.currency)} per adult · 1st child per adult free (no seat)</p>
          </div>

          <div className="px-6 py-5 space-y-4">
            {[
              { label: "Adults", sub: `Age 5+ · max ${PKG_MAX_ADULTS}`, value: adultCount, min: 1, max: Math.min(PKG_MAX_ADULTS, remaining), set: (v: number) => { setAdultCount(v); const newMax = Math.min(v * PKG_CHILDREN_PER_ADULT, v + Math.max(0, remaining - v)); setChildCount(c => Math.min(c, newMax)); } },
              { label: "Children", sub: `Under 5 · max ${PKG_CHILDREN_PER_ADULT} per adult · 1st per adult FREE (no seat)`, value: childCount, min: 0, max: Math.min(adultCount * PKG_CHILDREN_PER_ADULT, adultCount + Math.max(0, remaining - adultCount)), set: setChildCount },
            ].map(({ label, sub, value, min, max, set }) => (
              <div key={label} className="flex items-center justify-between">
                <div>
                  <p className="text-sm font-semibold text-gray-900 dark:text-white">{label}</p>
                  <p className="text-xs text-gray-400">{sub}</p>
                </div>
                <div className="flex items-center gap-3">
                  <button type="button" onClick={() => set(Math.max(min, value - 1))}
                    disabled={value <= min}
                    className="w-8 h-8 rounded-full border-2 border-gray-200 dark:border-gray-700 flex items-center justify-center text-lg font-bold text-gray-600 dark:text-gray-300 disabled:opacity-30 hover:border-primary hover:text-primary transition-colors">
                    −
                  </button>
                  <span className="w-6 text-center text-base font-bold text-gray-900 dark:text-white">{value}</span>
                  <button type="button" onClick={() => set(value + 1)}
                    disabled={value >= max}
                    className="w-8 h-8 rounded-full border-2 border-gray-200 dark:border-gray-700 flex items-center justify-center text-lg font-bold text-gray-600 dark:text-gray-300 disabled:opacity-30 hover:border-primary hover:text-primary transition-colors">
                    +
                  </button>
                </div>
              </div>
            ))}

            {freeChildren > 0 && (
              <div className="flex items-center justify-between text-xs text-green-600 dark:text-green-400">
                <span>{freeChildren} child{freeChildren > 1 ? 'ren' : ''} travel free (no seat)</span>
                <span>ETB 0.00</span>
              </div>
            )}
            <div className="flex items-center justify-between pt-2 border-t border-gray-100 dark:border-gray-800">
              <span className="text-sm text-gray-500">Total{priceMultiplier === 2 ? ' (round-trip) from:' : ''}</span>
              <span className="text-base font-extrabold text-primary">{formatPrice(totalMinor, tier.currency)}</span>
            </div>

            {error && (
              <div className="flex items-start gap-2 p-3 bg-red-50 dark:bg-red-900/20 border border-red-200 dark:border-red-800 rounded-xl">
                <AlertCircle className="w-4 h-4 text-red-500 flex-shrink-0 mt-0.5" />
                <p className="text-xs text-red-600 dark:text-red-400">{error}</p>
              </div>
            )}

            {/* Departure Station */}
            <div>
              <label className="flex items-center gap-1.5 text-sm font-semibold text-gray-700 dark:text-gray-300 mb-1.5 border-t pt-3">
                Departure Station
              </label>
              <select
                value={departureStationId}
                onChange={(e) => { setDepartureStationId(e.target.value); setShowStationError(false); }}
                className={`w-full rounded-xl border bg-white dark:bg-gray-800 text-sm text-gray-900 dark:text-white px-3 py-2.5 focus:outline-none focus:ring-2 focus:ring-primary/40 ${showStationError && !departureStationId ? 'border-red-400 dark:border-red-500' : 'border-gray-200 dark:border-gray-700'
                  }`}
              >
                <option value="">Select your boarding station</option>
                {stations.map((s) => (
                  <option key={s.id} value={s.id}>{s.name.trim()} ({s.code})</option>
                ))}
              </select>
              <p className="text-[10px] text-gray-400 mt-1">For informational purposes — pricing remains fixed regardless of boarding point.</p>
            </div>

            {showStationError && !departureStationId && (
              <p className="text-xs text-red-500 -mt-2">Please select your boarding station to continue.</p>
            )}

            <button type="button" onClick={() => {
              if (!departureStationId) { setShowStationError(true); return; }
              const station = stations.find(s => s.id === departureStationId);
              onConfirm(adultCount, childCount, departureStationId, station?.name ?? '');
            }}
              disabled={loading || adultCount + childCount < 1}
              className="w-full py-3.5 bg-[rgb(20,113,76)] hover:bg-[rgb(16,89,60)] disabled:opacity-60 text-white font-bold text-sm rounded-xl transition-all shadow-lg flex items-center justify-center gap-2">
              {loading ? <><Loader2 className="w-4 h-4 animate-spin" /> Loading...</> : <>Continue <ArrowRight className="w-4 h-4" /></>}
            </button>
          </div>
        </div>
      </div>
    </>
  );
}

// ─── Main Page ────────────────────────────────────────────────────────────────

export default function PackageDetailPage() {
  const params = useParams();
  const router = useRouter();
  const id = params?.id as string;
  const { clearBooking, setSearchCriteria, setSelectedSchedule, setOutboundSchedule, setInboundSchedule, setPassengers, setPackageContext } = useBookingStore();

  const [selectedCoachTypeId, setSelectedCoachTypeId] = useState<string | null>(null);
  const [passengerModalOpen, setPassengerModalOpen] = useState(false);
  const [bookingContextLoading, setBookingContextLoading] = useState(false);
  const [bookingContextError, setBookingContextError] = useState<string | null>(null);

  const { data: pkg, isLoading, isError } = useQuery<PackageDetail>({
    queryKey: ["package", id],
    queryFn: async () =>
      (await apiClient.get<PackageDetail>(`/packages/${id}`)) as PackageDetail,
    enabled: !!id,
  });

  // Build departure station list from live route stops (always reflects current route definition)
  const routeStopStations: Station[] = pkg?.outboundSchedule?.routeStops?.length
    ? pkg.outboundSchedule.routeStops.map((rs) => rs.station).filter(Boolean)
    : [];

  // For the passenger modal, use the cheapest available tier in the selected coach type group
  const groups = pkg ? groupTiersByCoachType(pkg.priceTiers) : [];
  const selectedGroup = groups.find((g) => g.coachTypeId === selectedCoachTypeId);
  // Representative tier for the modal: cheapest available in the selected group
  const representativeTier = selectedGroup?.tiers
    .filter((t) => t.availableSeats > 0)
    .sort((a, b) => a.priceMinor - b.priceMinor)[0] ?? selectedGroup?.tiers[0] ?? null;

  const isRoundTripPkg = pkg?.journeyType === 'ROUND_TRIP';

  const handleBookNow = async (adultCount: number, childCount: number, departureStationId: string, departureStationName: string) => {
    if (!representativeTier || !pkg) return;
    setBookingContextLoading(true);
    setBookingContextError(null);
    try {
      const ctx: any = await apiClient.get(
        `/packages/${id}/booking-context?tierId=${representativeTier.id}&adultCount=${adultCount}&childCount=${childCount}`,
      );

      clearBooking();

      const passengerCount = adultCount + childCount;
      const isRoundTrip = !!ctx.returnSchedule;

      const toSchedule = (s: any) => ({
        id: s.scheduleId,
        trainNumber: s.trainNumber ?? "",
        origin: s.originStation?.name ?? "",
        destination: s.destinationStation?.name ?? "",
        originStationId: s.originStationId ?? s.originStation?.id ?? "",
        destinationStationId: s.destinationStationId ?? s.destinationStation?.id ?? "",
        departureTime: s.departureAt,
        arrivalTime: s.arrivalAt,
        duration: s.durationMinutes ? `${Math.floor(s.durationMinutes / 60)}h ${s.durationMinutes % 60}m` : "",
        baseFareAdult: Math.round(ctx.totalMinor / passengerCount),
        baseFareChild: 0,
        displayCurrency: representativeTier.currency,
        selectedSeatClass: ctx.seatClassId,
        selectedSeatClassName: ctx.seatClassName ?? "",
        seatClassName: ctx.seatClassName ?? "",
        selectedCoachTypeId: ctx.coachTypeId ?? "",
        selectedCoachTypeCode: ctx.coachTypeCode ?? "",
        selectedCoachTypeName: ctx.coachTypeName ?? "",
        coachTypes: Array.isArray(ctx.coachTypes) ? ctx.coachTypes : groups.map((g) => ({
          coachId: g.coachTypeId,
          coachTypeId: g.coachTypeId,
          coachTypeName: g.coachTypeName,
          coachTypeCode: g.coachTypeCode,
          classes: g.tiers.map((t) => ({ name: t.label, baseFareMinor: t.priceMinor })),
        })),
      });

      // booking-context returns flat originStationId/destinationStationId, not nested objects.
      // Use the user's selected departure station as the true origin for both the
      // search criteria and the schedule objects so hold/booking APIs get the right segment.
      const outboundDestId = ctx.outboundSchedule.destinationStationId ?? ctx.outboundSchedule.destinationStation?.id ?? "";

      const outboundSched = {
        ...toSchedule(ctx.outboundSchedule),
        originStationId: departureStationId,
        origin: departureStationName,
      };

      setSearchCriteria({
        originStationId: departureStationId,
        destinationStationId: outboundDestId,
        departureDate: ctx.outboundSchedule.departureAt?.slice(0, 10) ?? "",
        returnDate: ctx.returnSchedule?.departureAt?.slice(0, 10),
        tripType: isRoundTrip ? "ROUND_TRIP" : "ONE_WAY",
        adultCount,
        childCount,
        nationality: "ETHIOPIAN",
      });

      if (isRoundTrip) {
        setOutboundSchedule(outboundSched);
        setInboundSchedule({
          ...toSchedule(ctx.returnSchedule),
          destinationStationId: departureStationId,
          destination: departureStationName,
        });
      } else {
        setSelectedSchedule(outboundSched);
      }

      setPassengers(
        Array.from({ length: passengerCount }, (_, i) => {
          // First `adultCount` entries are adults; remaining are children.
          // Among children, the first `adultCount` are free (one per adult, no seat).
          const isChildPassenger = i >= adultCount;
          const childIndex = i - adultCount; // 0-based index among children
          const isFreeChild = isChildPassenger && childIndex < adultCount;
          return {
            name: "",
            // Free children travel without a seat — give them a synthetic DOB that
            // makes isChild() return true so seat eligibility logic excludes them.
            dateOfBirth: isFreeChild ? new Date(Date.now() - 2 * 365.25 * 24 * 60 * 60 * 1000).toISOString().slice(0, 10) : "",
            nationality: "ETHIOPIAN",
            isPrimaryPassenger: i === 0,
          };
        }),
      );

      // Store per-adult tier price (×1 leg); review page applies round-trip multiplier and child pricing
      // Store the group's cheapest tier price as a placeholder — the actual berth fare
      // (Upper/Middle/Lower) will be resolved and saved when the user picks a seat.
      setPackageContext(id, representativeTier.id, representativeTier.priceMinor, pkg.name, departureStationId, departureStationName);

      router.push("/booking/passengers");
    } catch (err: any) {
      setBookingContextError(
        err?.response?.data?.message ?? "Failed to load booking context. Please try again.",
      );
    } finally {
      setBookingContextLoading(false);
    }
  };

  if (isLoading) {
    return (
      <div className="min-h-screen flex items-center justify-center bg-gray-50 dark:bg-gray-950">
        <div className="text-center">
          <Loader2 className="w-8 h-8 animate-spin text-primary mx-auto mb-3" />
          <p className="text-sm text-gray-500">Loading package details...</p>
        </div>
      </div>
    );
  }

  if (isError || !pkg) {
    return (
      <div className="min-h-screen flex items-center justify-center bg-gray-50 dark:bg-gray-950">
        <div className="text-center">
          <AlertCircle className="w-8 h-8 text-red-400 mx-auto mb-3" />
          <p className="text-sm text-gray-500 mb-4">Unable to load package details.</p>
          <button
            onClick={() => router.back()}
            className="text-sm text-primary font-medium flex items-center gap-1 mx-auto hover:underline"
          >
            <ChevronLeft className="w-4 h-4" /> Go back
          </button>
        </div>
      </div>
    );
  }

  const origin = pkg.outboundSchedule?.originStation;
  const destination = pkg.outboundSchedule?.destinationStation;
  return (
    <div className="min-h-screen bg-gray-50 dark:bg-gray-950">
      {/* Passenger count modal */}
      {passengerModalOpen && representativeTier && (
        <PassengerCountModal
          tier={representativeTier}
          onClose={() => { setPassengerModalOpen(false); setBookingContextError(null); }}
          onConfirm={handleBookNow}
          loading={bookingContextLoading}
          error={bookingContextError}
          priceMultiplier={isRoundTripPkg ? 2 : 1}
          stations={routeStopStations}
        />
      )}

      {/* Hero */}
      <div className="relative h-56 md:h-80 bg-gradient-to-br from-[rgb(14,80,54)] to-[rgb(20,140,90)] overflow-hidden">
        <Image
          src="/packages/kulubi.jpeg"
          alt={pkg.name}
          fill
          className="object-cover"
          sizes="100vw"
          priority
        />
        <div className="absolute inset-0 bg-gradient-to-t from-black/75 via-black/20 to-transparent" />

        <button
          onClick={() => router.back()}
          className="absolute top-4 left-4 flex items-center gap-1.5 text-white/90 hover:text-white bg-black/25 backdrop-blur-sm px-3 py-2 rounded-full text-sm font-medium transition-colors"
        >
          <ChevronLeft className="w-4 h-4" /> Back
        </button>

        <div className="absolute bottom-0 left-0 right-0 p-6">
          <div className="max-w-4xl mx-auto">
            <div className="flex items-center gap-2 mb-2">
              <span className="inline-block bg-white/20 text-white text-xs font-semibold px-2.5 py-1 rounded-full backdrop-blur-sm">
                {pkg.code}
              </span>
              {pkg.status === "ACTIVE" && (
                <span className="inline-block bg-green-500/90 text-white text-xs font-bold px-2.5 py-1 rounded-full">
                  Active
                </span>
              )}
            </div>
            <h1 className="text-2xl md:text-3xl font-extrabold text-white leading-tight">
              {pkg.name.trim()}
            </h1>
            {origin && destination && (
              <div className="flex items-center gap-1.5 text-white/75 text-sm mt-2">
                <MapPin className="w-4 h-4 flex-shrink-0" />
                {origin.name.trim()}
                <ArrowRight className="w-3.5 h-3.5" />
                {destination.name.trim()}
                {pkg.returnSchedule && (
                  <span className="text-white/50 text-xs ml-1">· Round Trip</span>
                )}
              </div>
            )}
          </div>
        </div>
      </div>

      <div className="max-w-4xl mx-auto px-4 py-8">
        <div className="grid grid-cols-1 lg:grid-cols-3 gap-6">
          {/* ── Main content ── */}
          <div className="lg:col-span-2 space-y-5">

            {/* Description */}
            {pkg.description && (
              <div className="bg-white dark:bg-gray-900 rounded-2xl p-6 border border-gray-100 dark:border-gray-800">
                <h2 className="text-base font-bold text-gray-900 dark:text-white mb-3">
                  About this Package
                </h2>
                <p className="text-sm text-gray-600 dark:text-gray-400 leading-relaxed">
                  {pkg.description}
                </p>
              </div>
            )}

            {/* Outbound journey */}
            {pkg.outboundSchedule && (
              <JourneyCard schedule={pkg.outboundSchedule} label="Outbound Journey" />
            )}

            {/* Return journey */}
            {pkg.returnSchedule && (
              <JourneyCard schedule={pkg.returnSchedule} label="Return Journey" />
            )}

            {/* Bus transfer */}
            {pkg.busTransferIncluded && (
              <div className="bg-white dark:bg-gray-900 rounded-2xl p-5 border border-gray-100 dark:border-gray-800">
                <div className="flex items-center gap-3">
                  <div className="w-10 h-10 bg-amber-50 dark:bg-amber-900/20 rounded-xl flex items-center justify-center flex-shrink-0">
                    <Bus className="w-5 h-5 text-amber-600 dark:text-amber-400" />
                  </div>
                  <div>
                    <p className="text-sm font-bold text-gray-900 dark:text-white">
                      Bus Transfer Included
                    </p>
                    {pkg.busTransferRoute && (
                      <p className="text-xs text-gray-500 mt-0.5">
                        {pkg.busTransferRoute.trim()}
                      </p>
                    )}
                  </div>
                  <Check className="w-5 h-5 text-green-500 ml-auto flex-shrink-0" />
                </div>
              </div>
            )}

            {/* Travel info */}
            <div className="bg-white dark:bg-gray-900 rounded-2xl p-6 border border-gray-100 dark:border-gray-800">
              <h2 className="text-base font-bold text-gray-900 dark:text-white mb-4">
                Travel Information
              </h2>
              <div className="grid grid-cols-1 sm:grid-cols-2 gap-4">
                <InfoRow icon={<Clock className="w-4 h-4 text-primary" />} label="Boarding Time">
                  {fmtTime(pkg.boardingTime)} · {fmt(pkg.boardingTime)}
                </InfoRow>
                <InfoRow icon={<Calendar className="w-4 h-4 text-primary" />} label="Departure Time">
                  {fmtTime(pkg.departureTime)} · {fmt(pkg.departureTime)}
                </InfoRow>
                <InfoRow icon={<MapPin className="w-4 h-4 text-primary" />} label="Arrival">
                  {fmtTime(pkg.arrivalTime)} · {fmt(pkg.arrivalTime)}
                </InfoRow>
                {pkg.coachConfiguration && (
                  <InfoRow icon={<Train className="w-4 h-4 text-primary" />} label="Coach Config">
                    {pkg.coachConfiguration.trim()}
                  </InfoRow>
                )}
                <InfoRow icon={<Shield className="w-4 h-4 text-primary" />} label="Valid Period">
                  {fmt(pkg.validFrom, { month: "short", day: "numeric" })} –{" "}
                  {fmt(pkg.validUntil, { month: "short", day: "numeric", year: "numeric" })}
                </InfoRow>
              </div>
            </div>

            {/* Included services */}
            {pkg.includedServices?.length > 0 && (
              <div className="bg-white dark:bg-gray-900 rounded-2xl p-6 border border-gray-100 dark:border-gray-800">
                <h2 className="text-base font-bold text-gray-900 dark:text-white mb-4">
                  Included Services
                </h2>
                <ul className="space-y-2.5">
                  {pkg.includedServices.map((svc, i) => (
                    <li
                      key={i}
                      className="flex items-start gap-2.5 text-sm text-gray-600 dark:text-gray-400"
                    >
                      <Check className="w-4 h-4 text-green-500 flex-shrink-0 mt-0.5" />
                      {stripBullet(svc)}
                    </li>
                  ))}
                </ul>
              </div>
            )}

            {/* Price tiers — mobile */}
            <div className="lg:hidden">
              <PriceTiersPanel
                tiers={pkg.priceTiers}
                onBookNow={(coachTypeId) => { setSelectedCoachTypeId(coachTypeId); setPassengerModalOpen(true); }}
                isRoundTrip={isRoundTripPkg}
              />
            </div>
          </div>

          {/* ── Sidebar — desktop ── */}
          <div className="hidden lg:block">
            <div>
              <PriceTiersPanel
                tiers={pkg.priceTiers}
                onBookNow={(coachTypeId) => { setSelectedCoachTypeId(coachTypeId); setPassengerModalOpen(true); }}
                isRoundTrip={isRoundTripPkg}
              />
            </div>
          </div>
        </div>
      </div>
    </div>
  );
}

function InfoRow({
  icon,
  label,
  children,
}: {
  icon: React.ReactNode;
  label: string;
  children: React.ReactNode;
}) {
  return (
    <div className="flex items-start gap-3">
      <div className="flex-shrink-0 mt-0.5">{icon}</div>
      <div>
        <p className="text-[10px] text-gray-400 uppercase tracking-wide font-semibold">
          {label}
        </p>
        <p className="text-sm font-medium text-gray-700 dark:text-gray-300 mt-0.5">
          {children}
        </p>
      </div>
    </div>
  );
}
