'use client';
// @design-system: checkout/AddCardForm

import { useEffect, useState, type SubmitEvent } from 'react';
import { loadStripe, type Stripe as StripeJS } from '@stripe/stripe-js';
import { Elements, PaymentElement, useStripe, useElements } from '@stripe/react-stripe-js';
import { useT } from '@/lib/i18n/react';
import { Button } from '@/components/ui/primitives/Button';
import { Spinner } from '@/components/ui/feedback/Spinner';
import { InlineNotice } from '@/components/ui/feedback/InlineNotice';
import { MockCardForm } from '@/features/checkout/MockCardForm';
import { fetchWithRefresh } from '@/lib/api/refresh-on-401';
import { getCsrfToken } from '@/lib/csrf';
import { captureCaught } from '@/lib/observability';
import { isMockScenario, type MockScenario } from '@/server/payments/mock/scenarios';
import type { ClientConfig } from '@/server/payments/provider';
import { useBrowserHref } from '@/lib/hooks/useHydrated';

// ─── Public types ─────────────────────────────────────────────────────────────

export interface SavedCard {
  id: string;
  brandName: string;
  last4: string;
  isDefault: boolean;
}

export interface AddCardFormProps {
  /** CSRF token — pass ctx.csrfToken from PurchaseContext. */
  csrfToken: string;
  /** Called when the card is saved successfully. */
  onSaved: (card: SavedCard) => void;
  /** Called when the user cancels. If undefined, no cancel button is shown. */
  onCancel?: () => void;
}

// ─── SetupForm (rendered inside Stripe <Elements>) ───────────────────────────

interface SetupFormProps {
  csrfToken: string;
  onSaved: (card: SavedCard) => void;
  onCancel?: () => void;
}

function SetupForm({ csrfToken, onSaved, onCancel }: SetupFormProps) {
  const t = useT('purchase_flow');
  const stripe = useStripe();
  const elements = useElements();
  const browserHref = useBrowserHref();
  const [saving, setSaving] = useState(false);
  const [error, setError] = useState<string | null>(null);

  async function handleSubmit(e: SubmitEvent) {
    e.preventDefault();
    if (!stripe || !elements) return;
    setSaving(true);
    setError(null);

    const { error: confirmError, setupIntent } = await stripe.confirmSetup({
      elements,
      confirmParams: { return_url: browserHref },
      redirect: 'if_required',
    });

    if (confirmError) {
      setError(confirmError.message ?? t('error_loading'));
      setSaving(false);
      return;
    }

    // setupIntent is present when redirect was not required (card path without 3DS)
    const pmId =
      typeof setupIntent?.payment_method === 'string' ? setupIntent.payment_method : null;

    if (!pmId) {
      // 3DS redirect occurred — card was NOT saved to our DB.
      // User must try again with a different card or complete 3DS and return.
      setError(t('card_requires_auth'));
      setSaving(false);
      return;
    }

    try {
      const res = await fetchWithRefresh('/api/payment-methods', {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json',
          'x-csrf-token': csrfToken,
        },
        body: JSON.stringify({ paymentMethodId: pmId }),
      });
      const data = (await res.json()) as {
        ok: boolean;
        data?: { method: { id: string; last4: string; brand: string; isDefault: boolean } };
        error?: string;
      };
      if (!data.ok || !data.data?.method) throw new Error(data.error ?? 'save failed');
      const m = data.data.method;
      onSaved({ id: m.id, brandName: m.brand, last4: m.last4, isDefault: m.isDefault });
    } catch (err) {
      captureCaught(err, { scope: 'ui.checkout.AddCardForm.save', severity: 'warning' });
      setError(t('error_loading'));
      setSaving(false);
    }
  }

  return (
    <form onSubmit={handleSubmit} className="space-y-4">
      <PaymentElement />
      {error && <InlineNotice tone="danger" description={error} />}
      <div className="flex flex-col gap-2">
        <Button
          type="submit"
          variant="primary"
          size="lg"
          className="w-full"
          loading={saving}
          disabled={saving}
        >
          {t('save_card')}
        </Button>
        {onCancel && (
          <Button
            type="button"
            variant="ghost"
            size="lg"
            className="w-full"
            onClick={onCancel}
            disabled={saving}
          >
            {t('back_to_purchase')}
          </Button>
        )}
      </div>
    </form>
  );
}

// ─── AddCardForm (outer — handles loading + provider dispatch) ───────────────

