import React, { useState, useContext, useEffect, useMemo } from 'react';
import ContentWithAsideLayout from '../../layouts/ContentWithAsideLayout';
import AppContext from '../../context/Context';
import CheckoutAside from './checkout/CheckoutAside';
import {
  Card,
  CardBody,
  Col,
  Button,
  Row,
  FormGroup,
  Input,
  CustomInput,
  UncontrolledTooltip,
  Label
} from 'reactstrap';
import Select from 'react-select';
import FalconCardHeader from '../common/FalconCardHeader';
import { useForm, Controller, get, set } from 'react-hook-form';
import FalconInput from '../common/FalconInput';
import { Link, useHistory } from 'react-router-dom';
import Flex from '../common/Flex';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import iconPaymentMethodsGrid from '../../assets/img/icons/icon-payment-methods-grid.png';
import iconPaypalFull from '../../assets/img/icons/icon-paypal-full.png';
import { useResponsive } from '@farfetch/react-context-responsive';
import { useShoppingCart } from '../../hooks/useShoppingCart';
import { getBillingInfo, getUserDetail, getCountries, createRecurlyAccount, placeOrder } from '../../helpers/rest';
import { useAuth } from '../../context/UserAuth';
import { isValid, isExpirationDateValid, isSecurityCodeValid, getCreditCardNameByNumber } from 'creditcard.js';
import { useCheckout } from '../../hooks/useCheckout';

