import React, { useState } from "react";
import Col from "react-bootstrap/Col";
import Form from "react-bootstrap/Form";
import Row from "react-bootstrap/Row";
import Button from "../../pageElements/Button";
import { useParams } from "react-router-dom";
import { db, auth } from "../../firebase";
import { createUserWithEmailAndPassword } from "firebase/auth";
import { useNavigate } from "react-router-dom";
import Toggle from "../../pageElements/Toggle";
import TextInput from "../../pageElements/TextInput";
import { v4 as uuidv4 } from "uuid";
import { collection, setDoc, doc } from "firebase/firestore";
import LoadingSpinner from "../../pageElements/LoadingSpinner";
import { splitEvery } from "../../Utils/Array";
import { ArrowLeftSquare, ArrowRightSquare } from "react-bootstrap-icons";
import {
  getFormDataDefaults,
  getValidatedFormData,
  handleFormDataChange,
  isFormDataHasErrors,
} from "../../Utils/Form";
import { objectMap } from "../../Utils/Object";
import {
  signupFields,
  stateDataValues,
} from "../../Constants/Fields/SignupFields";
import { paymentfields } from "../../Constants/Fields/PaymentFields";
import { signupRadioFields } from "../../Constants/Fields/RadioFields";
import PaymentModal from "../Modals/PaymentModal";
import Radio from "../../pageElements/Radio";
import "../../styles/signup.scss";
import Stripe from "stripe";
import { stripeApiKey, marchEmailPrm } from "../../secrets";
import ConfirmModal from "../Modals/ConfirmModal";

