/**
 * ═══════════════════════════════════════════════════════════════════
 * Explore Detail Page Component (State-driven)
 * ═══════════════════════════════════════════════════════════════════
 *
 * Shows destination details (full-page explore-detail view).
 * Embeddable TV panel: `window.ExploreDestinationDetailEmbedded` and `window.ExploreActivityDetailEmbedded`
 * for ExplorePage TV viewport (chrome/back handled by ExplorePage).
 * TV primary CTA uses purple hotbar styling and mirrors Explore trip-timeline hotkey behavior when wired from ExplorePage.
 * Navigation is state-driven — NO URL routing for identity.
 */

(function () {
  'use strict';

  const { useState, useEffect } = React;
  const SF_API_BASE = window.SF_API_BASE;

  /** Issue #126.1b — mirror NuAsk / ExplorePage hard-commitment detection. */
  function exploreActivityLooksHardCommitted(activity) {
    if (!activity || typeof activity !== 'object') return false;
    if (activity.hard_booking === true) return true;
    if (activity.locked === true || activity.is_fixed === true) return true;
    const ref = activity.booking_ref;
    return ref != null && String(ref).trim().length > 0;
  }

  /**
   * @param {string} destinationId
   * @returns {Promise<object>}
   */
  async function fetchDestinationRecord(destinationId) {
    if (!destinationId) {
      throw new Error('Destination ID not found');
    }
    const url = `${SF_API_BASE}/api/destinations/${encodeURIComponent(destinationId)}`;
    const res = await window.SylvanFlowAuth.authenticatedFetch(url);
    if (!res.ok) {
      throw new Error(`Failed to load destination: ${res.status}`);
    }
    const data = await res.json();
    if (data.ok && data.destination) {
      return data.destination;
    }
    throw new Error(data.error || 'Destination not found');
  }

  function formatDescriptionParagraphs(text, paragraphClass) {
    const cls = paragraphClass || 'mb-4 last:mb-0';
    if (!text) return null;
    return text.split(/\n\n+/).map((para, i) => (
      <p key={i} className={cls}>
        {para}
      </p>
    ));
  }

  /**
   * @param {object} props
   * @param {'page'|'tv'} props.variant
   */
  function ExploreDestinationDetailView({
    variant,
    destination,
    loading,
    error,
    onBack,
    labels
  }) {
    const isTv = variant === 'tv';
    const L = labels || {};

    const heroPage = (
      <div
        className="relative w-full"
        style={isTv ? undefined : { height: '40vh', minHeight: '300px', maxHeight: '500px' }}
      >
        <div
          className={
            isTv
              ? 'relative max-h-[min(24svh,180px)] min-h-[100px] w-full overflow-hidden bg-slate-900'
              : 'relative h-full w-full'
          }
        >
          {destination?.PhotosOfDestinations ? (
            <img
              src={destination.PhotosOfDestinations}
              alt={destination.Name || 'Destination'}
              className={
                isTv
                  ? 'max-h-[min(24svh,180px)] w-full object-cover'
                  : 'h-full w-full object-cover'
              }
              onError={(e) => {
                e.target.style.display = 'none';
                const sib = e.target.nextElementSibling;
                if (sib) sib.style.display = 'flex';
              }}
            />
          ) : null}
          <div
            className={
              isTv
                ? 'flex max-h-[min(24svh,180px)] min-h-[100px] w-full items-center justify-center bg-gradient-to-br from-teal-900/90 to-slate-900'
                : 'flex h-full w-full items-center justify-center bg-gradient-to-br from-teal-400 to-teal-600'
            }
            style={{ display: destination?.PhotosOfDestinations ? 'none' : 'flex' }}
          >
            <span className={`text-white opacity-50 ${isTv ? 'text-4xl' : 'text-6xl'}`}>📷</span>
          </div>
        </div>

        {!isTv ? (
          <button
            type="button"
            onClick={onBack}
            className="absolute left-4 top-4 flex h-10 w-10 items-center justify-center rounded-full bg-white bg-opacity-90 shadow-md transition-all hover:bg-opacity-100"
            aria-label={L.goBack || 'Go back'}
          >
            <svg
              xmlns="http://www.w3.org/2000/svg"
              width="20"
              height="20"
              viewBox="0 0 24 24"
              fill="none"
              stroke="currentColor"
              strokeWidth="2"
              strokeLinecap="round"
              strokeLinejoin="round"
              className="text-slate-800"
            >
              <polyline points="15 18 9 12 15 6" />
            </svg>
          </button>
        ) : null}
      </div>
    );

    const bodyPage = (
      <>
        {loading ? (
          <p className={`text-center text-sm ${isTv ? 'py-10 text-slate-500' : 'py-8 text-slate-500'}`}>
            {L.loading || 'Loading destination...'}
          </p>
        ) : null}

        {!loading && error ? (
          <div className={`text-center ${isTv ? 'py-10' : 'py-8'}`}>
            <p className={`mb-4 text-sm ${isTv ? 'text-rose-300' : 'text-red-500'}`}>{error}</p>
            <button
              type="button"
              onClick={onBack}
              className={
                isTv
                  ? 'min-h-[44px] rounded-lg bg-gradient-to-r from-teal-400 to-cyan-400 px-4 py-2 font-semibold text-black active:brightness-95'
                  : 'rounded-lg bg-teal-600 px-4 py-2 text-white hover:bg-teal-700'
              }
            >
              {L.goBack || 'Go Back'}
            </button>
          </div>
        ) : null}

        {!loading && !error && destination ? (
          <>
            <h1
              className={
                isTv
                  ? 'mb-1 text-xl font-bold text-white'
                  : 'mb-2 text-2xl font-extrabold text-slate-900 sm:text-3xl'
              }
            >
              {destination.Name || 'Destination'}
            </h1>
            <p className={isTv ? 'mb-3 text-sm text-slate-400' : 'mb-4 text-base text-slate-600 sm:mb-6 sm:text-lg'}>
              {L.aiVoice || "In Sylvan AI's Words"}
            </p>
            <div
              className={
                isTv
                  ? 'mb-4 text-sm leading-relaxed text-slate-300'
                  : 'mb-6 text-base leading-relaxed text-slate-700 sm:text-sm'
              }
            >
              {destination.BriefDescription ? (
                formatDescriptionParagraphs(
                  destination.BriefDescription,
                  isTv ? 'mb-3 last:mb-0 text-slate-300' : 'mb-4 last:mb-0'
                )
              ) : (
                <p className={isTv ? 'text-slate-500' : ''}>{L.noDescription || 'No description available.'}</p>
              )}
            </div>
            {(destination.Trip_Key || destination.Flow_Plan_ID) && L.onViewFlowPlan ? (
              isTv ? (
                <div className="relative w-full">
                  <div
                    className="pointer-events-none absolute -inset-0.5 rounded-[14px] opacity-40 blur-md"
                    style={{ background: 'rgba(168,85,247,0.55)' }}
                    aria-hidden
                  />
                  <button
                    type="button"
                    onClick={L.onViewFlowPlan}
                    className="relative flex w-full min-h-[52px] items-center gap-3 rounded-xl border border-[rgba(192,132,252,0.35)] bg-[#12151c] px-3 py-2.5 text-left shadow-[0_0_22px_-8px_rgba(168,85,247,0.65)] active:opacity-90"
                    style={{
                      boxShadow:
                        '0 0 14px rgba(168,85,247,0.45), inset 0 1px 0 rgba(255,255,255,0.04)'
                    }}
                  >
                    <div className="relative flex h-11 w-11 shrink-0 items-center justify-center">
                      <div
                        className="absolute h-9 w-9 rounded-full opacity-50 blur-md"
                        style={{ background: 'rgba(168,85,247,0.55)' }}
                        aria-hidden
                      />
                      <div
                        className="relative flex h-10 w-10 items-center justify-center rounded-full border bg-[#0a0c10]"
                        style={{
                          borderColor: 'rgba(192,132,252,0.35)',
                          boxShadow: '0 0 8px rgba(168,85,247,0.55)'
                        }}
                      >
                        <svg
                          className="h-[17px] w-[17px] shrink-0 text-violet-300/95"
                          viewBox="0 0 24 24"
                          fill="none"
                          stroke="currentColor"
                          strokeWidth={2}
                          aria-hidden
                        >
                          <path
                            strokeLinecap="round"
                            strokeLinejoin="round"
                            d="M12 6v6l4 2m6-2a10 10 0 11-20 0 10 10 0 0120 0z"
                          />
                        </svg>
                      </div>
                    </div>
                    <div className="min-w-0 flex-1">
                      <span className="block text-[13px] font-bold leading-tight text-white">
                        {L.viewFlowPlan || 'Trip timeline'}
                      </span>
                      {L.viewFlowPlanSub ? (
                        <span className="mt-0.5 block text-[10px] leading-snug text-[#9CA3AF]">
                          {L.viewFlowPlanSub}
                        </span>
                      ) : null}
                    </div>
                  </button>
                </div>
              ) : (
                <button
                  type="button"
                  onClick={L.onViewFlowPlan}
                  className="min-h-[44px] w-full rounded-md bg-teal-600 py-3 text-base font-medium text-white hover:bg-teal-700"
                >
                  {L.viewFlowPlan || 'View Detailed Flow Plan'}
                </button>
              )
            ) : null}
          </>
        ) : null}
      </>
    );

    if (isTv) {
      return (
        <div className="flex min-h-0 max-h-full min-w-0 flex-1 flex-col overflow-hidden bg-[#070a0c]">
          {heroPage}
          <div className="min-h-0 flex-1 overflow-y-auto overscroll-y-contain px-3 pb-6 pt-3">{bodyPage}</div>
        </div>
      );
    }

    return (
      <div className="min-h-screen bg-white">
        {heroPage}
        <div className="px-4 py-6 sm:px-6">{bodyPage}</div>
      </div>
    );
  }

  function ExploreDetailPage() {
    const [destination, setDestination] = useState(null);
    const [loading, setLoading] = useState(true);
    const [error, setError] = useState(null);

    const state = window.appState?.get() || {};
    const destinationParams = state.destinationParams || {};

    useEffect(() => {
      if (destinationParams.id) {
        loadDestination();
      } else {
        setError('Destination ID not found');
        setLoading(false);
      }
    }, [destinationParams.id]);

    const loadDestination = async () => {
      try {
        setLoading(true);
        setError(null);
        const destinationId = destinationParams.id;
        const dest = await fetchDestinationRecord(destinationId);
        setDestination(dest);
      } catch (e) {
        if (window.uiLogger) {
          window.uiLogger.uiError('Destination load error:', e.message || e);
        }
        setError(e.message || 'Unable to load destination');
      } finally {
        setLoading(false);
      }
    };

    const handleViewFlowPlan = () => {
      if (!destination) return;
      const tripKey = destination.Trip_Key || destination.Flow_Plan_ID || destination.trip_key || '';
      if (!tripKey) {
        if (window.uiLogger) {
          window.uiLogger.uiWarn('[EXPLORE-DETAIL] No Trip_Key found, navigating to flow-plan without selection');
        }
        window.appState.set({
          view: 'explore',
          destinationParams: null
        });
        return;
      }
      const normalizedTripKey = window.NormalizeTripKey?.normalizeTripKey(tripKey) || tripKey;
      window.appState.set({
        view: 'explore',
        flowPlan: { trip_key: normalizedTripKey },
        destinationParams: null
      });
    };

    const goBack = () => {
      window.appState.set({
        view: 'explore',
        destinationParams: null
      });
    };

    return (
      <ExploreDestinationDetailView
        variant="page"
        destination={destination}
        loading={loading}
        error={error}
        onBack={goBack}
        labels={{
          loading: 'Loading destination...',
          noDescription: 'No description available.',
          aiVoice: "In Sylvan AI's Words",
          viewFlowPlan: 'View Detailed Flow Plan',
          goBack: 'Go Back',
          onViewFlowPlan: handleViewFlowPlan
        }}
      />
    );
  }

  /**
   * TV viewport embed: loads destination by id; chrome/back handled by ExplorePage.
   * @param {{ destinationId: string, onBack: function, onViewFlowPlan: function, labels?: object }} props
   */
  function ExploreDestinationDetailEmbedded({ destinationId, onBack, onViewFlowPlan, labels }) {
    const [destination, setDestination] = useState(null);
    const [loading, setLoading] = useState(true);
    const [error, setError] = useState(null);
    const L = labels || {};

    useEffect(() => {
      let cancelled = false;
      if (!destinationId) {
        setDestination(null);
        setError('Destination ID not found');
        setLoading(false);
        return undefined;
      }
      (async () => {
        try {
          setLoading(true);
          setError(null);
          const dest = await fetchDestinationRecord(destinationId);
          if (!cancelled) setDestination(dest);
        } catch (e) {
          if (window.uiLogger) {
            window.uiLogger.uiError('[EXPLORE-DETAIL-TV] load error:', e.message || e);
          }
          if (!cancelled) setError(e.message || 'Unable to load destination');
        } finally {
          if (!cancelled) setLoading(false);
        }
      })();
      return () => {
        cancelled = true;
      };
    }, [destinationId]);

    const handleViewFlowPlanClick = () => {
      if (!destination) return;
      onViewFlowPlan(destination);
    };

    return (
      <ExploreDestinationDetailView
        variant="tv"
        destination={destination}
        loading={loading}
        error={error}
        onBack={onBack}
        labels={{
          ...L,
          onViewFlowPlan: destination && (destination.Trip_Key || destination.Flow_Plan_ID) ? handleViewFlowPlanClick : undefined
        }}
      />
    );
  }

  function exploreActivityLocaleTag() {
    const lang = window.SylvanFlowState?.getLanguage?.() || 'en';
    const map = {
      en: 'en-US',
      'zh-CN': 'zh-CN',
      ja: 'ja-JP',
      ko: 'ko-KR',
      th: 'th-TH',
      vi: 'vi-VN',
      id: 'id-ID',
      ms: 'ms-MY',
      ar: 'ar',
      fil: 'fil-PH'
    };
    return map[lang] || 'en-US';
  }

  function exploreActivityFormatTime(timeStr) {
    try {
      if (!timeStr) return '';
      if (!String(timeStr).includes(':')) return timeStr;
      const [hours, minutes] = String(timeStr).split(':');
      const hour = parseInt(hours, 10);
      const min = parseInt(minutes || '0', 10);
      if (Number.isNaN(hour)) return timeStr;
      const d = new Date(2000, 0, 1, hour, Number.isNaN(min) ? 0 : min);
      return d.toLocaleTimeString(exploreActivityLocaleTag(), { hour: 'numeric', minute: '2-digit' });
    } catch {
      return timeStr || '';
    }
  }

  function exploreActivityFormatDate(dateStr) {
    try {
      const date = new Date(dateStr);
      return date.toLocaleDateString(exploreActivityLocaleTag(), {
        year: 'numeric',
        month: 'long',
        day: 'numeric'
      });
    } catch {
      return dateStr || '';
    }
  }

  function exploreActivityDayNumber(dateStr, itemsByDay) {
    try {
      if (!itemsByDay) return null;
      const sortedDates = Object.keys(itemsByDay).sort((a, b) => a.localeCompare(b));
      const dayIndex = sortedDates.indexOf(dateStr);
      return dayIndex >= 0 ? dayIndex + 1 : null;
    } catch {
      return null;
    }
  }

  /**
   * Single activity inside Explore TV (dark NuAsk-tech styling). Chrome/back from ExplorePage.
   */
  function ExploreActivityDetailView({ activity, itinerary, dayKey, loading, error, labels }) {
    const L = labels || {};

    const getActivityImage = (act) =>
      act?.image_url || act?.Image_URL || act?.photo_url || act?.Photo_URL || null;

    const getActivityLocation = (act) => {
      if (typeof act?.location === 'object' && act.location !== null) {
        return act.location.address || act.location.name || act.location.Location || '';
      }
      return act?.location || act?.Location || '';
    };

    const getActivityType = (act) =>
      act?.type || act?.Type || act?.category || act?.Category || '';

    if (loading && !activity) {
      return (
        <div className="flex min-h-0 flex-1 flex-col items-center justify-center px-4 py-12">
          <p className="font-mono text-[10px] uppercase tracking-[0.28em] text-cyan-300/65">
            {L.loading || 'Loading…'}
          </p>
        </div>
      );
    }

    if (error && !activity) {
      return (
        <div className="flex min-h-0 flex-1 flex-col items-center justify-center px-4 py-10 text-center">
          <p className="text-sm text-rose-300">{error}</p>
        </div>
      );
    }

    if (!activity) {
      return (
        <div className="flex min-h-0 flex-1 flex-col items-center justify-center px-4 py-10 text-center text-sm text-slate-500">
          {L.missingParams || 'Unavailable'}
        </div>
      );
    }

    const imageUrl = getActivityImage(activity);
    const location = getActivityLocation(activity);
    const startTime =
      activity.start_time_local || activity.start_time || activity.Start_Time || '';
    const endTime = activity.end_time_local || activity.end_time || activity.End_Time || '';
    const timeRange = endTime
      ? `${exploreActivityFormatTime(startTime)} – ${exploreActivityFormatTime(endTime)}`
      : exploreActivityFormatTime(startTime);
    const title = activity.title || activity.Title || L.fallbackTitle || 'Activity';
    const isFixedBooking = exploreActivityLooksHardCommitted(activity);
    const description =
      activity.description || activity.Description || activity.rich_description || '';
    const activityType = getActivityType(activity);
    const destination =
      itinerary?.destination || itinerary?.Destination || itinerary?.destination_name || '';
    const dayNum =
      dayKey && itinerary?.items_by_day
        ? exploreActivityDayNumber(dayKey, itinerary.items_by_day)
        : null;

    const dayLabel =
      dayKey &&
      (dayNum != null
        ? `Day ${dayNum} · ${exploreActivityFormatDate(dayKey)}`
        : exploreActivityFormatDate(dayKey));

    const MetaRow = ({ k, v }) =>
      v ? (
        <div className="flex gap-3 rounded-xl border border-white/[0.07] bg-[#0c1016]/90 px-3 py-2.5">
          <span className="w-[92px] shrink-0 font-mono text-[9px] font-semibold uppercase tracking-[0.14em] text-cyan-400/75">
            {k}
          </span>
          <span className="min-w-0 flex-1 text-sm leading-snug text-slate-200">{v}</span>
        </div>
      ) : null;

    return (
      <div className="flex min-h-0 flex-1 flex-col overflow-hidden bg-[#070a0c]">
        <div className="relative max-h-[min(26svh,200px)] min-h-[120px] w-full shrink-0 overflow-hidden bg-slate-900">
          {imageUrl ? (
            <img
              src={imageUrl}
              alt={title}
              className="max-h-[min(26svh,200px)] w-full object-cover"
              onError={(e) => {
                e.target.style.display = 'none';
                const sib = e.target.nextElementSibling;
                if (sib) sib.style.display = 'flex';
              }}
            />
          ) : null}
          <div
            className="flex max-h-[min(26svh,200px)] min-h-[120px] w-full items-center justify-center bg-gradient-to-br from-violet-900/85 to-slate-950"
            style={{ display: imageUrl ? 'none' : 'flex' }}
          >
            <span className="text-4xl text-white/45">◆</span>
          </div>
          <div className="pointer-events-none absolute inset-0 bg-gradient-to-t from-[#070a0c] via-transparent to-transparent" />
        </div>
        <div className="min-h-0 flex-1 overflow-y-auto overscroll-y-contain px-3 pb-10 pt-4">
          {timeRange ? (
            <div className="mb-3 inline-flex items-center gap-2 rounded-full border border-[rgba(168,85,247,0.35)] bg-[#12151c] px-3 py-1.5 font-mono text-[10px] font-semibold uppercase tracking-[0.18em] text-violet-200/95 shadow-[0_0_18px_-8px_rgba(168,85,247,0.55)]">
              {timeRange}
            </div>
          ) : null}
          <h2 className="mb-3 flex flex-wrap items-center gap-2 break-words text-xl font-bold leading-snug text-white sm:text-2xl">
            <span>{title}</span>
            {isFixedBooking ? (
              <span
                className="inline-block rounded border border-amber-500/35 bg-amber-950/50 px-1.5 py-0.5 text-[9px] font-bold uppercase tracking-wide text-amber-200/95"
                aria-label={L.fixedBookingBadge || 'Fixed'}
              >
                {L.fixedBookingBadge || 'Fixed'}
              </span>
            ) : null}
          </h2>
          {description ? (
            <div className="mb-5 space-y-3 text-sm leading-relaxed text-slate-300">
              {description.split(/\n\n+/).map((para, i) => (
                <p key={i}>{para}</p>
              ))}
            </div>
          ) : (
            <p className="mb-5 text-sm italic text-slate-500">{L.noDescription}</p>
          )}
          <div className="space-y-2">
            <MetaRow k={L.labelDestination} v={destination} />
            <MetaRow k={L.labelDay} v={dayLabel} />
            <MetaRow k={L.labelLocation} v={location} />
            <MetaRow k={L.labelType} v={activityType} />
          </div>
        </div>
      </div>
    );
  }

  /**
   * TV viewport: loads activity from itinerary API; ExplorePage supplies chrome/back.
   */
  function ExploreActivityDetailEmbedded({ tripKey, dayKey, activityIndex, initialActivity, labels }) {
    const [activity, setActivity] = useState(initialActivity || null);
    const [itinerary, setItinerary] = useState(null);
    const [loading, setLoading] = useState(true);
    const [error, setError] = useState(null);

    useEffect(() => {
      let cancelled = false;
      const L = labels || {};
      if (
        !tripKey ||
        dayKey === undefined ||
        dayKey === null ||
        dayKey === '' ||
        activityIndex === undefined ||
        activityIndex === null
      ) {
        setError(L.missingParams || 'Missing parameters');
        setLoading(false);
        return undefined;
      }
      (async () => {
        try {
          setLoading(true);
          setError(null);
          const itineraryUrl = `${SF_API_BASE}/api/itineraries/${encodeURIComponent(tripKey)}`;
          const res = await window.SylvanFlowAuth.authenticatedFetch(itineraryUrl);
          await window.SylvanFlowAuth.handleAuthResponse(res);
          if (!res.ok) {
            throw new Error(`Failed to load itinerary (${res.status})`);
          }
          const data = await res.json();
          if (!data.ok || !data.itinerary) {
            throw new Error(data.error || 'Itinerary not found');
          }
          const loadedItinerary = data.itinerary;
          if (!loadedItinerary.items_by_day || !loadedItinerary.items_by_day[dayKey]) {
            throw new Error(L.missingParams || 'Day not found');
          }
          const activities = loadedItinerary.items_by_day[dayKey];
          const idx = parseInt(activityIndex, 10);
          if (idx < 0 || idx >= activities.length) {
            throw new Error(L.missingParams || 'Activity not found');
          }
          if (!cancelled) {
            setItinerary(loadedItinerary);
            setActivity(activities[idx]);
          }
        } catch (e) {
          if (window.uiLogger) {
            window.uiLogger.uiError('[EXPLORE-ACTIVITY-TV]', e?.message || e);
          }
          if (!cancelled) setError(e.message || 'Error');
        } finally {
          if (!cancelled) setLoading(false);
        }
      })();
      return () => {
        cancelled = true;
      };
    }, [tripKey, dayKey, activityIndex]);

    return (
      <ExploreActivityDetailView
        activity={activity}
        itinerary={itinerary}
        dayKey={dayKey}
        loading={loading}
        error={error}
        labels={labels}
      />
    );
  }

  if (typeof window !== 'undefined') {
    window.ExploreDetailPage = ExploreDetailPage;
    window.ExploreDestinationDetailEmbedded = ExploreDestinationDetailEmbedded;
    window.ExploreActivityDetailEmbedded = ExploreActivityDetailEmbedded;
  }
})();