const JKCheckout = () => {
  const { currency } = useContext(AppContext);
  const { cartTotal: payableTotal, loading: cartLoading, getCartItems, shoppingCart } = useShoppingCart();
  const { greaterThan } = useResponsive();
  const { currentUser } = useAuth();
  const history = useHistory();
  const { setPreserveBillingInfo, refreshPreserveBillingInfo, shouldPreserveBillingInfo, deletePreserveBillingInfo } = useCheckout();

  const [paymentMethod, setPaymentMethod] = useState('credit-card');
  const [paymentErrorMessage, setPaymentErrorMessage] = useState('');
  const [orderErrorMessage, setOrderErrorMessage] = useState('');
  const [cardNumber, setCardNumber] = useState('');
  const [billingInfo, setBillingInfo] = useState({});
  const [countries, setCountries] = useState([]);
  const [submitting, setSubmitting] = useState(false);

  const [reuseExistingCard, setReuseExistingCard] = useState(false);
  const [hasRedeemableJamTrack, setHasRedeemableJamTrack] = useState(false);
  const [hasAlreadyEnteredBillingInfo, setHasAlreadyEnteredBillingInfo] = useState(false);
  const [saveThisCard, setSaveThisCard] = useState(false);
  const [hideBillingInfo, setHideBillingInfo] = useState(true);

  const labelClassName = 'ls text-600 font-weight-semi-bold mb-0';

  const {
    register,
    control,
    handleSubmit,
    setValue,
    setError,
    formState: { errors }
  } = useForm({
    defaultValues: {
      first_name: '',
      last_name: '',
      address1: '',
      address2: '',
      city: '',
      state: '',
      zip: '',
      country: 'US',
      number: '',
      month: '',
      year: '',
      verification_value: ''
    }
  });

  useEffect(() => {
      getCartItems()
    }, [])

  useEffect(() => {
    if (shouldPreserveBillingInfo) {
      refreshPreserveBillingInfo();
      setHasAlreadyEnteredBillingInfo(true);
      setHideBillingInfo(true);
    } else {
      setHideBillingInfo(false);
    }
  }, []);

  useEffect(() => {
    if (currentUser) {
      fetchCountries();
      populateData();
    }
  }, [currentUser]);

  const fetchCountries = () => {
    getCountries()
      .then(response => {
        if (response.ok) {
          return response.json();
        }
      })
      .then(data => {
        setCountries(data.countriesx);
      })
      .catch(error => console.log(error));
  };

  const populateData = async () => {
    const options = {
      id: currentUser.id
    };
    try {
      const userResp = await getUserDetail(options);
      const userData = await userResp.json();
      //console.log('User Data:', userData);
      setHasRedeemableJamTrack(userData.has_redeemable_jamtrack);

      if (userData.has_recurly_account) {
        setReuseExistingCard(userData.reuse_card);
        await populateBillingAddress();
      } else {
        setValue('first_name', userData.first_name);
        setValue('last_name', userData.last_name);
        setValue('address1', userData.address1);
        setValue('address2', userData.address2);
        setValue('city', userData.city);
        setValue('state', userData.state);
        setValue('zip', userData.zip);
        setValue('country', userData.country);
      }
    } catch (error) {
      console.error('Failed to get user details:', error);
    }
  };

  const populateBillingAddress = async () => {
    try {
      const resp = await getBillingInfo();
      const data = await resp.json();
      const bi = data.billing_info;

      setValue('first_name', bi.first_name);
      setValue('last_name', bi.last_name);
      setValue('address1', bi.address1);
      setValue('address2', billingInfo.address2);
      setValue('city', bi.city);
      setValue('state', bi.state);
      setValue('zip', bi.zip);
      setValue('country', bi.country);

      setBillingInfo(bi);
    } catch (error) {
      console.error('Failed to get billing info:', error);
    }
  };

  const disableCardFields = useMemo(() => {
    return paymentMethod === 'existing-card';
  }, [paymentMethod]);

  const onSubmit = async data => {
    //console.log('Form Data:', data);
    if (paymentMethod === 'credit-card' || paymentMethod === 'existing-card') {
      constructRecurlyAccount(data);
    } else if (paymentMethod === 'paypal') {
      handoverToPaypal();
    }
  };

  const constructRecurlyAccount = async data => {
    //console.log('Form Data:', data);

    if (paymentMethod === 'credit-card' && !isValidateCard(data)) {
      return;
    }

    const bInfo = { ...data, number: cardNumber };
    // Save card
    try {
      setSubmitting(true);
      await createRecurlyAccount({
        billing_info: bInfo,
        terms_of_service: true,
        reuse_card_this_time: paymentMethod === 'existing-card',
        reuse_card_next_time: saveThisCard || paymentMethod === 'existing-card'
      });
      setPreserveBillingInfo();
      await doPlaceOrder();
    } catch (error) {
      console.error('Failed to create recurly account:', error);
      if (error.responseJSON && error.responseJSPN.errors) {
        error.responseJSON.errors.forEach((key, err) => {
          if (key === 'number') {
            setError('number', { type: 'manual', message: err }, { shouldFocus: false });
          }
          if (key === 'verification_value') {
            setError('verification_value', { type: 'manual', message: err }, { shouldFocus: false });
          }
          if (key === 'message') {
            setPaymentErrorMessage(err);
          }
        });
      } else if (error.responseText) {
        setPaymentErrorMessage(error.responseText);
      }
    } finally {
      setSubmitting(false);
    }
  };

  const doPlaceOrder = async () => {
    let message = 'Error submitting payment: ';
    try {
      const orderResp = await placeOrder();
      const orderData = await orderResp.json();
      //console.log('Order Data:', orderData);
      localStorage.setItem('lastPurchaseResponse', JSON.stringify(orderData));
      deletePreserveBillingInfo();
      history.push('/checkout/success');
    } catch (error) {
      console.error('Failed to place order:', error);
      if (error.responseJSON && error.responseJSON.errors) {
        error.responseJSON.errors.forEach((key, err) => {
          message += key + ': ' + err;
        });
        setOrderErrorMessage(message);
      } else if (error.responseText) {
        setOrderErrorMessage(error.responseText);
      }
    }
  };

  const isValidateCard = data => {
    let _isValid = true;

    if (!isValid(cardNumber)) {
      _isValid = false;
      //console.log('Invalid Card Number');
      setError('number', { type: 'manual', message: 'Invalid Card Number' }, { shouldFocus: false });
    }
    if (!isExpirationDateValid(data.month, data.year)) {
      _isValid = false;
      //console.log('Invalid Expiration Date');
      setError('month', { type: 'manual', message: 'Invalid Expiration Date' }, { shouldFocus: false });
      setError('year', { type: 'manual', message: 'Invalid Expiration Date' }, { shouldFocus: false });
    }
    // if (!isSecurityCodeValid(data.verification_value)) {
    //   _isValid = false;
    //   console.log('Invalid Security Code');
    //   setError('verification_value', { type: 'manual', message: 'Invalid Security Code' }, { shouldFocus: false });
    // }
    return _isValid;
  };

  function formatCardNumber(value) {
    const v = value.replace(/\s+/g, '').replace(/[^0-9]/gi, '');
    const matches = v.match(/\d{4,16}/g);
    const match = (matches && matches[0]) || '';
    const parts = [];

    for (let i = 0; i < match.length; i += 4) {
      parts.push(match.substring(i, i + 4));
    }

    if (parts.length) {
      return parts.join(' ');
    } else {
      return value;
    }
  }

  const handleOnCardNumberChange = e => {
    const cardNumber = e.target.value;
    //console.log('Formatted Card Number:', formatCardNumber(cardNumber));
    setCardNumber(formatCardNumber(cardNumber));
  };

  const handoverToPaypal = () => {
    // Handover to Paypal
    window.location = `${process.env.REACT_APP_CLIENT_BASE_URL}/paypal/checkout/start`;
  };

  const handleCountryChange = selectedOption => {
    setValue('country', selectedOption.value);
  };

  return (
    <div style={{ width: greaterThan.sm ? '75%' : '100%' }} className="mx-auto">
      <div className='mb-3'>
        <Link to="/shopping-cart">{`< Back to shopping cart`}</Link>
      </div>
      {hasAlreadyEnteredBillingInfo && (
        <div className="alert alert-info" role="alert">
          <div className="d-flex">
            <FontAwesomeIcon icon="info-circle" className="mr-2" />
            <p>
              You recently entered payment info successfully. If you want to change your payment info, click the
              CHANGE PAYMENT INFO button. Otherwise, click the Confirm &amp; Pay button to checkout.
            </p>
          </div>
          <div className='d-flex'>
            <Button onClick={() => setHideBillingInfo(!hideBillingInfo)}>
              {hideBillingInfo ? 'Change Payment Info' : 'Hide Payment Info'}
            </Button>
            <Button onClick={doPlaceOrder} className="ml-2">
              Confirm &amp; Pay
            </Button>
          </div>

        </div>
      )}
      <ContentWithAsideLayout
        aside={cartLoading ? <div>Cart Loading...</div> : <CheckoutAside shoppingCart={shoppingCart} />}
        isStickyAside={false}
      >


        <form onSubmit={handleSubmit(onSubmit)} className={hideBillingInfo ? 'd-none' : 'd-block'}>
          {/* {hasRedeemableJamTrack ? (
            <div className="alert alert-info d-flex" role="alert">
              <FontAwesomeIcon icon="info-circle" className="mr-2" />
              <p>
                Please enter your billing address and payment information below.&nbsp;{' '}
                <strong>You will not be billed for any charges of any kind without your explicit authorization.</strong>
                &nbsp; There are no "hidden" charges or fees, thank you!
              </p>
            </div>
          ) : (
            <div className="alert alert-info d-flex" role="alert">
              <FontAwesomeIcon icon="info-circle" className="mr-2" />
              <p>Please enter your billing address and payment information below.&nbsp; </p>
            </div>
          )} */}
          <Card className="mb-3">
            <FalconCardHeader title="Billing Address" titleTag="h5" />
            <CardBody>
              <Row className="mb-2">
                <Col xs={12} md={5} lg={4} className="text-md-right">
                  <Label for="first_name" className={labelClassName}>
                    First Name
                  </Label>
                </Col>
                <Col>
                  <input {...register('first_name', { required: 'First Name is required' })} className="form-control" />
                  {errors.first_name && (
                    <div className="text-danger">
                      <small>{errors.first_name.message}</small>
                    </div>
                  )}
                </Col>
              </Row>
              <Row className="mb-2">
                <Col xs={12} md={5} lg={4} className="text-md-right">
                  <Label for="last_name" className={labelClassName}>
                    Last Name
                  </Label>
                </Col>
                <Col>
                  <input {...register('last_name', { required: 'Last Name is required' })} className="form-control" />
                  {errors.last_name && (
                    <div className="text-danger">
                      <small>{errors.last_name.message}</small>
                    </div>
                  )}
                </Col>
              </Row>
              <Row className="mb-2">
                <Col xs={12} md={5} lg={4} className="text-md-right">
                  <Label for="address1" className={labelClassName}>
                    Address 1
                  </Label>
                </Col>
                <Col>
                  <input {...register('address1', { required: 'Address is required' })} className="form-control" />
                  {errors.address1 && (
                    <div className="text-danger">
                      <small>{errors.address1.message}</small>
                    </div>
                  )}
                </Col>
              </Row>
              <Row className="mb-2">
                <Col xs={12} md={5} lg={4} className="text-md-right">
                  <Label for="address2" className={labelClassName}>
                    Address 2
                  </Label>
                </Col>
                <Col>
                  <input {...register('address2')} className="form-control" />
                  {errors.address2 && (
                    <div className="text-danger">
                      <small>{errors.address2.message}</small>
                    </div>
                  )}
                </Col>
              </Row>
              <Row className="mb-2">
                <Col xs={12} md={5} lg={4} className="text-md-right">
                  <Label for="city" className={labelClassName}>
                    City
                  </Label>
                </Col>
                <Col>
                  <input {...register('city', { required: 'City is required' })} className="form-control" />
                  {errors.city && (
                    <div className="text-danger">
                      <small>{errors.city.message}</small>
                    </div>
                  )}
                </Col>
              </Row>
              <Row className="mb-2">
                <Col xs={12} md={5} lg={4} className="text-md-right">
                  <Label for="state" className={labelClassName}>
                    State or Region
                  </Label>
                </Col>
                <Col>
                  <input {...register('state', { required: 'State or Region is required' })} className="form-control" />
                  {errors.state && (
                    <div className="text-danger">
                      <small>{errors.state.message}</small>
                    </div>
                  )}
                </Col>
              </Row>
              <Row className="mb-2">
                <Col xs={12} md={5} lg={4} className="text-md-right">
                  <Label for="zip" className={labelClassName}>
                    Zip or Postal Code
                  </Label>
                </Col>
                <Col>
                  <input
                    {...register('zip', { required: 'Zip or Postal Code is required' })}
                    className="form-control"
                  />
                  {errors.zip && (
                    <div className="text-danger">
                      <small>{errors.zip.message}</small>
                    </div>
                  )}
                </Col>
              </Row>
              <Row className="mb-2">
                <Col xs={12} md={5} lg={4} className="text-md-right">
                  <Label for="country" className={labelClassName}>
                    Country
                  </Label>
                </Col>
                <Col>
                  <Controller
                    name="country"
                    control={control}
                    rules={{ required: 'Country is required' }}
                    render={({ field: { onChange, value } }) => {
                      const country = countries.find(country => country.countrycode === value);
                      if (!country) {
                        return (
                          <Select
                            data-testid="countrySelect"
                            onChange={handleCountryChange}
                            options={countries.map(c => {
                              return { value: c.countrycode, label: c.countryname };
                            })}
                          />
                        );
                      }
                      return (
                        <Select
                          data-testid="countrySelect"
                          value={{ value: country.countrycode, label: country.countryname }}
                          onChange={handleCountryChange}
                          options={countries.map(c => {
                            return { value: c.countrycode, label: c.countryname };
                          })}
                        />
                      );
                    }}
                  />
                  {errors.country && (
                    <div className="text-danger">
                      <small>{errors.country.message}</small>
                    </div>
                  )}
                </Col>
              </Row>
            </CardBody>
          </Card>
          <Card className="mb-3">
            <FalconCardHeader title="Payment Method" titleTag="h5" />
            <CardBody>
              {paymentErrorMessage && (
                <div className="alert alert-danger" role="alert">
                  {paymentErrorMessage}
                </div>
              )}
              {reuseExistingCard && (
                <>
                  <Row className="mt-3">
                    <Col xs={12}>
                      <CustomInput
                        label={
                          <>
                            <Flex align="center" className="mb-2">
                              <div className="fs-1">Reuse Existing Card</div>
                            </Flex>
                            <div>Use card ending with {billingInfo.last_four}</div>
                          </>
                        }
                        id="existing-card"
                        value="existing-card"
                        checked={paymentMethod === 'existing-card'}
                        onChange={({ target }) => setPaymentMethod(target.value)}
                        type="radio"
                      />
                    </Col>
                  </Row>
                  <hr />
                </>
              )}
              <Row>
                <Col xs={12}>
                  <CustomInput
                    label={
                      <Flex align="center" className="mb-2 fs-1">
                        Credit Card
                      </Flex>
                    }
                    id="credit-card"
                    value="credit-card"
                    checked={paymentMethod === 'credit-card'}
                    onChange={({ target }) => setPaymentMethod(target.value)}
                    type="radio"
                  />
                </Col>
                <Col xs={12} className="pl-4">
                  <Row>
                    <Col sm={8}>
                      <Row className="align-items-center">
                        <Col>
                          <FormGroup>
                            <input
                              type="text"
                              value={cardNumber}
                              className={errors.number ? 'form-control form-control-is-invalid' : 'form-control'}
                              placeholder="•••• •••• •••• ••••"
                              onChange={handleOnCardNumberChange}
                              disabled={disableCardFields}
                            />
                            {/* {errors.number && (
                              <div className="text-danger">
                                <small>{errors.number.message}</small>
                              </div>
                            )} */}
                          </FormGroup>
                        </Col>
                      </Row>
                      <Row className="align-items-center">
                        <Col xs={4}>
                          <FormGroup>
                            <Label>Month</Label>
                            <input
                              type="text"
                              {...register('month')}
                              className={errors.month ? 'form-control form-control-is-invalid' : 'form-control'}
                              placeholder="MM"
                              maxLength={2}
                              disabled={disableCardFields}
                            />
                          </FormGroup>
                        </Col>
                        <Col xs={4}>
                          <FormGroup>
                            <Label>Year</Label>
                            <input
                              type="text"
                              {...register('year')}
                              className={errors.year ? 'form-control form-control-is-invalid' : 'form-control'}
                              placeholder="YYYY"
                              maxLength={4}
                              disabled={disableCardFields}
                            />
                          </FormGroup>
                        </Col>
                        <Col xs={4}>
                          <FormGroup>
                            <Label>CVV</Label>
                            <input
                              type="text"
                              {...register('verification_value')}
                              className={
                                errors.verification_value ? 'form-control form-control-is-invalid' : 'form-control'
                              }
                              placeholder="123"
                              maxLength={3}
                              disabled={disableCardFields}
                            />
                          </FormGroup>
                        </Col>
                      </Row>
                      <Row>
                        <Col>
                          <FormGroup check>
                            <Label check>
                              <Input
                                type="checkbox"
                                checked={saveThisCard}
                                onChange={() => setSaveThisCard(!saveThisCard)}
                              />{' '}
                              Reuse this card for future purchases
                            </Label>
                          </FormGroup>
                        </Col>
                      </Row>
                    </Col>
                    <div className="col-4 text-center pt-2 d-none d-sm-block">
                      <div className="rounded p-2 mt-3 bg-100">
                        <div className="text-uppercase fs--2 font-weight-bold">We Accept</div>
                        <img src={iconPaymentMethodsGrid} alt="" width="120" />
                      </div>
                    </div>
                  </Row>
                </Col>
              </Row>
              <hr />
              <Row className="mt-3">
                <Col xs={12}>
                  <CustomInput
                    label={<img className="pull-right" src={iconPaypalFull} height="20" alt="" />}
                    id="paypal"
                    value="paypal"
                    checked={paymentMethod === 'paypal'}
                    onChange={({ target }) => setPaymentMethod(target.value)}
                    type="radio"
                  />
                </Col>
              </Row>
              {/* <hr className="border-dashed my-5" /> */}
              <Row>
                <Col className="pl-lg-4 pl-xl-2 pl-xxl-5 text-center">
                  <hr className="border-dashed d-block d-md-none d-xl-block d-xxl-none my-4" />
                  <div className="fs-2 font-weight-semi-bold">
                    Total:{' '}
                    <span className="text-primary">
                      {currency}
                      {payableTotal}
                    </span>
                  </div>
                  <Button type="submit" color="primary" className="mt-3 px-5" disabled={!payableTotal || submitting}>
                    Confirm &amp; Pay
                  </Button>
                  <p className="fs--1 mt-3 mb-0">
                    By clicking <strong>Confirm &amp; Pay </strong>button you agree to JamKazam's{' '}
                    <a href="https://www.jamkazam.com/corp/terms" target='_blank'>Terms Of Service</a>, including the <a href="https://www.jamkazam.com/corp/terms#purchasing-jamtracks">JamTracks Purchase Terms</a>.
                  </p>
                </Col>
              </Row>
            </CardBody>
          </Card>
        </form>
      </ContentWithAsideLayout>
    </div>
  );
};

export default JKCheckout;
