/**
 * Add Payment Method Modal Component
 *
 * Uses Stripe Elements with SetupIntent to securely save card details
 * without charging the customer.
 *
 * For Stripe Connect, we must initialize Stripe with the connected account ID
 * so the SetupIntent (created on the connected account) can be confirmed.
 */

import React, { useState, useEffect } from 'react';
import { loadStripe, Stripe } from '@stripe/stripe-js';
import {
  Elements,
  CardElement,
  useStripe,
  useElements,
} from '@stripe/react-stripe-js';
import { CreditCard, Loader2, X, CheckCircle, AlertCircle } from 'lucide-react';
import { useTranslation } from 'react-i18next';
import { useCreateSetupIntent, useSetDefaultPaymentMethod, useCustomerPaymentMethods } from '../hooks/useCustomerBilling';
import { useQueryClient } from '@tanstack/react-query';

// Cache for Stripe instances per connected account
// Note: Module-level cache persists across component re-renders but not page reloads
const stripeInstanceCache: Record<string, Promise<Stripe | null>> = {};

// Clear cache entry (useful for debugging)
export const clearStripeCache = (key?: string) => {
  if (key) {
    delete stripeInstanceCache[key];
  } else {
    Object.keys(stripeInstanceCache).forEach(k => delete stripeInstanceCache[k]);
  }
};

// Get or create Stripe instance for a connected account (or platform account if empty)
// For direct_api mode, customPublishableKey will be the tenant's key
// For connect mode, we use the platform's key with stripeAccount
const getStripeInstance = (
  stripeAccount: string,
  customPublishableKey?: string
): Promise<Stripe | null> => {
  // Use custom key for direct_api mode, platform key for connect mode
  const publishableKey = customPublishableKey || import.meta.env.VITE_STRIPE_PUBLISHABLE_KEY || '';
  // Use 'platform' as cache key for direct_api mode (empty stripeAccount)
  // For direct_api with custom key, include key in cache to avoid conflicts
  const cacheKey = customPublishableKey
    ? `direct_${customPublishableKey.substring(0, 20)}`
    : (stripeAccount || 'platform');

  console.log('[AddPaymentMethodModal] getStripeInstance called with:', {
    stripeAccount: stripeAccount || '(empty - direct_api mode)',
    cacheKey,
    publishableKey: publishableKey.substring(0, 20) + '...',
    isDirectApi: !!customPublishableKey,
  });

  if (!stripeInstanceCache[cacheKey]) {
    console.log('[AddPaymentMethodModal] Creating new Stripe instance for:', cacheKey);
    // Only pass stripeAccount option if it's not empty (connect mode)
    // For direct_api mode, we use the tenant's own API keys (no connected account needed)
    stripeInstanceCache[cacheKey] = stripeAccount
      ? loadStripe(publishableKey, { stripeAccount })
      : loadStripe(publishableKey);
  } else {
    console.log('[AddPaymentMethodModal] Using cached Stripe instance for:', cacheKey);
  }

  return stripeInstanceCache[cacheKey];
};

interface CardFormProps {
  clientSecret: string;
  onSuccess: () => void;
  onCancel: () => void;
}

