// Shared checkout state + Stripe wiring.
// Used by both CheckoutC (desktop) and CheckoutCMobile.
// The hook owns: plan, all form fields, the Stripe instance + Elements,
// submit handling, error state. It exposes everything the layouts need.

// Self-hosted thank-you page on the same checkout domain — keeps customers on
// pay.{homesalelegalprotection,sellersshield}.com (no cross-domain hop).
function returnUrl() {
  try { return window.location.origin + "/thank-you"; }
  catch (_) { return "/thank-you"; }
}

// State-aware coverage. 4-Year = $75k everywhere; 2-Year = $30k in FL & GA,
// $75k elsewhere. Must mirror the server-side helper in lib/zoho.js.
function coverageFor(state, plan) {
  if (plan === "4yr") return 75000;
  const s = String(state || "").toUpperCase().trim();
  if (s === "FL" || s === "GA" || s === "FLORIDA" || s === "GEORGIA") return 30000;
  return 75000;
}

// Host-aware tagline: drop "Powered by" on sellersshield.com (own brand).
function brandTagline() {
  try {
    return /(^|\.)sellersshield\.com$/i.test(window.location.hostname)
      ? "By Sellers Shield"
      : "Powered by Sellers Shield";
  } catch (_) { return "Powered by Sellers Shield"; }
}

const plansData = {
  "2yr": {
    termLong: "2-Year",
    title: "2-Year Plan",
    coverage: 75000,
    price: 32900,
    listPrice: 70000,
    save: 37100,
    badge: { label: "BEST VALUE", tone: "green" },
    bullets: [
      "Up to $75,000 in legal defense covered",
      "Paid expert attorney provided in 24–48 hrs",
      "100% refundable if your home doesn't sell",
    ],
  },
  "4yr": {
    termLong: "4-Year",
    title: "4-Year Plan",
    coverage: 75000,
    price: 102900,
    listPrice: 210000,
    save: 107100,
    badge: { label: "MAX PROTECTION", tone: "dark" },
    bullets: [
      "Up to $75,000 in legal defense covered",
      "Paid expert attorney provided in 24–48 hrs",
      "4 full years of post-sale coverage",
    ],
  },
};

const disputeTypes = [
  { icon: "roof", label: "Roof & structural" },
  { icon: "foundation", label: "Foundation" },
  { icon: "droplet", label: "Flooding & water" },
  { icon: "bolt", label: "Electrical" },
  { icon: "thermostat", label: "HVAC & plumbing" },
  { icon: "mold", label: "Mold & mildew" },
];

const API = () => window.API_BASE || "";

// Validates the buyer-facing form fields. Stripe handles its own validation
// inside PaymentElement.
function validateForm(s, reduced) {
  // In "reduced" mode (an emailed link with an existing order id), the order
  // already has name + property, so we only require a valid email.
  if (!s.email.trim() || !/^[^@\s]+@[^@\s]+\.[^@\s]+$/.test(s.email)) return "Valid email is required";
  if (reduced) return null;
  if (!s.firstName.trim())    return "First name is required";
  if (!s.lastName.trim())     return "Last name is required";
  if (!s.propertyLine1.trim()) return "Street address is required";
  if (!s.propertyCity.trim())  return "City is required";
  if (!s.propertyState.trim()) return "State is required";
  if (!/^\d{5}(-\d{4})?$/.test(s.propertyZip.trim())) return "Valid ZIP is required";
  return null;
}

// Read order-routing + source-tracking params from the URL.
const UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
function linkParamsFromUrl() {
  try {
    const q = new URLSearchParams(window.location.search);
    const pid = (q.get("pid") || "").trim();
    return {
      pid: UUID_RE.test(pid) ? pid : "",     // existing-order id (UUID)
      src: (q.get("src") || "").trim(),      // HSLP upsell source
      pcr: (q.get("pcr") || "").trim(),      // pay-at-close → pay-now reason
      state: (q.get("state") || "").trim(),  // pre-fill propertyState (e.g. "FL", "Florida")
    };
  } catch (_) {
    return { pid: "", src: "", pcr: "", state: "" };
  }
}

