// ============================================================
// LVRD Diagnostic Checkout — App root + state machine
//
// State persists to localStorage under `lvrd_dx_v1` so a tab
// refresh or abandoned-cart recovery brings the user back to
// where they left off. On step-04 payment success Stripe
// redirects to /checkout-flow-booked.html.
//
// Stripe integration:
//   When the user reaches step 04, this component fetches a
//   PaymentIntent client_secret from POST /api/create-payment-intent,
//   then initializes stripe.elements({ clientSecret }) and passes
//   the stripe + elements objects to Step04 via stripeCtx.
//
//   When STRIPE_PUBLISHABLE_KEY is not configured (dev/preview),
//   the API returns mock: true and stripeCtx.mock is set. Step04
//   renders a simplified dev UI and simulates payment success.
// ============================================================

const { useState, useEffect, useCallback, useRef } = React;

const STORAGE_KEY    = "lvrd_dx_v1";
const COMPLETED_KEY  = "lvrd_dx_completed";
const STEP_NAMES     = ["Quick start", "About your business", "How this works", "Secure your spot"];
const TOTAL_STEPS    = 4;

// ------------------------------------------------------------
// localStorage helpers
// ------------------------------------------------------------
function loadState() {
  try {
    const raw = localStorage.getItem(STORAGE_KEY);
    return raw ? JSON.parse(raw) : null;
  } catch (_) {
    return null;
  }
}
function saveState(state) {
  try {
    localStorage.setItem(STORAGE_KEY, JSON.stringify(state));
  } catch (_) { /* full or blocked — fail silently */ }
}

// ------------------------------------------------------------
// App
// ------------------------------------------------------------
function App() {
  const restored = loadState();
  const [step, setStep] = useState(
    restored && restored.step >= 1 && restored.step <= TOTAL_STEPS ? restored.step : 1
  );
  const [data, setDataRaw] = useState(restored && restored.data ? restored.data : {});

  // stripeCtx: { stripe, elements, loading, error, mock }
  const [stripeCtx, setStripeCtx] = useState(null);
  const stripeInitialized = useRef(false);

  // Persist state on every data change.
  const setData = useCallback((patch) => {
    setDataRaw((prev) => {
      const next = { ...prev, ...patch };
      saveState({ step, data: next });
      return next;
    });
  }, [step]);

  // Persist step changes + scroll to top.
  useEffect(() => {
    saveState({ step, data });
    window.scrollTo({ top: 0, behavior: "auto" });
  }, [step]);

  // Initialize Stripe when step 4 is reached.
  useEffect(() => {
    if (step !== 4 || stripeInitialized.current) return;
    stripeInitialized.current = true;

    setStripeCtx({ stripe: null, elements: null, loading: true, error: null, mock: false });

    fetch("/api/create-payment-intent", {
      method: "POST",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify({ email: data.email }),
    })
      .then((r) => {
        if (!r.ok) throw new Error("Payment setup failed. Please try again.");
        return r.json();
      })
      .then(({ clientSecret, publishableKey, mock }) => {
        if (mock || !publishableKey || !window.Stripe) {
          // Dev/preview mode without credentials, or Stripe.js not loaded.
          setStripeCtx({ stripe: null, elements: null, loading: false, error: null, mock: true });
          return;
        }
        const stripe = window.Stripe(publishableKey);
        const elements = stripe.elements({
          clientSecret,
          appearance: {
            theme: "stripe",
            variables: {
              colorPrimary: "#0039c6",    // --accent from LVRD design system
              colorText:    "#111111",
              borderRadius: "6px",
              fontFamily:   "Satoshi, -apple-system, system-ui, sans-serif",
            },
          },
        });
        setStripeCtx({ stripe, elements, loading: false, error: null, mock: false });
      })
      .catch((err) => {
        console.error("[checkout] Stripe init failed:", err.message);
        setStripeCtx({ stripe: null, elements: null, loading: false, error: err.message, mock: true });
      });
  }, [step]);

  const goNext = useCallback(() => setStep((s) => Math.min(s + 1, TOTAL_STEPS)), []);
  const goBack = useCallback(() => setStep((s) => Math.max(s - 1, 1)), []);

  // onPay is called only in mock mode from Step04 to simulate success.
  // With real Stripe, stripe.confirmPayment() redirects and this never fires.
  const onPay = useCallback((paymentInfo) => {
    const completed = {
      ...data,
      paidAt: new Date().toISOString(),
      paymentMethod: paymentInfo.method,
      amount: paymentInfo.amount,
      reference: "dx_" + Date.now().toString(36).slice(-8),
    };
    try {
      localStorage.setItem(COMPLETED_KEY, JSON.stringify(completed));
      localStorage.removeItem(STORAGE_KEY);
    } catch (_) {}
    window.location.href = "checkout-flow-booked.html";
  }, [data]);

  let body;
  if (step === 1) body = <Step01 data={data} setData={setData} onNext={goNext} />;
  else if (step === 2) body = <Step02 data={data} setData={setData} onNext={goNext} onBack={goBack} />;
  else if (step === 3) body = <Step03 onNext={goNext} onBack={goBack} />;
  else if (step === 4) body = <Step04 data={data} onPay={onPay} onBack={goBack} stripeCtx={stripeCtx} />;

  return (
    <>
      <CheckoutHeader />
      <ProgressBar
        step={step}
        totalSteps={TOTAL_STEPS}
        name={STEP_NAMES[step - 1]}
        onBack={step > 1 ? goBack : null}
        wide={step === 4}
      />
      {body}
      <CheckoutFooter />
    </>
  );
}

Object.assign(window, { LvrdDxApp: App });
