import React, { useEffect, useMemo, useState } from "react";
import { loadStripe } from "@stripe/stripe-js";
import { Elements, PaymentElement, useElements, useStripe } from "@stripe/react-stripe-js";

const LABELS = {
  free: 'Free booking',
  cash: 'Pay at location',
  woocommerce: 'Card or gateway checkout',
  stripe: 'Secure card payment',
  paypal: 'PayPal',
};

const NOTES = {
  free: 'No payment is required for this booking.',
  cash: 'Confirm now and pay when you arrive.',
  woocommerce: 'Continue to your checkout page to complete payment.',
  stripe: 'Pay securely without leaving the booking flow.',
  paypal: 'Continue to PayPal to approve the payment.',
};

const ICONS = {
  cash: 'payment_type_cash.png',
  free: 'payment_later.png',
  woocommerce: 'payment_type_cards.png',
  stripe: 'processor-stripe.png',
  paypal: 'processor-paypal.png',
};

function buildImageUrl(baseImages, fileName, buildVersion) {
  if (!baseImages || !fileName) return '';
  const base = String(baseImages).replace(/\/$/, '');
  const suffix = buildVersion ? `?v=${encodeURIComponent(buildVersion)}` : '';
  return `${base}/${fileName}${suffix}`;
}

function InnerStripePay({ bookingId, bookingKey, onPaid, onBack, onSubmitStart }) {
  const stripe = useStripe();
  const elements = useElements();
  const [loading, setLoading] = useState(false);
  const [err, setErr] = useState("");

  const pay = async () => {
    setErr("");
    if (!stripe || !elements) return;

    setLoading(true);
    try {
      await onSubmitStart?.();
      const { error, paymentIntent } = await stripe.confirmPayment({
        elements,
        confirmParams: {
          return_url: window.location.href,
        },
        redirect: "if_required",
      });

      if (error) {
        setErr(error.message || "Payment failed.");
        setLoading(false);
        return;
      }

      const res = await fetch("/wp-json/pointly-booking/v1/front/payment/stripe/confirm", {
        method: "POST",
        credentials: "same-origin",
        headers: {
          "Content-Type": "application/json",
          "X-WP-Nonce": window.pointlybooking_FRONT?.nonce || "",
        },
        body: JSON.stringify({
          booking_id: bookingId,
          payment_intent_id: paymentIntent?.id || "",
          status: paymentIntent?.status || "",
          key: bookingKey,
        }),
      });

      const j = await res.json();
      if (j?.success) {
        onPaid();
        return;
      }

      setErr("Payment not completed yet. Please try again.");
    } catch (e) {
      setErr(e?.message || "Payment error.");
    } finally {
      setLoading(false);
    }
  };

  return (
    <div className="bp-pay-wrap">
      <div className="bp-pay-box">
        <PaymentElement />
      </div>

      {err ? <div className="bp-alert bp-alert-error">{err}</div> : null}

      <div className="bp-pay-actions">
        <button type="button" className="bp-btn bp-btn-light" onClick={onBack} disabled={loading}>
          Back
        </button>
        <button type="button" className="bp-btn bp-btn-primary" onClick={pay} disabled={!stripe || loading}>
          {loading ? "Processing..." : "Pay now"}
        </button>
      </div>
    </div>
  );
}