const CardFormInner: React.FC<CardFormProps> = ({
  clientSecret,
  onSuccess,
  onCancel,
}) => {
  const { t } = useTranslation();
  const stripe = useStripe();
  const elements = useElements();
  const queryClient = useQueryClient();
  const [isProcessing, setIsProcessing] = useState(false);
  const [errorMessage, setErrorMessage] = useState<string | null>(null);
  const [isComplete, setIsComplete] = useState(false);
  const [cardComplete, setCardComplete] = useState(false);

  // Get current payment methods to check if this is the first one
  const { data: paymentMethodsData } = useCustomerPaymentMethods();
  const setDefaultPaymentMethod = useSetDefaultPaymentMethod();

  // Detect dark mode for Stripe CardElement styling
  const [isDarkMode, setIsDarkMode] = useState(() =>
    document.documentElement.classList.contains('dark')
  );

  useEffect(() => {
    // Watch for dark mode changes
    const observer = new MutationObserver(() => {
      setIsDarkMode(document.documentElement.classList.contains('dark'));
    });
    observer.observe(document.documentElement, {
      attributes: true,
      attributeFilter: ['class'],
    });
    return () => observer.disconnect();
  }, []);

  const handleSubmit = async (event: React.FormEvent) => {
    event.preventDefault();

    if (!stripe || !elements) {
      return;
    }

    const cardElement = elements.getElement(CardElement);
    if (!cardElement) {
      return;
    }

    setIsProcessing(true);
    setErrorMessage(null);

    try {
      // Confirm the SetupIntent with Stripe
      const { error, setupIntent } = await stripe.confirmCardSetup(clientSecret, {
        payment_method: {
          card: cardElement,
        },
      });

      if (error) {
        setErrorMessage(error.message || t('billing.addCardFailed', 'Failed to add card. Please try again.'));
        setIsProcessing(false);
        return;
      }

      if (setupIntent && setupIntent.status === 'succeeded') {
        // Get the payment method ID from the setup intent
        const paymentMethodId = typeof setupIntent.payment_method === 'string'
          ? setupIntent.payment_method
          : setupIntent.payment_method?.id;

        // Check if there's already a default payment method
        const existingMethods = paymentMethodsData?.payment_methods;
        const hasDefaultMethod = existingMethods?.some(pm => pm.is_default) ?? false;

        console.log('[AddPaymentMethodModal] SetupIntent succeeded:', {
          paymentMethodId,
          existingMethodsCount: existingMethods?.length ?? 0,
          hasDefaultMethod,
        });

        // Set as default if no default payment method exists yet
        if (!hasDefaultMethod && paymentMethodId) {
          console.log('[AddPaymentMethodModal] No default payment method exists, setting new one as default:', paymentMethodId);
          // Set as default (fire and forget - don't block the success flow)
          setDefaultPaymentMethod.mutate(paymentMethodId, {
            onSuccess: () => {
              console.log('[AddPaymentMethodModal] Successfully set payment method as default');
            },
            onError: (err) => {
              console.error('[AddPaymentMethodModal] Failed to set default payment method:', err);
            },
          });
        } else {
          console.log('[AddPaymentMethodModal] Default already exists or no paymentMethodId - existingMethods:', existingMethods?.length, 'hasDefaultMethod:', hasDefaultMethod, 'paymentMethodId:', paymentMethodId);
        }

        // Invalidate payment methods to refresh the list
        queryClient.invalidateQueries({ queryKey: ['customerPaymentMethods'] });
        setIsComplete(true);
        setTimeout(() => {
          onSuccess();
        }, 1500);
      }
    } catch (err: any) {
      setErrorMessage(err.message || t('billing.unexpectedError', 'An unexpected error occurred.'));
      setIsProcessing(false);
    }
  };

  if (isComplete) {
    return (
      <div className="text-center py-8">
        <CheckCircle className="w-16 h-16 text-green-500 mx-auto mb-4" />
        <h3 className="text-lg font-semibold text-gray-900 dark:text-white mb-2">
          {t('billing.cardAdded', 'Card Added Successfully!')}
        </h3>
        <p className="text-gray-600 dark:text-gray-400">
          {t('billing.cardAddedDescription', 'Your payment method has been saved.')}
        </p>
      </div>
    );
  }

  return (
    <form onSubmit={handleSubmit} className="space-y-4">
      <div className="bg-white dark:bg-gray-800 rounded-lg border border-gray-200 dark:border-gray-700 p-4">
        <CardElement
          options={{
            style: {
              base: {
                fontSize: '16px',
                color: isDarkMode ? '#f1f5f9' : '#1e293b',
                iconColor: isDarkMode ? '#94a3b8' : '#64748b',
                '::placeholder': {
                  color: isDarkMode ? '#64748b' : '#94a3b8',
                },
              },
              invalid: {
                color: isDarkMode ? '#f87171' : '#dc2626',
                iconColor: isDarkMode ? '#f87171' : '#dc2626',
              },
            },
          }}
          onChange={(e) => setCardComplete(e.complete)}
        />
      </div>

      {errorMessage && (
        <div className="flex items-start gap-2 p-3 bg-red-50 dark:bg-red-900/30 border border-red-200 dark:border-red-800 rounded-lg">
          <AlertCircle className="w-5 h-5 text-red-600 dark:text-red-400 shrink-0 mt-0.5" />
          <p className="text-sm text-red-600 dark:text-red-400">{errorMessage}</p>
        </div>
      )}

      <div className="flex gap-3 pt-2">
        <button
          type="button"
          onClick={onCancel}
          disabled={isProcessing}
          className="flex-1 py-2.5 border border-gray-300 dark:border-gray-600 text-gray-700 dark:text-gray-300 rounded-lg hover:bg-gray-50 dark:hover:bg-gray-700 disabled:opacity-50"
        >
          {t('common.cancel', 'Cancel')}
        </button>
        <button
          type="submit"
          disabled={!stripe || isProcessing || !cardComplete}
          className="flex-1 py-2.5 bg-brand-600 text-white rounded-lg hover:bg-brand-700 disabled:opacity-50 flex items-center justify-center gap-2"
        >
          {isProcessing ? (
            <>
              <Loader2 className="w-4 h-4 animate-spin" />
              {t('common.saving', 'Saving...')}
            </>
          ) : (
            <>
              <CreditCard className="w-4 h-4" />
              {t('billing.saveCard', 'Save Card')}
            </>
          )}
        </button>
      </div>

      <p className="text-xs text-center text-gray-500 dark:text-gray-400 mt-2">
        {t('billing.stripeSecure', 'Your payment information is securely processed by Stripe')}
      </p>
    </form>
  );
};