const SignupPage = () => {
  const { isUpgrade, currentPlan } = useParams();
  const navigate = useNavigate();
  const [notice, setNotice] = useState("");
  const fieldsChunkSize = 2;
  const [isBusy, setIsBusy] = useState(false);
  const [data, setData] = useState(getFormDataDefaults(signupFields));
  const [paymentData, setPaymentData] = useState(
    getFormDataDefaults(paymentfields)
  );
  const [showPaymentModal, setShowPaymentModal] = useState(false);

  const [showSelectPlan, setShowSelectPlan] = useState(
    isUpgrade ? true : false
  );

  //const [showSelectPlan, setShowSelectPlan] = useState(true);

  const [activeRadioOption, setActiveRadioOption] = useState("partner");
  const [selectedPlan, setSelectedPlan] = useState([signupRadioFields[2]]);
  const stripe = new Stripe(stripeApiKey);
  const apiUrl =
    process.env.NODE_ENV === "development"
      ? process.env.REACT_APP_API_DEV
      : process.env.REACT_APP_API_PROD;
  const [showAddAccount, setShowAddAccount] = useState(false);
  const [numberOfAccountsToAdd, setNumberOfAccountsToAdd] = useState();
  const [showPromoModal, setShowPromoModal] = useState(false);
  const [issueText, setIssueText] = useState("");
  const [isAnnual, setIsAnnual] = useState(1);
  const [valX, setValX] = useState(1);
  const [valY, setValY] = useState(4);
  const userAgent = window.navigator.userAgent;

  const handleChangeInput = (e, name) => {
    const newData = handleFormDataChange(e, name, data, signupFields);
    if (newData !== null) {
      setData(newData);
    }
  };

  const handleConfirmPromoCode = (code) => {
    if (code === marchEmailPrm) {
      handlePromoSignup(code);
    }
  };

  const handleChangeAccountSelect = (e, name) => {
    const num = e.target.value;
    const temp = Number(num);
    setNumberOfAccountsToAdd(temp);
  };

  const handleChangePaymentInput = (e, name) => {
    const newPaymentData = handleFormDataChange(
      e,
      name,
      paymentData,
      paymentfields
    );
    if (newPaymentData !== null) {
      setPaymentData(newPaymentData);
    }
  };

  const handleChangeRadioInput = (value) => {
    const tempPlan = signupRadioFields.filter((plan) => {
      if (plan.value === value) {
        return plan;
      }
    });

    setSelectedPlan(tempPlan);
    setActiveRadioOption(tempPlan[0].value);
  };
  console.log("selectedPlan in signup page", selectedPlan);
  const handleLeftArrowClick = () => {
    if (valX == 0) {
      return;
    } else {
      const tempx = valX - 1;
      const tempy = valY - 1;
      setValX(tempx);
      setValY(tempy);
    }
  };

  const handleRightArrowClick = () => {
    if (valX == 1) {
      return;
    } else {
      const tempx = valX + 1;
      const tempy = valY + 1;
      setValX(tempx);
      setValY(tempy);
    }
  };

  const vals = [
    [1, 2, 3, 4, 5, 6, 7, 8],
    [1, 2],
  ];
  const selectAdditionalAccountValues =
    selectedPlan[0].value === "partner" ? vals[1] : vals[0];

  const validateUserData = () => {
    const newData = getValidatedFormData(data, signupFields);
    const hasErrors = isFormDataHasErrors(newData);
    setData(newData);
    return hasErrors ? null : objectMap(({ value }) => value, newData);
  };

  const validatePaymentData = () => {
    const newPaymentData = getValidatedFormData(paymentData, paymentfields);
    const hasErrors = isFormDataHasErrors(newPaymentData);
    setPaymentData(newPaymentData);
    return hasErrors ? null : objectMap(({ value }) => value, newPaymentData);
  };

  async function saveLeadData(dataValues) {
    const signupId = uuidv4();
    const {
      firstName,
      lastName,
      firm,
      telephone,
      streetAddress,
      city,
      state,
      zipCode,
      barNumber,
      practiceArea,
      email,
    } = dataValues;

    const userData = {
      firstName,
      lastName,
      firm,
      telephone,
      streetAddress,
      city,
      state,
      zipCode,
      barNumber,
      practiceArea,
      email,
      signupId,
    };

    try {
      const collecRef = collection(db, "signupLeads");
      await setDoc(doc(collecRef, `${signupId}`), userData);
    } catch (error) {
      console.log(`Error saving new user to db: ${error}`);
    }
  }

  async function saveUserData(
    authId,
    dataValues,
    customerId,
    subscriptionCreated,
    subscriptionPeriodStart,
    subscriptionPeriodEnd,
    subscriptionId,
    isPromotionalMebership
  ) {
    const appUserId = uuidv4();
    const firmId = uuidv4();
    const fbAuthUid = authId;
    let plan = selectedPlan;
    let docsAllowedPerMonth;
    if (isPromotionalMebership === true) {
      docsAllowedPerMonth = 1;
      subscriptionId = uuidv4();
      plan = "promo plan";
    } else {
      docsAllowedPerMonth = selectedPlan[0].docsAllowedPerMonth;
    }

    const docsGenerated = 0;

    const {
      firstName,
      lastName,
      firm,
      telephone,
      streetAddress,
      city,
      state,
      zipCode,
      barNumber,
      practiceArea,
      email,
    } = dataValues;

    const userState = stateDataValues.filter((value) => {
      if (value.name === state) return value;
    });

    const userData = {
      docsAllowedPerMonth,
      docsGenerated,
      appUserId,
      fbAuthUid,
      firmId,
      firstName,
      lastName,
      firm,
      telephone,
      streetAddress,
      city,
      state: userState,
      zipCode,
      barNumber,
      practiceArea,
      email,
      isPromotionalMebership,
      customerId: customerId,
      subscriptionId: subscriptionId,
      subscriptionPlan: plan,
      subscriptionCreated: subscriptionCreated,
      subscriptionPeriodStart: subscriptionPeriodStart,
      subscriptionPeriodEnd: subscriptionPeriodEnd,
    };

    try {
      const usersRef = collection(db, "users");
      const res = await setDoc(doc(usersRef, fbAuthUid), userData);
      return res;
    } catch (error) {
      console.log(`Error saving new user to db: ${error}`);
    }
  }

  const handleProceedToPayment = (e) => {
    e.preventDefault();
    setShowPaymentModal(true);
  };

  const handleAdd = () => {
    setShowAddAccount(!showAddAccount);
    setShowPaymentModal(true);
  };

  const scrollToLowerPanel = () => {
    let target = document.getElementById("scroll-target-id");
    if (target) {
      window.scrollTo({
        top: target.offsetTop,
        behavior: "smooth",
      });
    }
  };

  const handleCancelModal = () => {
    setShowPromoModal(!showPromoModal);
    setShowSelectPlan(true);
    setTimeout(scrollToLowerPanel, 93);
  };

  const handleOpenSelectPlan = (e) => {
    e.preventDefault();
    if (isBusy) {
      return;
    }

    const dataValues = validateUserData();
    if (dataValues === null) {
      return;
    }

    saveLeadData(dataValues);
    setShowPromoModal(!showPromoModal);
    setShowSelectPlan(true);
  };

  const handleToggle = (val) => setIsAnnual(val);

  const handleAddAccounts = () => {
    setShowAddAccount(!showAddAccount);
  };

  const handleCancelAdd = () => {
    setShowAddAccount(!showAddAccount);
  };

  // ******************** STRIPE PAYMENT API CALL ******************** //
  async function handleStripeAuthorization(
    paymentDataValues,
    customerDataValues
  ) {
    const additionalAccounts = numberOfAccountsToAdd
      ? numberOfAccountsToAdd
      : 0;
    let error = false;
    let subscriptionId = null;
    let customerId = null;

    const token = await stripe.tokens.create({
      card: {
        number: paymentDataValues.cardNumber,
        exp_month: paymentDataValues.cardExpirationMonth,
        exp_year: paymentDataValues.cardExpirationYear,
        cvc: paymentDataValues.cardCvvCode,
        name:
          paymentDataValues.cardFirstName +
          " " +
          paymentDataValues.cardLastName,
      },
    });

    const type = selectedPlan[0].value ? selectedPlan[0].value : null;
    const tempAnnual =
      type === "ofCounsel" ? false : isAnnual === 1 ? true : false;

    try {
      let response;
      let data;

      if (type === "ofCounsel") {
        response = await fetch(`${apiUrl}/new-payment-intent`, {
          method: "POST",
          headers: {
            "Content-Type": "application/json",
            "User-Agent": userAgent,
          },
          body: JSON.stringify({
            planType: type,
            additionalAccounts: 0,
            isAnnual: false,
            customerData: {
              email: customerDataValues.email,
              name: `${customerDataValues.firstName} ${customerDataValues.lastName}`,
            },
            token,
          }),
        });
        data = await response.json();
      } else {
        response = await fetch(`${apiUrl}/create-subscription`, {
          method: "POST",
          headers: {
            "Content-Type": "application/json",
          },
          body: JSON.stringify({
            planType: type,
            additionalAccounts: additionalAccounts,
            isAnnual: tempAnnual,
            customerData: {
              email: customerDataValues.email,
              name: `${customerDataValues.firstName} ${customerDataValues.lastName}`,
            },
            token,
          }),
        });
        data = await response.json();
      }
      return {
        data,
      };
    } catch (error) {
      console.log(error);
      return error;
    }
  }

  // ******************** END STRIPE PAYMENT API CALL ******************** //
  const handleSignup = async (e) => {
    const paymentDataValues = validatePaymentData();

    if (paymentDataValues === null) {
      return;
    }

    let dataValues = validateUserData();
    if (dataValues === null) {
      return;
    }
    console.log("dataValues", dataValues);
    //const planType = determinePlan(isAnnual, activeRadioOption);

    if (paymentDataValues && dataValues) {
      setShowPaymentModal(false);
      window.scrollTo({ top: 0, behavior: "smooth" });
      setIsBusy(true);

      try {
        const data = await handleStripeAuthorization(
          paymentDataValues,
          dataValues
        );

        const customerId = data?.data?.customerId;
        const subscriptionCreated = data?.data?.subscriptionCreated;
        const subscriptionPeriodStart = data?.data?.subscriptionPeriodStart;
        const subscriptionPeriodEnd = data?.data?.subscriptionPeriodEnd;
        const subscriptionId = data?.data?.subscriptionId;

        if (data === undefined || customerId === undefined) {
          setIsBusy(false);
          setNotice("Sorry, something went wrong. Please try again.");
          return;
        } else {
          const userCredential = await createUserWithEmailAndPassword(
            auth,
            dataValues?.email,
            dataValues?.password
          );

          const user = userCredential?.user;
          dataValues = { ...dataValues, ...data };
          const isPromotionalMebership = false;
          const res = await saveUserData(
            user?.uid,
            dataValues,
            customerId,
            subscriptionCreated,
            subscriptionPeriodStart,
            subscriptionPeriodEnd,
            subscriptionId,
            isPromotionalMebership
          );
          setIsBusy(false);
          navigate("/dashboard");
        }
      } catch (error) {
        console.log("Error handling request", error);
        setIsBusy(false);
        setNotice("Sorry, something went wrong. Please try again.");
      }
    }
  };

  const handlePromoSignup = async (code) => {
    let dataValues = validateUserData();
    if (dataValues === null) {
      return;
    }

    if (dataValues) {
      window.scrollTo({ top: 0, behavior: "smooth" });
      setIsBusy(true);

      try {
        const customerId = `${uuidv4()}-promo`;
        const today = new Date();
        const subscriptionCreated = today;
        const subscriptionPeriodStart = today;
        const subscriptionPeriodEnd = "it ends whatever"; //today.setDate(today.getDate() + 30);
        const subscriptionId = uuidv4();

        const userCredential = await createUserWithEmailAndPassword(
          auth,
          dataValues.email,
          dataValues.password
        );

        const user = userCredential.user;
        dataValues = { ...dataValues };

        const isPromotionalMebership = true;
        const res = await saveUserData(
          user.uid,
          dataValues,
          customerId,
          subscriptionCreated,
          subscriptionPeriodStart,
          subscriptionPeriodEnd,
          subscriptionId,
          isPromotionalMebership
        );
        setIsBusy(false);
        navigate("/dashboard");
      } catch (error) {
        console.log("Error handling request", error, error.message);
        setIsBusy(false);
        setNotice("Sorry, something went wrong. Please try again.");
      }
    }
  };

  const showNoticeOnPage = "" !== notice && !showPaymentModal;
  const addAccountCopy =
    selectedPlan[0]?.value === "seniorPartner"
      ? "Add up to eight"
      : "Add up to two";
  const showAddAccountBtn =
    selectedPlan[0].value === "seniorPartner" ||
    selectedPlan[0].value === "partner";

  const signupForm = (
    <div className="signup-sub-container">
      {showNoticeOnPage ? (
        <>
          <br></br>
          <div className="alert alert-danger" role="alert">
            {notice}
          </div>
        </>
      ) : (
        <></>
      )}
      <div className="signup-header">
        <h1 className="signup-header-text">Create A Novodraft Account</h1>
        {!isUpgrade ? (
          <h5 className="signup-header-text trial">
            Create an account to start a free trial - save time and draft
            smarter
          </h5>
        ) : (
          <></>
        )}
      </div>
      <Form className="signup-form">
        {splitEvery(
          Object.keys(signupFields).slice(0, -2),
          fieldsChunkSize
        ).map((names, j) => (
          <Row key={`row${j}`} className="signup-form-row">
            {names.map((name, i) => (
              <Col
                key={`${name}${i + fieldsChunkSize * j}`}
                className="mb-3 signup-form-column"
              >
                <TextInput
                  name={name}
                  value={data[name].value}
                  onChange={(e) => handleChangeInput(e, name)}
                  error={data[name].error}
                  message={data[name].message}
                  label={
                    data[name].value.length === 0
                      ? signupFields[name].label
                      : ""
                  }
                  type={signupFields[name].type}
                  values={signupFields[name].values}
                  disabled={isBusy}
                  inputClassName="mobile-text-input"
                />
              </Col>
            ))}
          </Row>
        ))}
        <Row className="signup-password-row">
          <Col className="mb-3">
            <TextInput
              id="signupPassword"
              type="password"
              label={
                data.password.value.length === 0
                  ? signupFields.password.label
                  : ""
              }
              value={data.password.value}
              error={data.password.error}
              message={data.password.message}
              onChange={(e) => handleChangeInput(e, "password")}
              disabled={isBusy}
            />
          </Col>
        </Row>
        <Row className="signup-password-row">
          <Col className="mb-3">
            <TextInput
              id="confirmPassword"
              type="password"
              label={
                data.confirmPassword.value.length === 0
                  ? signupFields.confirmPassword.label
                  : ""
              }
              value={data.confirmPassword.value}
              error={data.confirmPassword.error}
              message={data.confirmPassword.message}
              onChange={(e) => handleChangeInput(e, "confirmPassword")}
              disabled={isBusy}
            />
          </Col>
        </Row>
      </Form>
      <div className="signup-button-box">
        <Button
          className="primary-button signup-proceed"
          type="button"
          size="lg"
          onClick={handleOpenSelectPlan}
          disabled={isBusy}
          labelText="Select A Plan"
        />
      </div>
    </div>
  );
  const disableIndex =
    currentPlan === "associate" ? 1 : currentPlan === "partner" ? 2 : 0;

  return (
    <div className="signup-super-container">
      {isBusy ? <LoadingSpinner message={""} loaderType="MoonLoader" /> : null}
      {!isUpgrade && !isBusy ? signupForm : <></>}
      {showSelectPlan && !isBusy ? (
        <div className="select-plan-container" id="select-plan-scid">
          <div className="select-plan-header">
            <div className="plan-header-right">
              <h5 className="signup-subheader-text">
                Select a subscription plan
              </h5>
              <p className="subscribe-header-sub">
                ← Click left/right for more options →
              </p>
            </div>
            <div className="plan-header-left">
              <div className="select-toggle-box">
                <p className="select-billing-text">Billed annually</p>
                <Toggle value={isAnnual} onClick={handleToggle} />
                <p className="select-billing-text">Billed montly</p>
              </div>
            </div>
          </div>

          <div className="radio-group-super">
            <div className="toggle-arrow-box">
              <ArrowLeftSquare
                className="arrow-left-toggle"
                color="#f7c697"
                size="30px"
                onClick={handleLeftArrowClick}
                style={{ marginTop: "-25px" }}
              />
            </div>
            <div className="radio-group-box">
              {signupRadioFields?.slice(valX, valY).map((option, index) => (
                <div className="signup-radio-container">
                  <Radio
                    onClick={handleChangeRadioInput}
                    value={option.value}
                    name={option.name}
                    description={option.description}
                    details={option.details}
                    activeRadioOption={activeRadioOption}
                    price={option.pricing}
                    isAnnual={isAnnual}
                    isUpgrade={index < disableIndex ? true : false}
                    disabled={index < disableIndex ? true : false}
                    currentPlan={currentPlan}
                    parentIndex={index}
                  />
                </div>
              ))}
            </div>
            <div className="toggle-arrow-box">
              <ArrowRightSquare
                className="arrow-left-toggle"
                color="#f7c697"
                size="30px"
                onClick={handleRightArrowClick}
                style={{ marginTop: "-25px" }}
              />
            </div>
          </div>
          {showAddAccount && !isBusy ? (
            <div className="show-addaccount-wrapper">
              <div className="show-addaccount-container">
                <div className="plan-header-right-lower">
                  <h5 className="signup-button-wrapper-text">
                    Add additional accounts
                  </h5>
                  <p className="signup-accounts-info">
                    User profiles will be setup later
                  </p>
                </div>
                <div className="signup-select-wrapper">
                  <div className="signup-select-box">
                    <select
                      id="accountNo"
                      className={`form-select`}
                      value={numberOfAccountsToAdd}
                      name={"addAccountsSelect"}
                      onChange={(e) =>
                        handleChangeAccountSelect(e, "addAccountsSelect")
                      }
                    >
                      <option
                        id="ddlProducts"
                        className={`select-option`}
                        value=""
                      ></option>
                      {selectAdditionalAccountValues.map((item, i) => (
                        <option
                          id="ddlProducts"
                          className={`select-option`}
                          key={`item${i}`}
                        >
                          {item}
                        </option>
                      ))}
                    </select>
                  </div>
                </div>
                <div className="details-foo-box ">
                  <Button
                    className="secondary-button"
                    onClick={handleCancelAdd}
                    labelText="Cancel"
                  />
                  <div className="upload-button-box">
                    <Button
                      className="p-2 mr-2 primary-button signup-proceed-btn"
                      onClick={handleAdd}
                      labelText="Proceed To Payment"
                    />
                  </div>
                </div>
              </div>
            </div>
          ) : (
            <></>
          )}
          <div className="signup-button-box">
            {!showAddAccount && !isBusy ? (
              <>
                {showAddAccountBtn ? (
                  <Button
                    className="secondary-button add-account-button"
                    type="button"
                    size="lg"
                    onClick={handleAddAccounts}
                    disabled={isBusy}
                    labelText="Add Account(s)"
                    style={{ marginTight: "12px;" }}
                  />
                ) : (
                  <></>
                )}

                <Button
                  className="primary-button signup-proceed"
                  type="button"
                  size="lg"
                  onClick={handleProceedToPayment}
                  disabled={isBusy}
                  labelText="Proceed to Payment"
                />
              </>
            ) : (
              <></>
            )}
          </div>
        </div>
      ) : (
        <></>
      )}
      {showPaymentModal ? (
        <PaymentModal
          key="modal-one-xc"
          paymentData={paymentData}
          paymentfields={paymentfields}
          setShowPaymentModal={setShowPaymentModal}
          handleChangePaymentInput={handleChangePaymentInput}
          handleSignup={handleSignup}
          notice={notice}
          setNotice={setNotice}
          selectedPlan={selectedPlan}
          isAnnual={isAnnual === 1 ? true : false}
          numberOfAccountsToAdd={numberOfAccountsToAdd}
          fieldsChunkSize={2}
        />
      ) : (
        <></>
      )}
      {showPromoModal ? (
        <ConfirmModal
          titleText="Enter Promo Code"
          onCancel={handleCancelModal}
          buttonLabelText="Enter Code"
          isPromoModal={true}
          issueText={issueText}
          setIssueText={setIssueText}
          onConfirm={handleConfirmPromoCode}
          cancelButtonText="I don't have a code"
        />
      ) : (
        <></>
      )}
    </div>
  );
};

export default SignupPage;
