"use client";

import { Controller, useForm } from "react-hook-form";
import { FaChevronRight } from "react-icons/fa6";
import { useRouter, useSearchParams } from "next/navigation";
import { useEffect, useRef, useState } from "react";
import { useDisclosure } from "@nextui-org/react";
import { parsePhoneNumber } from "awesome-phonenumber";
import { Turnstile, TurnstileInstance } from "@marsidev/react-turnstile";
import { useFormState, useFormStatus } from "react-dom";

import { AUTOCOMPLETE_VALUES } from "@/constants/signup-auto-complete-mapping";
import StepHeading from "@/components/pages/participant/sign-up/common/step-heading";
import Button from "@/components/common/button";
import { CreateNewAccountData } from "@/types/signup/user-signup-types";
import { INTERNAL_PAGES } from "@/constants/pages-mapping/internal-pages-mapping";
import DividerLabel from "@/components/pages/participant/sign-up/common/divider-label";
import PasswordInput from "@/components/common/password-input";
import TextInput from "@/components/common/text-input";
import CheckboxSingle from "@/components/common/single-checkbox";
import { Option } from "@/types/options/options-data-types";
import { COOKIE_SIGNUP_IN_PROGRESS } from "@/constants/cookie-mapping";
import { storeCookie } from "@/utils/cookie-utils";
import BlockedSignup from "@/components/pages/participant/sign-up/common/blocked-signup";
import { initiateSignUpProcess } from "@/services/participant/signup/signup-actions";
import Alert from "@/components/common/alert";
import FormError from "@/components/common/form-error";
import DateInput from "@/components/common/date-input";
import ConfirmModal from "@/components/pages/participant/sign-up/common/confirm-modal";
import { generateAndSendOTP } from "@/services/global/request-sms-otp-actions";
import { ALLOWED_COUNTRY_CALLING_CODES } from "@/constants/allowed-countries";
import BlockedSignupModal from "@/components/pages/participant/sign-up/common/blocked-signup-modal";
import { AIRTABLE_INTERNATIONAL } from "@/constants/signup-form-constants";
import FinalActionsFooter from "@/components/pages/participant/sign-up/common/final-actions-footer";
import type { ParticipantSignupContent } from "@/lib/participant-signup-ghost-content";

type CreateNewAccountProps = {
  isSignupBlocked: boolean;
  userCountry: string;
  userCountryCode: string;
  hero: ParticipantSignupContent["hero"];
};

function SubmitButton({ isTurnstileReady }: { isTurnstileReady: boolean }) {
  const { pending } = useFormStatus();

  const getButtonLabel = () => {
    if (pending) return "Validating your data...";
    if (!isTurnstileReady) return "Waiting for security verification...";
    return "Continue to verify account";
  };

  return (
    <Button
      fullWidth
      aria-disabled={pending || !isTurnstileReady}
      btnLabel={getButtonLabel()}
      customVariant="black"
      endContent={pending || !isTurnstileReady ? null : <FaChevronRight />}
      isDisabled={pending || !isTurnstileReady}
      isLoading={pending}
      type="submit"
    />
  );
}