interface AddPaymentMethodModalProps {
  isOpen: boolean;
  onClose: () => void;
  onSuccess?: () => void;
}

export const AddPaymentMethodModal: React.FC<AddPaymentMethodModalProps> = ({
  isOpen,
  onClose,
  onSuccess,
}) => {
  const { t } = useTranslation();
  const [clientSecret, setClientSecret] = useState<string | null>(null);
  const [stripeAccount, setStripeAccount] = useState<string | null>(null);
  const [stripePromise, setStripePromise] = useState<Promise<Stripe | null> | null>(null);
  const [error, setError] = useState<string | null>(null);
  const createSetupIntent = useCreateSetupIntent();

  // Detect dark mode for Stripe Elements appearance
  const [isDarkMode, setIsDarkMode] = useState(() =>
    document.documentElement.classList.contains('dark')
  );

  useEffect(() => {
    // Watch for dark mode changes
    const observer = new MutationObserver(() => {
      setIsDarkMode(document.documentElement.classList.contains('dark'));
    });
    observer.observe(document.documentElement, {
      attributes: true,
      attributeFilter: ['class'],
    });
    return () => observer.disconnect();
  }, []);

  useEffect(() => {
    if (isOpen && !clientSecret && !createSetupIntent.isPending) {
      // Create SetupIntent when modal opens
      createSetupIntent.mutate(undefined, {
        onSuccess: (data) => {
          console.log('[AddPaymentMethodModal] SetupIntent response:', {
            client_secret: data.client_secret?.substring(0, 30) + '...',
            setup_intent_id: data.setup_intent_id,
            customer_id: data.customer_id,
            stripe_account: data.stripe_account,
            publishable_key: data.publishable_key ? data.publishable_key.substring(0, 20) + '...' : null,
          });

          // stripe_account can be empty string for direct_api mode, or acct_xxx for connect mode
          // Only undefined/null indicates an error
          if (data.stripe_account === undefined || data.stripe_account === null) {
            console.error('[AddPaymentMethodModal] stripe_account is undefined/null - payment system may not be configured correctly');
            setError(t('billing.paymentSystemNotConfigured', 'The payment system is not fully configured. Please contact support.'));
            return;
          }

          setClientSecret(data.client_secret);
          setStripeAccount(data.stripe_account);
          // Load Stripe - empty stripe_account means direct_api mode (use tenant's publishable_key)
          // Non-empty stripe_account means connect mode (use platform key with connected account)
          setStripePromise(getStripeInstance(data.stripe_account, data.publishable_key));
        },
        onError: (err: any) => {
          console.error('[AddPaymentMethodModal] SetupIntent error:', err);
          setError(err.response?.data?.error || t('billing.setupIntentFailed', 'Failed to initialize. Please try again.'));
        },
      });
    }
  }, [isOpen]);

  useEffect(() => {
    if (!isOpen) {
      // Reset state when modal closes
      setClientSecret(null);
      setStripeAccount(null);
      setStripePromise(null);
      setError(null);
    }
  }, [isOpen]);

  const handleSuccess = () => {
    onSuccess?.();
    onClose();
  };

  if (!isOpen) return null;

  return (
    <div className="fixed inset-0 z-50 flex items-center justify-center bg-black/50">
      <div className="bg-white dark:bg-gray-800 rounded-lg shadow-xl w-full max-w-md mx-4 p-6">
        <div className="flex items-center justify-between mb-6">
          <div>
            <h3 className="text-lg font-semibold text-gray-900 dark:text-white">
              {t('billing.addPaymentMethod', 'Add Payment Method')}
            </h3>
            <p className="text-sm text-gray-500 dark:text-gray-400">
              {t('billing.addPaymentMethodDescription', 'Save a card for future payments')}
            </p>
          </div>
          <button
            onClick={onClose}
            className="text-gray-400 hover:text-gray-600 dark:hover:text-gray-300"
          >
            <X className="w-5 h-5" />
          </button>
        </div>

        {createSetupIntent.isPending ? (
          <div className="flex flex-col items-center justify-center py-12">
            <Loader2 className="w-8 h-8 animate-spin text-brand-600 mb-4" />
            <p className="text-gray-600 dark:text-gray-400">
              {t('common.loading', 'Loading...')}
            </p>
          </div>
        ) : error ? (
          <div className="space-y-4">
            <div className="flex items-start gap-2 p-3 bg-red-50 dark:bg-red-900/30 border border-red-200 dark:border-red-800 rounded-lg">
              <AlertCircle className="w-5 h-5 text-red-600 dark:text-red-400 shrink-0 mt-0.5" />
              <p className="text-sm text-red-600 dark:text-red-400">{error}</p>
            </div>
            <div className="flex gap-3">
              <button
                onClick={onClose}
                className="flex-1 py-2 border border-gray-300 dark:border-gray-600 text-gray-700 dark:text-gray-300 rounded-lg hover:bg-gray-50 dark:hover:bg-gray-700"
              >
                {t('common.cancel', 'Cancel')}
              </button>
              <button
                onClick={() => {
                  setError(null);
                  createSetupIntent.mutate(undefined, {
                    onSuccess: (data) => {
                      setClientSecret(data.client_secret);
                      setStripeAccount(data.stripe_account);
                      setStripePromise(getStripeInstance(data.stripe_account, data.publishable_key));
                    },
                    onError: (err: any) => {
                      setError(err.response?.data?.error || t('billing.setupIntentFailed', 'Failed to initialize. Please try again.'));
                    },
                  });
                }}
                className="flex-1 py-2 bg-brand-600 text-white rounded-lg hover:bg-brand-700"
              >
                {t('common.tryAgain', 'Try Again')}
              </button>
            </div>
          </div>
        ) : clientSecret && stripePromise ? (
          <Elements
            stripe={stripePromise}
            options={{
              clientSecret,
              appearance: {
                theme: isDarkMode ? 'night' : 'stripe',
                variables: {
                  colorPrimary: '#2563eb',
                  colorBackground: isDarkMode ? '#1f2937' : '#ffffff',
                  colorText: isDarkMode ? '#f1f5f9' : '#1e293b',
                  colorDanger: isDarkMode ? '#f87171' : '#dc2626',
                  fontFamily: 'system-ui, -apple-system, sans-serif',
                  spacingUnit: '12px',
                  borderRadius: '8px',
                },
              },
            }}
          >
            <CardFormInner
              clientSecret={clientSecret}
              onSuccess={handleSuccess}
              onCancel={onClose}
            />
          </Elements>
        ) : null}
      </div>
    </div>
  );
};

export default AddPaymentMethodModal;
