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 { db, auth } from "../../firebase";
import { createUserWithEmailAndPassword } from "firebase/auth";
import { Link, useNavigate } from "react-router-dom";
import TextInput from "../../pageElements/TextInput";
import { v4 as uuidv4 } from "uuid";
import { collection, setDoc, doc } from "firebase/firestore";
import { splitEvery } from "../../Utils/Array";
import {
  getFormDataDefaults,
  getValidatedFormData,
  handleFormDataChange,
  isFormDataHasErrors,
} from "../../Utils/Form";
import { objectMap } from "../../Utils/Object";
import { signupfields } from "../../Constants/Fields/SignupFields";
import { paymentfields } from "../../Constants/Fields/PaymentFields";
import PaymentModal from "../Modals/PaymentModal";
import "../../styles/signup.scss";

const SignupPage = () => {
  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 modalText = "Description of monthly and annual subscriptions";

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

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

  const validateData = () => {
    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 saveUserData(authId, dataValues) {
    const appUserId = uuidv4();
    const firmId = uuidv4();
    const fbAuthUid = authId;
    const {
      firstName,
      lastName,
      firm,
      telephone,
      streetAddress,
      city,
      state,
      zipCode,
      barNumber,
      practiceArea,
      email,
    } = dataValues;

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

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

  const handleProceedToPayment = (e) => {
    e.preventDefault();

    if (isBusy) {
      return;
    }

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

    setShowPaymentModal(true);
  };

  async function handleStripeAuthorization(paymentDataValues) {
    // Do: calls to Stripe API
    // if success, return some truthy value or
    // handle failure in handleSignup
  }

  const handleSignup = async (e) => {
    e.preventDefault();
    const paymentDataValues = validatePaymentData();
    if (paymentDataValues === null) {
      return;
    }

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

    setIsBusy(true);
    const paymentSuccess = handleStripeAuthorization(paymentDataValues);
    if (paymentSuccess) {
      try {
        const userCredential = await createUserWithEmailAndPassword(
          auth,
          dataValues.email,
          dataValues.password
        );
        const user = userCredential.user;
        await saveUserData(user.uid, dataValues);
        navigate("/");
      } catch (error) {
        setIsBusy(false);
        setNotice(
          error.message || "Sorry, something went wrong. Please try again."
        );
      }
    } else {
      //handle payment failure
    }
  };

  return (
    <div className="signup-super-container">
      <div className="signup-sub-container">
        <div className="signup-header">
          <h1 className="signup-header-text">Create a Novodraft account</h1>
        </div>
        <Form className="signup-form">
          {splitEvery(
            Object.keys(signupfields).slice(0, -2),
            fieldsChunkSize
          ).map((names, j) => (
            <Row key={`row${j}`}>
              {names.map((name, i) => (
                <Col key={`${name}${i + fieldsChunkSize * j}`} className="mb-3">
                  <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}
                  />
                </Col>
              ))}
            </Row>
          ))}
          <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>
            <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={handleProceedToPayment}
            disabled={isBusy}
            labelText="Proceed to Payment"
          />
          <div className="mt-3">
            <span>
              <Link to="/login">Go to login</Link>
            </span>
          </div>
        </div>

        {"" !== notice && (
          <>
            <br></br>
            <div className="alert alert-danger" role="alert">
              {notice}
            </div>
          </>
        )}
      </div>
      {showPaymentModal ? (
        <PaymentModal
          key="modal-one-xc"
          paymentData={paymentData}
          paymentfields={paymentfields}
          setShowPaymentModal={setShowPaymentModal}
          handleChangePaymentInput={handleChangePaymentInput}
          handleSignup={handleSignup}
          modalText={modalText}
        />
      ) : (
        <></>
      )}
    </div>
  );
};

export default SignupPage;