function CreateNewAccount({
  isSignupBlocked,
  userCountry,
  userCountryCode,
  hero,
}: CreateNewAccountProps) {
  const router = useRouter();
  const searchParams = useSearchParams();
  const queryString = searchParams.toString();
  const turnstileSiteKey = process.env
    .NEXT_PUBLIC_CLOUDFLARE_TURNSTILE_SITE_KEY as string;
  const [token, setToken] = useState<string>();
  const [hasError, setHasError] = useState<boolean>(false);
  const [isBot, setIsBot] = useState<boolean>(false);
  const {
    isOpen: isOpenConfirmModal,
    onOpen: onOpenConfirmModal,
    onClose: onCloseConfirmModal,
  } = useDisclosure();

  const {
    isOpen: isOpenBlockSignupModal,
    onOpen: onOpenBlockSignupModal,
    onClose: onCloseBlockSignupModal,
  } = useDisclosure();

  const turnstileRef = useRef<TurnstileInstance>(null);
  const isTurnstileReady = !!turnstileRef.current?.getResponse();

  const [state, formAction] = useFormState(
    initiateSignUpProcess.bind(null, token),
    {
      success: false,
      error: "",
    },
  );

  const { control, getValues } = useForm<CreateNewAccountData>({
    defaultValues: {
      firstName: "",
      lastName: "",
      email: "",
      dateOfBirth: "",
      phoneNumber: `${userCountryCode}`,
      password: "",
      isGdprAccepted: false,
    },
    mode: "all",
  });

  const userPhoneNumber = getValues("phoneNumber");
  const formattedPhoneNumber =
    parsePhoneNumber(userPhoneNumber).number?.international;

  const handleClickBackConfirmModal = () => {
    onCloseConfirmModal();
    turnstileRef.current?.reset();
  };

  const handleClickJoin = () => {
    onCloseBlockSignupModal();
    router.push(AIRTABLE_INTERNATIONAL);
  };

  const handleClickConfirm = async () => {
    onCloseConfirmModal();

    const middleNameValue = (
      document.getElementById("middleName") as HTMLInputElement
    )?.value;

    if (middleNameValue) {
      setIsBot(true);
      return;
    }

    storeCookie(COOKIE_SIGNUP_IN_PROGRESS, "true", {
      secure: process.env.NODE_ENV === "production",
      sameSite: "strict",
      expires: new Date(Date.now() + 60 * 60 * 2 * 1000),
    });

    try {
      await generateAndSendOTP(userPhoneNumber);
      setHasError(false);
      queryString
        ? router.push(
            `${INTERNAL_PAGES.participant.signup.verifyAccount}?${queryString}`,
          )
        : router.push(INTERNAL_PAGES.participant.signup.verifyAccount);
    } catch (error) {
      setHasError(true);
    }
  };

  useEffect(() => {
    const currentCountryCode = parsePhoneNumber(userPhoneNumber).countryCode;

    const isCountryAllowed =
      currentCountryCode !== undefined &&
      ALLOWED_COUNTRY_CALLING_CODES.some(
        (country) => country.countryCode === `+${currentCountryCode}`,
      );

    // this is a workaround to avoid users who use VPN's and spoof the geolocation data, but then try to use phone numbers
    // from countries that are not allowed.
    if (state.success && !isCountryAllowed) {
      onOpenBlockSignupModal();
    }

    if (!state.success) {
      turnstileRef.current?.reset();
    }

    if (state.success && isCountryAllowed) {
      onOpenConfirmModal();
    }
  }, [
    onOpenBlockSignupModal,
    onOpenConfirmModal,
    state.success,
    userPhoneNumber,
  ]);

  if (isSignupBlocked) {
    return <BlockedSignup userCountry={userCountry} />;
  }

  return (
    <main
      className="xl:w-7/12 relative bg-white xl:pt-0 pt-6 light"
      id="main-content"
    >
      <div className="absolute xl:hidden top-0 w-full h-2 bg-participant-bittersweet dark:bg-participant-cerulean" />
      <StepHeading
        currentStep={1}
        subtitle={hero.subtitle}
        title={hero.title}
      />
      <>
        <form
          noValidate
          action={formAction}
          className="mt-6 sm:mt-8 flex flex-col gap-4 xl:mx-16 mx-6"
        >
          <div className="flex flex-col xl:flex-row space-x-0 space-y-2 xl:space-y-0 xl:space-x-3">
            <div className="flex-grow">
              <Controller
                control={control}
                name="firstName"
                render={({ fieldState, field }) => {
                  return (
                    <TextInput
                      isClearable
                      autoComplete={AUTOCOMPLETE_VALUES.GIVEN_NAME}
                      control={control}
                      fieldProps={field}
                      fieldState={fieldState}
                      label="First name"
                      name={field.name}
                      placeholder="Your first name"
                    />
                  );
                }}
              />
              {state.errors?.firstName && (
                <FormError text={state.errors.firstName} />
              )}
            </div>

            {/* Honeypot field to prevent bots */}
            <div
              aria-hidden
              style={{
                position: "absolute",
                left: "-9999px",
                visibility: "hidden",
              }}
            >
              <input
                aria-hidden
                autoComplete="new-password"
                id="middleName"
                name="hiddenField987"
                style={{
                  opacity: 0,
                  height: 0,
                  pointerEvents: "none",
                }}
                tabIndex={-1}
                type="text"
              />
            </div>

            <div className="flex-grow">
              <Controller
                control={control}
                name="lastName"
                render={({ fieldState, field }) => {
                  return (
                    <TextInput
                      isClearable
                      autoComplete={AUTOCOMPLETE_VALUES.FAMILY_NAME}
                      control={control}
                      fieldProps={field}
                      fieldState={fieldState}
                      label="Last name"
                      name={field.name}
                      placeholder="Your last name"
                    />
                  );
                }}
              />
              {state.errors?.lastName && (
                <FormError text={state.errors.lastName} />
              )}
            </div>
          </div>
          <Controller
            control={control}
            name="email"
            render={({ fieldState, field }) => {
              return (
                <TextInput
                  isClearable
                  autoComplete={AUTOCOMPLETE_VALUES.EMAIL}
                  control={control}
                  fieldProps={field}
                  fieldState={fieldState}
                  label="Email address"
                  name={field.name}
                  placeholder="Your email address"
                />
              );
            }}
          />
          {state.errors?.email && <FormError text={state.errors.email} />}
          <Controller
            control={control}
            name="dateOfBirth"
            render={({ fieldState, field }) => {
              return (
                <DateInput
                  control={control}
                  description="Your date of birth is required to verify your identify."
                  fieldProps={field}
                  fieldState={fieldState}
                  label="Date of birth"
                  name={field.name}
                />
              );
            }}
          />
          {state.errors?.dateOfBirth && (
            <FormError text={state.errors.dateOfBirth} />
          )}
          <Controller
            control={control}
            name="phoneNumber"
            render={({ fieldState, field }) => {
              return (
                <TextInput
                  isClearable
                  control={control}
                  description="The country code (e.g. +44) is required. Your phone number is required to verify your identify."
                  fieldProps={field}
                  fieldState={fieldState}
                  label="Phone number"
                  name={field.name}
                  placeholder="Your phone number"
                />
              );
            }}
          />
          {state.errors?.phoneNumber && (
            <FormError text={state.errors.phoneNumber} />
          )}
          <Controller
            control={control}
            name="password"
            render={({ fieldState, field }) => {
              return (
                <PasswordInput
                  control={control}
                  fieldProps={field}
                  fieldState={fieldState}
                  label="Password"
                  name={field.name}
                  placeholder="Your password"
                />
              );
            }}
          />
          {state.errors?.password && <FormError text={state.errors.password} />}
          <DividerLabel label="Terms and Conditions" sideMargins="mx-10" />
          <Controller
            control={control}
            name="isGdprAccepted"
            render={({ field, fieldState }) => {
              const gpdrOption: Option = {
                id: 1,
                title:
                  "I give permission for my personal information to be held securely by People for Research Ltd in accordance with current data protection legislation, solely for the purpose of contacting me to participate in paid research.",
              };

              return (
                <CheckboxSingle
                  control={control}
                  fieldProps={field}
                  fieldState={fieldState}
                  name={field.name}
                  option={gpdrOption}
                />
              );
            }}
          />
          {state.errors?.isGdprAccepted && (
            <FormError text={state.errors.isGdprAccepted} />
          )}
          <Turnstile
            ref={turnstileRef}
            as="aside"
            options={{
              action: "login",
              theme: "light",
              size: "flexible",
            }}
            siteKey={turnstileSiteKey}
            onSuccess={(token) => setToken(token)}
          />
          {state.error && (
            <Alert
              message={state.error}
              title={`Error (${state.errorCode})`}
              variant="error"
            />
          )}
          {hasError && (
            <Alert
              showSupportEmail
              message="An error has occurred while trying to create your account. Please try again. If the error persists, please contact us at "
              title="Error"
              variant="error"
            />
          )}
          {isBot && (
            <Alert
              showSupportEmail
              message="We encountered an issue while processing your signup. Please refresh the page and try again. If the problem continues, feel free to reach out to our support team at "
              title={`Error (PFRPPTERR31)`}
              variant="error"
            />
          )}
          {state.errors && (
            <Alert
              message="Some fields have missing or incorrect information. Please review the highlighted fields and correct any errors."
              title="Error"
              variant="alert"
            />
          )}
          <SubmitButton isTurnstileReady={isTurnstileReady} />
        </form>
        <FinalActionsFooter />
      </>
      <ConfirmModal
        dateOfBirth={getValues("dateOfBirth")}
        firstName={getValues("firstName")}
        formattedPhoneNumber={formattedPhoneNumber || ""}
        isOpen={isOpenConfirmModal}
        lastName={getValues("lastName")}
        onClickBack={handleClickBackConfirmModal}
        onClickConfirm={handleClickConfirm}
        onClose={onCloseConfirmModal}
      />
      <BlockedSignupModal
        firstName={getValues("firstName")}
        isOpen={isOpenBlockSignupModal}
        userCountryCode={parsePhoneNumber(userPhoneNumber).countryCode || 0}
        onClickJoin={handleClickJoin}
        onClose={onCloseBlockSignupModal}
      />
    </main>
  );
}

export default CreateNewAccount;