export default function StepPayment({
  bookingId,
  bookingKey,
  totalLabel,
  paymentMethod,
  paymentMethodLabel,
  enabledMethods = ['cash'],
  imagesBase = '',
  onChangePaymentMethod,
  onPrepareStripePayment,
  onSubmitBooking,
  onPaid,
  onBack,
  onStripeConfirmStart,
}) {
  const pk = window.pointlybooking_FRONT?.stripe_pk || "";
  const stripePromise = useMemo(() => (pk ? loadStripe(pk) : null), [pk]);
  const methods = Array.isArray(enabledMethods) && enabledMethods.length ? enabledMethods : ['cash'];
  const selectedMethod = paymentMethod || methods[0] || 'cash';
  const selectedLabel = paymentMethodLabel || LABELS[selectedMethod] || selectedMethod;
  const buildVersion = window.pointlybooking_FRONT?.imagesBuild || "";
  const [clientSecret, setClientSecret] = useState("");
  const [loading, setLoading] = useState(false);
  const [err, setErr] = useState("");
  const canSwitchMethod = !bookingId && !loading && !clientSecret;
  const isStripe = selectedMethod === "stripe";
  const actionLabel = selectedMethod === 'woocommerce'
    ? 'Continue to checkout'
    : selectedMethod === 'paypal'
      ? 'Continue to PayPal'
      : selectedMethod === 'cash'
        ? 'Confirm booking'
        : 'Book now';

  useEffect(() => {
    if (!bookingId || !bookingKey) return;
    if (selectedMethod !== "stripe") return;

    let alive = true;
    setErr("");
    setLoading(true);

    fetch("/wp-json/pointly-booking/v1/front/payment/stripe/start", {
      method: "POST",
      credentials: "same-origin",
      headers: {
        "Content-Type": "application/json",
        "X-WP-Nonce": window.pointlybooking_FRONT?.nonce || "",
      },
      body: JSON.stringify({ booking_id: bookingId, key: bookingKey }),
    })
      .then((r) => r.json().then((j) => ({ ok: r.ok, j })))
      .then(({ ok, j }) => {
        if (!alive) return;
        if (!ok || !j?.success || !j?.client_secret) {
          throw new Error(j?.message || "Could not start Stripe payment.");
        }
        setClientSecret(j.client_secret);
      })
      .catch((e) => {
        if (!alive) return;
        setErr(e?.message || "Stripe start error.");
      })
      .finally(() => alive && setLoading(false));

    return () => {
      alive = false;
    };
  }, [bookingId, bookingKey, selectedMethod]);

  useEffect(() => {
    if (selectedMethod === "stripe") return;
    setClientSecret("");
    setErr("");
  }, [selectedMethod]);

  async function prepareStripePayment() {
    if (!onPrepareStripePayment) return;
    setErr("");
    setLoading(true);
    try {
      await onPrepareStripePayment();
    } catch (e) {
      setErr(e?.message || "Could not prepare secure payment.");
      setLoading(false);
    }
  }

  async function handleSubmitNonStripe() {
    setErr("");
    setLoading(true);
    try {
      await onSubmitBooking?.();
    } catch (e) {
      setErr(e?.message || "Could not continue with payment.");
      setLoading(false);
    }
  }

  return (
    <div className="bp-step">
      <div className="bp-step-body">
        <section className="bp-section-card">
          <div className="bp-step-head">
            <div>
              <h3>Payment</h3>
              <div className="bp-muted">Choose how you want to complete the booking.</div>
            </div>
            <div className="bp-total">{totalLabel}</div>
          </div>

          <div className="bp-pay-grid bp-mt-12">
            {methods.map((method) => {
              const iconUrl = buildImageUrl(imagesBase, ICONS[method], buildVersion);

              return (
                <button
                  key={method}
                  type="button"
                  className={`bp-pay-option ${selectedMethod === method ? 'is-active' : ''}`}
                  onClick={() => canSwitchMethod && onChangePaymentMethod?.(method)}
                  disabled={!canSwitchMethod && selectedMethod !== method}
                  aria-pressed={selectedMethod === method}
                >
                  <div className="bp-pay-logo">
                    {iconUrl ? <img src={iconUrl} alt="" /> : null}
                  </div>
                  <div className="bp-pay-meta">
                    <div className="bp-font-800">{LABELS[method] || method}</div>
                    <div className="bp-text-xs bp-muted">{NOTES[method] || ''}</div>
                  </div>
                </button>
              );
            })}
          </div>

          <div className="bp-inline-note">
            <strong>{selectedLabel}</strong>
            <span>{NOTES[selectedMethod] || 'Your selection is saved for this booking.'}</span>
          </div>
        </section>

        {err ? <div className="bp-alert bp-alert-error">{err}</div> : null}

        {isStripe ? (
          <>
            {!pk ? (
              <section className="bp-section-card">
                <div className="bp-alert bp-alert-error">
                  Stripe publishable key is missing. Please configure it in BookPoint Settings.
                </div>
                <div className="bp-pay-actions">
                  <button type="button" className="bp-btn bp-btn-light" onClick={onBack}>
                    Back
                  </button>
                </div>
              </section>
            ) : null}

            {pk && !bookingId ? (
              <section className="bp-section-card">
                <div className="bp-section-intro">
                  <div className="bp-section-eyebrow">Secure checkout</div>
                  <h3 className="bp-section-title">Prepare your secure payment form</h3>
                  <p className="bp-section-desc">We create a temporary booking hold first, then load the secure Stripe form inside the wizard.</p>
                </div>
                <div className="bp-pay-actions bp-pay-actions--spread">
                  <button type="button" className="bp-btn bp-btn-light" onClick={onBack} disabled={loading}>
                    Back
                  </button>
                  <button type="button" className="bp-btn bp-btn-primary" onClick={prepareStripePayment} disabled={loading}>
                    {loading ? "Preparing..." : "Prepare secure payment"}
                  </button>
                </div>
              </section>
            ) : null}

            {pk && loading && !clientSecret ? <div className="bp-muted">Preparing secure payment...</div> : null}

            {pk && clientSecret && stripePromise ? (
              <Elements stripe={stripePromise} options={{ clientSecret }}>
                <InnerStripePay
                  bookingId={bookingId}
                  bookingKey={bookingKey}
                  onPaid={onPaid}
                  onBack={onBack}
                  onSubmitStart={onStripeConfirmStart}
                />
              </Elements>
            ) : null}
          </>
        ) : (
          <section className="bp-section-card">
            <div className="bp-section-intro">
              <div className="bp-section-eyebrow">Next step</div>
              <h3 className="bp-section-title">{LABELS[selectedMethod] || selectedMethod}</h3>
              <p className="bp-section-desc">{NOTES[selectedMethod] || 'Continue to complete the booking.'}</p>
            </div>
            <div className="bp-pay-actions bp-pay-actions--spread">
              <button type="button" className="bp-btn bp-btn-light" onClick={onBack} disabled={loading}>
                Back
              </button>
              <button type="button" className="bp-btn bp-btn-primary" onClick={handleSubmitNonStripe} disabled={loading}>
                {loading ? "Continuing..." : actionLabel}
              </button>
            </div>
          </section>
        )}
      </div>
    </div>
  );
}
