"use client";

// Stripe Payment Element for the booking-deposit flow.
// First real client component in the app — needed because Stripe.js can only
// run in the browser.

import { useState } from "react";
import { loadStripe, type Stripe } from "@stripe/stripe-js";
import {
  Elements,
  PaymentElement,
  useElements,
  useStripe,
} from "@stripe/react-stripe-js";

// Cache the Stripe object across renders. loadStripe returns a Promise-like.
let stripePromise: ReturnType<typeof loadStripe> | null = null;
function getStripe(publishableKey: string) {
  if (!stripePromise) stripePromise = loadStripe(publishableKey);
  return stripePromise;
}

export function PaymentForm({
  publishableKey,
  clientSecret,
  amountCents,
  returnUrl,
}: {
  publishableKey: string;
  clientSecret: string;
  amountCents: number;
  returnUrl: string;
}) {
  return (
    <Elements
      stripe={getStripe(publishableKey)}
      options={{
        clientSecret,
        appearance: { theme: "stripe" },
      }}
    >
      <CheckoutInner amountCents={amountCents} returnUrl={returnUrl} />
    </Elements>
  );
}

function CheckoutInner({
  amountCents,
  returnUrl,
}: {
  amountCents: number;
  returnUrl: string;
}) {
  const stripe = useStripe();
  const elements = useElements();
  const [submitting, setSubmitting] = useState(false);
  const [error, setError] = useState<string | null>(null);

  async function onSubmit(e: React.FormEvent) {
    e.preventDefault();
    if (!stripe || !elements) return;
    setSubmitting(true);
    setError(null);

    const { error: stripeError } = await stripe.confirmPayment({
      elements,
      confirmParams: { return_url: returnUrl },
    });

    // confirmPayment only returns here on validation/network errors;
    // on success Stripe redirects to return_url.
    if (stripeError) {
      setError(stripeError.message ?? "Payment failed — try again.");
      setSubmitting(false);
    }
  }

  return (
    <form onSubmit={onSubmit} className="space-y-4">
      <PaymentElement />
      {error && (
        <div className="rounded-md border border-red-200 bg-red-50 p-3 text-sm text-red-800 dark:border-red-900 dark:bg-red-950/40 dark:text-red-200">
          {error}
        </div>
      )}
      <button
        type="submit"
        disabled={!stripe || !elements || submitting}
        className="w-full rounded-md bg-zinc-900 py-2.5 text-sm font-medium text-white hover:bg-zinc-800 disabled:opacity-50 dark:bg-zinc-100 dark:text-zinc-900"
      >
        {submitting ? "Processing…" : `Pay $${(amountCents / 100).toFixed(2)} deposit`}
      </button>
      <p className="text-center text-xs text-zinc-500">
        Your card is charged the deposit now. The remaining balance is paid in person.
      </p>
    </form>
  );
}

// Type re-export so the page can declare props without importing @stripe/stripe-js.
export type { Stripe };
