import React from 'react';
import { createRoot, hydrateRoot } from 'react-dom/client';
import { BrowserRouter } from 'react-router-dom';
import { HelmetProvider } from 'react-helmet-async';
import App from './App';
import { getPreviewBasename, stripPreviewPrefix } from './utils/previewPath';
import type { ListingLink } from './lib/settings';
import type { CoverageMap } from './lib/coverage';
import './index.css';

const rootElement = document.getElementById('root');
if (!rootElement) {
  throw new Error('Failed to find the root element');
}

// /__preview/<site-id>/... — the render Worker's domain-free preview route (see
// worker/src/index.ts in tenant-portal) strips this prefix server-side before routing and
// renders correctly, but the client-side app booting afterward has no idea about it: React
// Router matches the FULL pathname against App.tsx's routes, none of which start with
// "__preview", so it was hijacking a perfectly correct server-rendered preview page into its
// own "not found" the instant hydration ran. `basename` is exactly what React Router offers
// for this: routes match (and every generated <Link> href is prefixed) against the pathname
// with this stripped, so the preview keeps working after hydration and internal navigation
// within a preview stays inside it.
const basename = getPreviewBasename(window.location.pathname);

// A first hydrateRoot attempt was tried and reverted earlier this same project (see git history
// around commits f4b514d/3492e07) — that was against render.ts's hand-templated HTML, which
// can't ever match a real component tree structurally, no matter how closely it's hand-copied.
// This is a DIFFERENT, later attempt against real React SSR (render-react.ts + entry-server.tsx)
// — the actual App component tree renders on both sides now, so a structural mismatch is a real
// bug to fix, not an inherent limitation of the approach.
//
// window.__REACT_SSR__ is set ONLY by render-react.ts's globalsScript (tenant-portal), which
// only ever runs behind the Worker's explicit ?__ssr=react feature flag — never for the
// stable, currently-live render.ts path, and never absent-but-truthy by accident (it's a
// literal `true`, not just "the key exists"). Every response without that exact marker keeps
// using createRoot() exactly as before this change — zero behavior change for the entire real
// production traffic today. Reverting is as simple as removing the flag from the Worker (same
// as Phase 3/3.6) — this file's createRoot() branch is untouched from what shipped before.
const isReactSsr = (window as unknown as { __REACT_SSR__?: boolean }).__REACT_SSR__ === true;

// Hydration requires the client's FIRST render to be structurally and textually identical to
// what the server actually sent — "the provider already falls back to reading window itself"
// (App.tsx's old comment) is NOT good enough, because some of those fallbacks apply a transform
// SSR's explicit-prop path skips (e.g. PlaceholderProvider blanks any literal "{key}"-shaped
// value when it falls back to getCurrentSettings(), but takes initialSettings as-is with no
// blanking when passed directly — a real, live mismatch for any tenant with an unconfigured
// setting, confirmed via this exact site's own company_location value during Phase 3.5's parity
// check). Passing every value SSR used, explicitly, removes any dependence on two independently
// -maintained code paths happening to agree — mirrors entry-server.tsx's own <App> call exactly.
const ssrProps = isReactSsr
  ? {
      pathnameOverride: stripPreviewPrefix(window.location.pathname),
      originOverride: window.location.origin,
      initialSettings: (window as unknown as { __PRERENDERED_SETTINGS__?: Record<string, string> }).__PRERENDERED_SETTINGS__,
      initialCoverage: (window as unknown as { __COVERAGE__?: CoverageMap }).__COVERAGE__,
      pageData: (window as unknown as { __PAGE_DATA__?: unknown }).__PAGE_DATA__,
      listingLinks: (window as unknown as { __LISTING_LINKS__?: ListingLink[] }).__LISTING_LINKS__
    }
  : {};

const tree = (
  <React.StrictMode>
    <HelmetProvider>
      <BrowserRouter basename={basename}>
        <App {...ssrProps} />
      </BrowserRouter>
    </HelmetProvider>
  </React.StrictMode>
);

// A "client-only" route (RESERVED_CLIENT_ONLY_SLUGS — /about, /contact, /privacy-policy,
// /terms-of-service, /accessibility — and the 3-segment city sub-pages /:state/:city/
// services|about|contact) is never server-rendered by either renderer, so on a genuinely
// COLD/direct visit (a bookmark, a shared link, typing the URL) window.__SITE_ID__ was never
// embedded — every downstream site-scoped read (settings, coverage) then has no way to resolve
// which site this is at all. Found live: hvac-pros's own /california/bell-gardens/services
// redirected to a blank, unbranded homepage on a fresh visit. Client-side navigation between
// pages that already loaded real data works fine regardless (App/CoverageProvider/
// PlaceholderProvider mount once, state persists) — this only ever fires on that one cold-load
// case. See worker/src/index.ts's /__site_info for why this can't just query Supabase directly
// (the `sites` table has no public read policy at all).
async function resolveSiteIdIfMissing(): Promise<void> {
  if ((window as unknown as { __SITE_ID__?: string }).__SITE_ID__) return;
  try {
    const res = await fetch('/__site_info');
    if (!res.ok) return;
    const data = (await res.json()) as { site_id: string | null };
    if (data.site_id) {
      (window as unknown as { __SITE_ID__?: string }).__SITE_ID__ = data.site_id;
    }
  } catch (err) {
    console.error('Failed to resolve site id for a client-only route:', err);
  }
}

resolveSiteIdIfMissing().then(() => {
  if (isReactSsr) {
    hydrateRoot(rootElement, tree);
  } else {
    createRoot(rootElement).render(tree);
  }
});