import debounce from "lodash/debounce";
import { GetServerSidePropsContext } from "next";
import { getCsrfToken } from "next-auth/react";
import React, { SyntheticEvent } from "react";

import { getSession } from "@lib/auth";
import { useLocale } from "@lib/hooks/useLocale";

import { EmailField } from "@components/form/fields";
import { HeadSeo } from "@components/seo/head-seo";
import Button from "@components/ui/Button";

export default function ForgotPassword({ csrfToken }: { csrfToken: string }) {
  const { t, i18n } = useLocale();
  const [loading, setLoading] = React.useState(false);
  const [error, setError] = React.useState<{ message: string } | null>(null);
  const [success, setSuccess] = React.useState(false);
  const [email, setEmail] = React.useState("");

  const handleChange = (e: SyntheticEvent) => {
    const target = e.target as typeof e.target & { value: string };
    setEmail(target.value);
  };

  const submitForgotPasswordRequest = async ({ email }: { email: string }) => {
    try {
      const res = await fetch("/api/auth/forgot-password", {
        method: "POST",
        body: JSON.stringify({ email: email, language: i18n.language }),
        headers: {
          "Content-Type": "application/json",
        },
      });

      const json = await res.json();
      if (!res.ok) {
        setError(json);
      } else if ("resetLink" in json) {
        window.location = json.resetLink;
      } else {
        setSuccess(true);
      }

      return json;
    } catch (reason) {
      setError({ message: t("unexpected_error_try_again") });
    } finally {
      setLoading(false);
    }
  };

  const debouncedHandleSubmitPasswordRequest = debounce(submitForgotPasswordRequest, 250);

  const handleSubmit = async (e: SyntheticEvent) => {
    e.preventDefault();

    if (!email) {
      return;
    }

    if (loading) {
      return;
    }

    setLoading(true);
    setError(null);
    setSuccess(false);

    await debouncedHandleSubmitPasswordRequest({ email });
  };

  const Success = () => {
    return (
      <div className="space-y-6">
        <h2 className="mt-6 text-3xl font-extrabold text-center text-gray-900">{t("done")}</h2>
        <p>{t("check_email_reset_password")}</p>
        {error && <p className="text-red-600">{error.message}</p>}
      </div>
    );
  };

  return (
    <div className="flex flex-col justify-center min-h-screen py-12 bg-gray-50 sm:px-6 lg:px-8">
      <HeadSeo title={t("forgot_password")} description={t("request_password_reset")} />
      <div className="mt-8 sm:mx-auto sm:w-full sm:max-w-md">
        <div className="px-4 pt-3 pb-8 mx-2 space-y-6 bg-white rounded-lg shadow sm:px-10">
          {success && <Success />}
          {!success && (
            <>
              <div className="space-y-6">
                <h2 className="mt-6 text-3xl font-extrabold text-center text-gray-900 font-cal">
                  {t("forgot_password")}
                </h2>
                <p className="text-sm text-gray-500">{t("reset_instructions")}</p>
                {error && <p className="text-red-600">{error.message}</p>}
              </div>
              <form className="space-y-6" onSubmit={handleSubmit} action="#">
                <input name="csrfToken" type="hidden" defaultValue={csrfToken} hidden />

                <EmailField
                  onChange={handleChange}
                  id="email"
                  name="email"
                  label={t("email_address")}
                  placeholder="john.doe@example.com"
                  required
                />
                <div className="space-y-2">
                  <Button
                    className="justify-center w-full"
                    type="submit"
                    disabled={loading}
                    aria-label={t("request_password_reset")}
                    loading={loading}>
                    {t("request_password_reset")}
                  </Button>

                  <Button
                    href="/auth/login"
                    color="minimal"
                    role="button"
                    aria-label={t("login_instead")}
                    className="justify-center w-full">
                    {t("login_instead")}
                  </Button>
                </div>
              </form>
            </>
          )}
        </div>
      </div>
    </div>
  );
}

ForgotPassword.getInitialProps = async (context: GetServerSidePropsContext) => {
  const { req, res } = context;
  const session = await getSession({ req });

  if (session) {
    res.writeHead(302, { Location: "/" });
    res.end();
    return;
  }

  return {
    csrfToken: await getCsrfToken(context),
  };
};