export function AddCardForm({ csrfToken, onSaved, onCancel }: AddCardFormProps) {
  const t = useT('purchase_flow');
  const [config, setConfig] = useState<ClientConfig | null>(null);
  const [clientSecret, setClientSecret] = useState<string | null | undefined>(undefined);
  // undefined = not loaded yet; null = mock provider (no SI needed); string = Stripe clientSecret
  const [stripePromise, setStripePromise] = useState<Promise<StripeJS | null> | null>(null);
  const [loadError, setLoadError] = useState<string | null>(null);
  const [mockScenario] = useState<MockScenario>(() => {
    if (typeof document === 'undefined') return 'success';
    const match = document.cookie.match(/(?:^|;\s*)md_mock_scenario=([^;]+)/);
    const raw = match?.[1] ?? null;
    return isMockScenario(raw) ? raw : 'success';
  });
  const [mockSaving, setMockSaving] = useState(false);
  const [mockError, setMockError] = useState<string | undefined>(undefined);

  useEffect(() => {
    async function load() {
      try {
        const [configRes, siRes] = await Promise.all([
          fetchWithRefresh('/api/payments/client-config'),
          fetchWithRefresh('/api/payment-methods/setup-intent', {
            method: 'POST',
            headers: { 'Content-Type': 'application/json', 'x-csrf-token': csrfToken },
            body: '{}',
          }),
        ]);
        const cfgData = (await configRes.json()) as { ok: boolean; data?: ClientConfig };
        const siData = (await siRes.json()) as {
          ok: boolean;
          data?: { clientSecret: string | null };
          error?: string;
        };
        if (!cfgData.ok || !cfgData.data) throw new Error('client-config failed');
        if (!siData.ok) throw new Error(siData.error ?? 'setup-intent failed');

        const cfg = cfgData.data;
        setConfig(cfg);
        const cs = siData.data?.clientSecret ?? null;
        setClientSecret(cs);

        if (cfg.provider === 'stripe' && typeof cs === 'string') {
          setStripePromise(loadStripe(cfg.publishableKey));
        }
      } catch (err) {
        captureCaught(err, { scope: 'ui.checkout.AddCardForm.load', severity: 'warning' });
        setLoadError(t('error_loading'));
      }
    }
    void load();
    // csrfToken is stable for the lifetime of the purchase context
  }, [csrfToken, t]);

  if (loadError) {
    return <InlineNotice tone="danger" description={loadError} />;
  }

  if (config === null || clientSecret === undefined) {
    return (
      <div className="flex justify-center py-6">
        <Spinner size="md" label={t('loading_card_form')} />
      </div>
    );
  }

  // ── Mock provider path ────────────────────────────────────────────────────
  if (config.provider === 'mock') {
    async function handleMockToken(singleUseToken: string) {
      setMockSaving(true);
      setMockError(undefined);
      try {
        const res = await fetchWithRefresh('/api/payment-methods', {
          method: 'POST',
          headers: {
            'Content-Type': 'application/json',
            'x-csrf-token': getCsrfToken(),
          },
          body: JSON.stringify({ paymentMethodId: singleUseToken }),
        });
        const data = (await res.json()) as {
          ok: boolean;
          data?: { method: { id: string; last4: string; brand: string; isDefault: boolean } };
          error?: string;
        };
        if (!data.ok || !data.data?.method) throw new Error(data.error ?? 'save failed');
        const m = data.data.method;
        onSaved({ id: m.id, brandName: m.brand, last4: m.last4, isDefault: m.isDefault });
      } catch (err) {
        captureCaught(err, { scope: 'ui.checkout.AddCardForm.mock.save', severity: 'warning' });
        setMockError(t('error_loading'));
        setMockSaving(false);
      }
    }

    return (
      <div className="space-y-3">
        <MockCardForm
          scenario={mockScenario}
          onToken={(tok) => {
            void handleMockToken(tok);
          }}
          isProcessing={mockSaving}
          externalError={mockError}
        />
        {onCancel && (
          <Button
            type="button"
            variant="ghost"
            size="lg"
            className="w-full"
            onClick={onCancel}
            disabled={mockSaving}
          >
            {t('back_to_purchase')}
          </Button>
        )}
      </div>
    );
  }

  // ── Stripe path ───────────────────────────────────────────────────────────
  if (!stripePromise || typeof clientSecret !== 'string') {
    return (
      <div className="flex justify-center py-6">
        <Spinner size="md" label={t('loading_card_form')} />
      </div>
    );
  }

  return (
    <Elements stripe={stripePromise} options={{ clientSecret }}>
      <SetupForm csrfToken={csrfToken} onSaved={onSaved} onCancel={onCancel} />
    </Elements>
  );
}
