import React, { useState } from 'react';
import { Box, Button, Typography, Alert, CircularProgress } from '@mui/material';
import { PaymentElement, AddressElement, useStripe, useElements } from '@stripe/react-stripe-js';
import type { StripePaymentElementChangeEvent, StripeAddressElementChangeEvent } from '@stripe/stripe-js';

interface PaymentMethodFormProps {
  onSubmit: (paymentMethodId: string) => void;
  isLoading?: boolean;
}

export const PaymentMethodForm: React.FC<PaymentMethodFormProps> = ({
  onSubmit,
  isLoading = false,
}) => {
  const stripe = useStripe();
  const elements = useElements();
  const [error, setError] = useState<string | null>(null);
  const [processing, setProcessing] = useState(false);
  const [paymentComplete, setPaymentComplete] = useState(false);
  const [addressComplete, setAddressComplete] = useState(false);

  const handlePaymentChange = (event: StripePaymentElementChangeEvent) => {
    setPaymentComplete(event.complete);
  };

  const handleAddressChange = (event: StripeAddressElementChangeEvent) => {
    setAddressComplete(event.complete);
  };

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

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

    setProcessing(true);
    setError(null);

    try {
      // Submit the elements to validate all fields
      const { error: submitError } = await elements.submit();
      if (submitError) {
        setError(submitError.message || 'Failed to validate payment details');
        setProcessing(false);
        return;
      }

      // Get billing details from AddressElement
      const addressElement = elements.getElement(AddressElement);
      if (!addressElement) {
        setError('Address element not found');
        setProcessing(false);
        return;
      }

      const addressData = await addressElement.getValue();
      if (!addressData.complete) {
        setError('Please complete the billing address');
        setProcessing(false);
        return;
      }

      // Create the payment method with billing details
      const { error: createError, paymentMethod } = await stripe.createPaymentMethod({
        elements,
        params: {
          billing_details: {
            name: addressData.value.name,
            address: {
              line1: addressData.value.address.line1,
              line2: addressData.value.address.line2 || undefined,
              city: addressData.value.address.city,
              state: addressData.value.address.state,
              postal_code: addressData.value.address.postal_code,
              country: addressData.value.address.country,
            },
          },
        },
      });

      if (createError) {
        setError(createError.message || 'Failed to create payment method');
        setProcessing(false);
        return;
      }

      if (paymentMethod) {
        onSubmit(paymentMethod.id);
      }
    } catch {
      setError('An unexpected error occurred');
      setProcessing(false);
    }
  };

  const isFormComplete = paymentComplete && addressComplete;

  return (
    <form onSubmit={handleSubmit}>
      <Box sx={{ mb: 3 }}>
        <Typography variant="subtitle2" gutterBottom>
          Billing Address
        </Typography>
        <Box
          sx={{
            border: 1,
            borderColor: 'divider',
            borderRadius: 1,
            p: 2,
            mb: 3,
            '&:hover': {
              borderColor: 'primary.main',
            },
          }}
        >
          <AddressElement
            options={{
              mode: 'billing',
              defaultValues: {
                address: {
                  country: 'US',
                },
              },
            }}
            onChange={handleAddressChange}
          />
        </Box>

        <Typography variant="subtitle2" gutterBottom>
          Card Details
        </Typography>
        <Box
          sx={{
            border: 1,
            borderColor: 'divider',
            borderRadius: 1,
            p: 2,
            '&:hover': {
              borderColor: 'primary.main',
            },
          }}
        >
          <PaymentElement
            options={{
              layout: 'tabs',
              fields: {
                billingDetails: {
                  address: 'never',
                },
              },
            }}
            onChange={handlePaymentChange}
          />
        </Box>
      </Box>

      {error && (
        <Alert severity="error" sx={{ mb: 2 }}>
          {error}
        </Alert>
      )}

      <Button
        type="submit"
        variant="contained"
        color="primary"
        fullWidth
        disabled={!stripe || processing || isLoading || !isFormComplete}
      >
        {processing || isLoading ? (
          <CircularProgress size={24} />
        ) : (
          'Update Payment Method'
        )}
      </Button>
    </form>
  );
};
