import React, { useState } from "react";
import { NextPage, GetStaticProps, GetStaticPaths } from "next";
import Head from "next/head";
import { useRouter } from "next/router";
import { ISubmitEvent } from "@rjsf/core";
import { toast } from "react-toastify";
import axios from "axios";
import useSWR, { mutate } from "swr";
import { Signup, SignupForm } from "@models/Signup";
import SignupApi from "@api/signupApi";
import SignUpPageView from "@views/SignUpPage/SignUpPageView";
import PageWrapper from "@views/common/PageWrapper";
import LoadingView from "@views/common/LoadingView";
import noop from "@utils/noop";
import NotFoundPage from "@pages/404";
import { v4 as uuid } from "uuid";

type InitialProps = {
  initialForm: SignupForm;
};

const FORM_URL = `${process.env.NEXT_PUBLIC_API_URL}/signupForm/`;

const SignUpPage: NextPage<InitialProps> = ({ initialForm }) => {
  const router = useRouter();
  const id = String(initialForm?.id ?? "");
  const SUBMIT_ID = uuid(); // Submission key, generated on page refresh
  const URL = `${FORM_URL}${id}/`;
  const { data: signupForm, error } = useSWR<SignupForm>(URL, (url) => axios.get(url).then((res) => res.data), { fallbackData: initialForm });

  if (error) {
    console.error(error);
  }

  // TODO: Shows LoadingView on client-side fetch error. Maybe something else preferred?
  if (router.isFallback || error) {
    return <LoadingView />;
  }

  if (!signupForm) {
    return (
      <NotFoundPage />
    );
  }

  const onSubmit = async ({ formData }: ISubmitEvent<string>) => {
    const payload: Signup = {
      submit_id: SUBMIT_ID, // This is for preventing duplicate requests; NOT RELATED TO THE SIGNUP ID IN DATABASE
      signupForm_id: signupForm.id,
      answer: formData,
    };

    try {
      await SignupApi.createSignup(payload);
      toast.success("Sign-up submitted successfully 😎");
      mutate(URL);
    } catch (err) {
      console.error(err);
      toast.error("Uh oh! Sign-up failed! 😟");
    }
  };

  return (
    <>
      <Head>
        <link rel="canonical" href={`${process.env.NEXT_PUBLIC_SITE_URL}/signup/${signupForm.id}`} />
      </Head>
      <PageWrapper>
        <SignUpPageView
          signUpForm={signupForm}
          formData={{}}
          onChange={noop}
          onSubmit={onSubmit}
        />
      </PageWrapper>
    </>
  );
};

export const getStaticPaths: GetStaticPaths = async () => {
  const allForms = await SignupApi.getForms();
  const paths = allForms.map((e: SignupForm) => ({
    params: {
      id: String(e.id),
    },
  }
  ));
  return {
    paths,
    fallback: true,
  };
};

export const getStaticProps: GetStaticProps<InitialProps> = async ({ params }) => {
  const { id } = params;
  let notFound = false;
  let initialForm: SignupForm;
  try {
    initialForm = await SignupApi.getForm(Number(id));
  } catch {
    notFound = true;
  }
  return {
    props: {
      initialForm,
    },
    revalidate: 10, // Required for deleting hidden pages
    notFound,
  };
};

export default SignUpPage;
