// Pulse preview page — renders the email digest as it would arrive,
// inside an iframe so the email's inline styles can't leak into the site.
//
// Hash route: #/pulse-preview        → defaults to los-angeles
//             #/pulse-preview/<city>
//
// The preview pulls real data from the DB. When a metro has no real events
// yet (most do, since wait-time reports + status logs are still sparse),
// we layer the sample data on top so the layout always demonstrates well.
// A toggle lets the visitor flip between "real" and "with sample data".

(function () {
  const { useState, useEffect, useMemo } = React;

  function PulsePreviewPage({ onNav }) {
    const hash = window.location.hash || "";
    const m = hash.match(/^#\/pulse-preview\/([a-z0-9-]+)/i);
    const initialCityId = m ? m[1] : "los-angeles";

    const [cityId, setCityId] = useState(initialCityId);
    const [data, setData] = useState(null);
    const [loading, setLoading] = useState(true);
    const [showSample, setShowSample] = useState(true);
    const [iframeMode, setIframeMode] = useState("desktop");

    const cities = (window.SI_DATA && window.SI_DATA.FEATURED_CITIES) || [
      { id: "los-angeles", name: "Los Angeles", state: "CA" },
      { id: "new-york", name: "New York", state: "NY" },
      { id: "chicago", name: "Chicago", state: "IL" },
      { id: "atlanta", name: "Atlanta", state: "GA" },
      { id: "denver", name: "Denver", state: "CO" },
    ];

    useEffect(() => {
      let canceled = false;
      async function run() {
        setLoading(true);
        const built = await buildDigestData(cityId, cities);
        if (!canceled) {
          setData(built);
          setLoading(false);
        }
      }
      run();
      return () => { canceled = true; };
    }, [cityId]);

    const finalData = useMemo(() => {
      if (!data) return null;
      if (!showSample) return data;
      // Layer sample data on top where the real arrays are empty
      const sample = window.PulseDigest.sampleData(data.city);
      return {
        ...data,
        facilityEvents: data.facilityEvents.length ? data.facilityEvents : sample.facilityEvents,
        waitTimes: data.waitTimes.length ? data.waitTimes : sample.waitTimes,
        intelTips: data.intelTips.length ? data.intelTips : sample.intelTips,
        metricMovers: data.metricMovers.length ? data.metricMovers : sample.metricMovers,
        dxUpdates: data.dxUpdates.length ? data.dxUpdates : (sample.dxUpdates || []),
        weatherAlerts: data.weatherAlerts.length ? data.weatherAlerts : (sample.weatherAlerts || []),
        weatherForecast: data.weatherForecast.length ? data.weatherForecast : (sample.weatherForecast || []),
        roadSignals: data.roadSignals.length ? data.roadSignals : (sample.roadSignals || []),
      };
    }, [data, showSample]);

    const rendered = useMemo(() => {
      if (!finalData || !window.PulseDigest) return null;
      return window.PulseDigest.render(finalData);
    }, [finalData]);

    return (
      <div className="pulse-preview-wrap">
        <div className="pulse-preview-header">
          <div className="pulse-preview-headline">
            <div className="section-eyebrow">Pulse · Live Preview</div>
            <h1>What lands in your inbox at 7am.</h1>
            <p>
              This is the actual email a {finalData ? finalData.city.name : "metro"} subscriber
              would receive tomorrow morning, generated from live database state.
              Real facility events, real wait times, real published driver intel.
            </p>
          </div>

          <div className="pulse-preview-controls">
            <label>
              <span>Metro</span>
              <select value={cityId} onChange={(e) => {
                setCityId(e.target.value);
                window.location.hash = `#/pulse-preview/${e.target.value}`;
              }}>
                {cities.map((c) => (
                  <option key={c.id} value={c.id}>{c.name}, {c.state}</option>
                ))}
              </select>
            </label>

            <label className="pulse-preview-toggle">
              <input
                type="checkbox"
                checked={showSample}
                onChange={(e) => setShowSample(e.target.checked)}
              />
              <span>Demo data when sparse</span>
            </label>

            <div className="pulse-preview-viewport">
              <button
                className={iframeMode === "desktop" ? "active" : ""}
                onClick={() => setIframeMode("desktop")}
              >Desktop</button>
              <button
                className={iframeMode === "mobile" ? "active" : ""}
                onClick={() => setIframeMode("mobile")}
              >Mobile</button>
            </div>
          </div>

          {rendered && (
            <div className="pulse-preview-meta">
              <div className="pulse-preview-meta-item">
                <span className="meta-k">Subject:</span>
                <span className="meta-v">{rendered.subject}</span>
              </div>
              {data && (
                <div className="pulse-preview-meta-item">
                  <span className="meta-k">Live data:</span>
                  <span className="meta-v">
                    {data.facilityEvents.length} facility events ·{" "}
                    {data.waitTimes.length} wait reports ·{" "}
                    {data.intelTips.length} published tips
                  </span>
                </div>
              )}
            </div>
          )}
        </div>

        <div className={`pulse-preview-frame-wrap mode-${iframeMode}`}>
          {loading && <div className="pulse-preview-loading">Loading…</div>}
          {!loading && rendered && (
            <iframe
              className="pulse-preview-frame"
              title="Pulse email preview"
              srcDoc={rendered.html}
              sandbox="allow-same-origin"
            />
          )}
        </div>

        <div className="pulse-preview-footer">
          <p>
            Pulse is the daily operating tempo of a metro: facility status,
            wait times, driver intel, score movement. Cron-driven, not editor-curated —
            we send what changed in the last 24 hours, and only what changed.
          </p>
          <p>
            Sign up from the homepage to receive it for your metro.
          </p>
        </div>
      </div>
    );
  }

  // Pull real data for a metro from Supabase. Falls back gracefully on errors —
  // empty arrays mean "we'll show the sample" if the toggle is on.
  async function buildDigestData(cityId, cities) {
    const city = cities.find((c) => c.id === cityId) || { id: cityId, name: cityId, state: "" };
    const result = {
      city,
      asOf: new Date().toISOString(),
      facilityEvents: [],
      waitTimes: [],
      intelTips: [],
      dxUpdates: [],
      weatherAlerts: [],
      weatherForecast: [],
      roadSignals: [],
      metricMovers: [],
      unsubscribeUrl: "https://shippingclarity.com/#/manage?token=PREVIEW",
    };

    if (!window.SI_DB || !window.SI_DB.SUPABASE_URL) return result;
    const base = window.SI_DB.SUPABASE_URL;
    const key = "sb_publishable_0zNSihwdiVEKHD_HQj7Oqw_wEGGPFf6";
    const headers = { apikey: key, Authorization: `Bearer ${key}` };
    const since24 = new Date(Date.now() - 24 * 3600 * 1000).toISOString();
    const since7d = new Date(Date.now() - 7 * 24 * 3600 * 1000).toISOString();

    try {
      // Carriers/facilities in this city — we'll need entity_id → name lookup
      const entRes = await fetch(
        `${base}/rest/v1/entities?select=id,name,primary_city_id,type&primary_city_id=eq.${cityId}`,
        { headers }
      );
      const entities = entRes.ok ? await entRes.json() : [];
      const entById = Object.fromEntries(entities.map((e) => [e.id, e.name]));
      const entityIds = entities.map((e) => `"${e.id}"`).join(",");

      // Facility events
      if (entityIds) {
        const fRes = await fetch(
          `${base}/rest/v1/facility_status_log?select=*&entity_id=in.(${entityIds})&created_at=gte.${since24}&order=created_at.desc`,
          { headers }
        );
        if (fRes.ok) {
          const rows = await fRes.json();
          result.facilityEvents = rows.map((r) => ({
            entity_name: entById[r.entity_id] || "Unknown facility",
            status: r.status,
            start_date: r.start_date,
            source_url: r.source_url,
            notes: r.notes,
          }));
        }
        // Wait times
        const wRes = await fetch(
          `${base}/rest/v1/wait_time_reports?select=*&facility_id=in.(${entityIds})&created_at=gte.${since24}&order=created_at.desc`,
          { headers }
        );
        if (wRes.ok) {
          const rows = await wRes.json();
          result.waitTimes = rows.map((r) => ({
            facility_name: entById[r.facility_id] || "Unknown facility",
            minutes: r.minutes,
            created_at: r.created_at,
          }));
        }
      }

      // Driver experience — facilities rated in last 7 days
      if (entityIds) {
        try {
          const r1 = await fetch(
            `${base}/rest/v1/facility_driver_ratings?select=facility_id&facility_id=in.(${entityIds})&created_at=gte.${since7d}`,
            { headers }
          );
          if (r1.ok) {
            const newRows = await r1.json();
            const newCounts = {};
            newRows.forEach((r) => { newCounts[r.facility_id] = (newCounts[r.facility_id] || 0) + 1; });
            const fIds = Object.keys(newCounts);
            if (fIds.length > 0) {
              const r2 = await fetch(
                `${base}/rest/v1/facility_driver_composite?select=*&facility_id=in.(${fIds.map((id) => `"${id}"`).join(",")})`,
                { headers }
              );
              if (r2.ok) {
                const comps = await r2.json();
                result.dxUpdates = comps.map((c) => ({
                  facility_name: entById[c.facility_id] || "—",
                  composite_rating: c.composite_rating,
                  total_ratings: c.total_ratings,
                  new_ratings_7d: newCounts[c.facility_id] || 0,
                })).sort((a, b) => b.new_ratings_7d - a.new_ratings_7d);
              }
            }
          }
        } catch (e) { /* views/tables not yet deployed */ }
      }

      // Weather alerts (moderate+) and forecast for the city
      try {
        const wa = await fetch(
          `${base}/rest/v1/active_weather_signals?select=*&city_id=eq.${cityId}&kind=eq.alert&severity=in.(moderate,severe,extreme)`,
          { headers }
        );
        if (wa.ok) result.weatherAlerts = await wa.json();
        const wf = await fetch(
          `${base}/rest/v1/active_weather_signals?select=*&city_id=eq.${cityId}&kind=eq.forecast&order=effective_at.asc&limit=5`,
          { headers }
        );
        if (wf.ok) result.weatherForecast = await wf.json();
      } catch (e) { /* tables not yet deployed */ }

      // Road signals
      try {
        const rs = await fetch(
          `${base}/rest/v1/active_road_signals?select=*&city_id=eq.${cityId}&order=severity.desc&limit=10`,
          { headers }
        );
        if (rs.ok) result.roadSignals = await rs.json();
      } catch (e) { /* tables not yet deployed */ }

      // Intel — published only, this city, last 7 days
      const iRes = await fetch(
        `${base}/rest/v1/intel_submissions?select=carrier_id,severity,parsed_intel_type,created_at&city_id=eq.${cityId}&status=eq.verified&visibility=eq.public&published_at=gte.${since7d}&order=published_at.desc`,
        { headers }
      );
      if (iRes.ok) {
        const rows = await iRes.json();
        result.intelTips = rows.map((r) => ({
          carrier_name: entById[r.carrier_id] || "—",
          severity: r.severity,
          parsed_intel_type: r.parsed_intel_type,
          created_at: r.created_at,
        }));
      }
    } catch (err) {
      console.warn("preview fetch err", err);
    }

    return result;
  }

  window.PulsePreviewPage = PulsePreviewPage;
})();