// Read an initial plan from the ?plan= URL param so marketing-site buttons can
// deep-link to a pre-selected plan. Accepts a few friendly aliases.
function initialPlanFromUrl() {
  try {
    const p = (new URLSearchParams(window.location.search).get("plan") || "").toLowerCase().trim();
    if (["2yr", "2", "2-year", "2year", "2-yr"].includes(p)) return "2yr";
    if (["4yr", "4", "4-year", "4year", "4-yr"].includes(p)) return "4yr";
  } catch (_) { /* noop */ }
  return "4yr"; // default
}

function useCheckout() {
  const link = React.useRef(linkParamsFromUrl()).current; // { pid, src, pcr }
  const hasOrderId = !!link.pid;

  const [plan, setPlan] = React.useState(initialPlanFromUrl);
  const [firstName, setFirstName] = React.useState("");
  const [lastName, setLastName] = React.useState("");
  const [email, setEmail] = React.useState("");
  const [phone, setPhone] = React.useState("");
  const [agentEmail, setAgentEmail] = React.useState("");
  const [propertyLine1, setPropertyLine1] = React.useState("");
  const [propertyCity, setPropertyCity] = React.useState("");
  // Pre-fill state from the URL (?state=FL or ?state=Florida) when present —
  // drives the coverage display ($30k vs $75k) without making the buyer type it.
  const [propertyState, setPropertyState] = React.useState(() => {
    try {
      const s = (new URLSearchParams(window.location.search).get("state") || "").trim();
      return s;
    } catch (_) { return ""; }
  });
  const [propertyZip, setPropertyZip] = React.useState("");

  const [paymentIntentId, setPaymentIntentId] = React.useState(null);
  const [paymentReady, setPaymentReady] = React.useState(false);
  const [submitting, setSubmitting] = React.useState(false);
  const [error, setError] = React.useState(null);

  const stripeRef = React.useRef(null);
  const elementsRef = React.useRef(null);
  const mountSelectorRef = React.useRef(null);

  // Init Stripe instance once
  React.useEffect(() => {
    if (!window.Stripe) {
      setError("Stripe.js failed to load");
      return;
    }
    if (!window.STRIPE_PUBLISHABLE_KEY || window.STRIPE_PUBLISHABLE_KEY.includes("REPLACE")) {
      setError("Stripe publishable key not configured (set window.STRIPE_PUBLISHABLE_KEY)");
      return;
    }
    stripeRef.current = window.Stripe(window.STRIPE_PUBLISHABLE_KEY);
  }, []);

  const piIdRef = React.useRef(null);
  const initedRef = React.useRef(false);

  // Create the PaymentIntent + mount the PaymentElement — EXACTLY ONCE.
  // (Stripe allows only one Element of type "payment" per elements instance,
  // so we never create a second one; plan changes re-price via fetchUpdates.)
  React.useEffect(() => {
    if (!stripeRef.current || initedRef.current) return;
    initedRef.current = true;
    let cancelled = false;

    (async () => {
      try {
        setError(null);
        const r = await fetch(`${API()}/api/create-payment-intent`, {
          method: "POST",
          headers: { "Content-Type": "application/json" },
          body: JSON.stringify({ plan, pid: link.pid, src: link.src, pcr: link.pcr }),
        });
        const data = await r.json();
        if (!r.ok) throw new Error(data.error || "Failed to create payment intent");
        if (cancelled) return;

        piIdRef.current = data.paymentIntentId;
        setPaymentIntentId(data.paymentIntentId);

        const elements = stripeRef.current.elements({
          clientSecret: data.clientSecret,
          appearance: {
            theme: "stripe",
            variables: {
              colorPrimary: "#1a3a5c",
              colorBackground: "#ffffff",
              colorText: "#1a2a4a",
              colorDanger: "#c2410c",
              borderRadius: "10px",
              fontFamily: "Inter Tight, -apple-system, BlinkMacSystemFont, sans-serif",
              spacingUnit: "4px",
            },
          },
        });
        elementsRef.current = elements;

        const target = mountSelectorRef.current || "#stripe-payment-element";
        elements.create("payment").mount(target);
        setPaymentReady(true);
      } catch (e) {
        if (!cancelled) { setError(e.message); initedRef.current = false; }
      }
    })();

    return () => { cancelled = true; };
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, []);

  // Re-price the existing PaymentIntent when the plan changes — NO remount.
  React.useEffect(() => {
    if (!piIdRef.current || !elementsRef.current) return; // not initialized yet
    let cancelled = false;
    (async () => {
      try {
        setError(null);
        const r = await fetch(`${API()}/api/update-payment-intent`, {
          method: "POST",
          headers: { "Content-Type": "application/json" },
          body: JSON.stringify({ paymentIntentId: piIdRef.current, plan, pid: link.pid, src: link.src, pcr: link.pcr }),
        });
        const data = await r.json();
        if (!r.ok) throw new Error(data.error || "Failed to update payment intent");
        if (cancelled) return;
        elementsRef.current.fetchUpdates();
      } catch (e) {
        if (!cancelled) setError(e.message);
      }
    })();
    return () => { cancelled = true; };
  }, [plan]);

  const handleSubmit = async () => {
    setError(null);
    const validationError = validateForm({
      firstName, lastName, email,
      propertyLine1, propertyCity, propertyState, propertyZip,
    }, hasOrderId);
    if (validationError) { setError(validationError); return; }
    if (!stripeRef.current || !elementsRef.current || !paymentIntentId) {
      setError("Payment isn't ready yet — give it a moment and try again.");
      return;
    }

    setSubmitting(true);
    try {
      // Push the latest form values to the PaymentIntent's metadata so the
      // webhook has everything it needs for the Zoho records.
      const updateResp = await fetch(`${API()}/api/update-payment-intent`, {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({
          paymentIntentId, plan, email, firstName, lastName, phone, agentEmail,
          pid: link.pid, src: link.src, pcr: link.pcr,
          propertyAddress: {
            line1: propertyLine1, city: propertyCity,
            state: propertyState, zip: propertyZip,
          },
        }),
      });
      if (!updateResp.ok) {
        const data = await updateResp.json().catch(() => ({}));
        throw new Error(data.error || "Couldn't save your order details");
      }

      const { error: confirmError } = await stripeRef.current.confirmPayment({
        elements: elementsRef.current,
        confirmParams: {
          return_url: returnUrl(),
          payment_method_data: {
            billing_details: {
              name: `${firstName} ${lastName}`.trim(),
              email,
              phone: phone || undefined,
              address: {
                line1: propertyLine1,
                city: propertyCity,
                state: propertyState,
                postal_code: propertyZip,
                country: "US",
              },
            },
          },
          receipt_email: email,
        },
      });
      if (confirmError) {
        setError(confirmError.message || "Payment failed. Please try again.");
      }
      // On success Stripe redirects to RETURN_URLS[plan] — nothing more to do here.
    } catch (e) {
      setError(e.message);
    } finally {
      setSubmitting(false);
    }
  };

  // Layouts call this to tell the hook where to mount PaymentElement.
  const setPaymentMountSelector = (sel) => {
    mountSelectorRef.current = sel;
  };

  return {
    // form state
    plan, setPlan,
    firstName, setFirstName, lastName, setLastName,
    email, setEmail, phone, setPhone, agentEmail, setAgentEmail,
    propertyLine1, setPropertyLine1, propertyCity, setPropertyCity,
    propertyState, setPropertyState, propertyZip, setPropertyZip,
    // payment state
    paymentReady, submitting, error,
    setError,
    handleSubmit,
    setPaymentMountSelector,
    // link context
    hasOrderId,   // true when the page was opened with a ?pid= existing order
  };
}

Object.assign(window, {
  plansData,
  disputeTypes,
  useCheckout,
  coverageFor,
  brandTagline,
});
