import React from "react";
import { Navigate, useNavigate } from "react-router";
import { useSignUpContext } from "./signUpContext";

import { yupResolver } from "@hookform/resolvers/yup";
import { useForm } from "react-hook-form";
import * as yup from "yup";
import { AuthContext } from "@/authContext";
import MkdSDK from "@/utils/MkdSDK";
import { Link } from "react-router-dom";
import { callCustomAPI } from "@/utils/callCustomAPI";
import { useRef } from "react";
import { isSameDay } from "@/utils/date-time-utils";
import moment from "moment/moment";
import TermsAndConditionsModal from "./TermsAndConditionsModal";
import DatePickerV2 from "@/components/frontend/DatePickerV2";
import { LoadingButton } from "@/components/frontend";
import PrivacyAndPolicyModal from "./PrivacyAndPolicyModal";
import commonPasswords from "@/assets/json/common-passwords.json";

export default function SignUpDetailsForm() {
  const navigate = useNavigate();
  const { signUpData } = useSignUpContext();
  const role = signUpData.role;
  const { dispatch: authDispatch } = React.useContext(AuthContext);
  const [showPassword, setShowPassword] = React.useState(false);
  const [loading, setLoading] = React.useState(false);
  const sdk = new MkdSDK();
  const [modalOpen, setModalOpen] = React.useState(false);
  const [privacyOpen, setPrivacyModalOpen] = React.useState(false);
  const initialDate = useRef(new Date());
  const [agreedToTerms, setAgreedToTerms] = React.useState(false);
  const [privacyRead, setPrivacyRead] = React.useState(false);
  const [passwordErrors, setPasswordErrors] = React.useState([]);

  function closeModal() {
    setModalOpen(false);
  }
  function closePrivacyModal() {
    setPrivacyModalOpen(false);
  }

  // --- DOB must be at least 18 years ---
  function isAtLeast18YearsOld(date) {
    if (!date) return false;
    const now = new Date();
    const dob = new Date(date);
    let age = now.getFullYear() - dob.getFullYear();
    const m = now.getMonth() - dob.getMonth();
    if (m < 0 || (m === 0 && now.getDate() < dob.getDate())) {
      age--;
    }
    return age >= 18;
  }

  // --- Password validation ---
  function validatePassword(password, firstName, lastName, dob) {
    const errors = [];
    if (!password) errors.push("Password is required.");
    if (password && password.length < 10)
      errors.push("Password must be at least 10 characters long.");
    if (password && !/[a-z]/.test(password))
      errors.push("Password must contain at least one lowercase letter.");
    if (password && !/[A-Z]/.test(password))
      errors.push("Password must contain at least one uppercase letter.");
    if (password && !/[0-9]/.test(password))
      errors.push("Password must contain at least one digit.");
    if (password && !/[^A-Za-z0-9]/.test(password))
      errors.push("Password must contain at least one symbol.");
    if (
      password &&
      firstName &&
      password.toLowerCase().includes(firstName.toLowerCase())
    )
      errors.push("Password must not contain your first name.");
    if (
      password &&
      lastName &&
      password.toLowerCase().includes(lastName.toLowerCase())
    )
      errors.push("Password must not contain your last name.");
    if (password && dob) {
      const dobStr = new Date(dob).toISOString().slice(0, 10).replace(/-/g, "");
      if (dobStr && password.includes(dobStr))
        errors.push("Password must not contain your date of birth.");
    }
    if (
      password &&
      commonPasswords.some((w) => password.toLowerCase().includes(w))
    )
      errors.push("Password must not contain common password words.");
    return errors;
  }

  // --- Validation schema ---
  const schema = yup.object({
    firstName: yup.string().required("First name is required."),
    lastName: yup.string().required("Last name is required."),
    dob: yup
      .date()
      .required("Date of birth is required.")
      .test("age", "You must be at least 18 years old.", isAtLeast18YearsOld),
    password: yup.string().required("Password is required."),
  });

  const {
    register,
    setError,
    handleSubmit,
    trigger,
    watch,
    setValue,
    control,
    formState: { errors, dirtyFields },
  } = useForm({
    resolver: yupResolver(schema),
    defaultValues: {
      firstName: signUpData.firstName,
      lastName: signUpData.lastName,
      dob: initialDate.current,
      password: signUpData.password,
    },
    criteriaMode: "all",
  });

  const data = watch();

  // --- Password error display ---
  React.useEffect(() => {
    setPasswordErrors(
      validatePassword(data.password, data.firstName, data.lastName, data.dob)
    );
  }, [data.password, data.firstName, data.lastName, data.dob]);

  // --- Terms and Privacy Modal handlers ---
  function handleAgreeTerms() {
    setAgreedToTerms(true);
    setModalOpen(false);
  }
  function handlePrivacyRead() {
    setPrivacyRead(true);
    setPrivacyModalOpen(false);
  }

  // --- Disable submit logic ---
  const canSubmit =
    data.firstName &&
    data.lastName &&
    data.dob &&
    isAtLeast18YearsOld(data.dob) &&
    data.password &&
    passwordErrors.length === 0 &&
    agreedToTerms &&
    privacyRead;

  async function onSubmit() {
    setLoading(true);
    try {
      const result = await sdk.register(signUpData.email, data.password, role);
      if (!result.error) {
        localStorage.setItem("token", result.token);

        // register device
        sdk.setTable("device");
        await sdk.callRestAPI(
          {
            active: 1,
            user_id: result.user_id,
            last_login_time: new Date().toISOString().split("T")[0],
            uid: localStorage.getItem("device-uid"),
          },
          "POST"
        );

        await callCustomAPI(
          "edit-self",
          "post",
          {
            user: {
              first_name: data.firstName,
              last_name: data.lastName,
            },
            profile: {
              dob: isSameDay(data.dob, initialDate.current)
                ? undefined
                : moment(data.dob).format("yyyy-MM-DD"),
            },
          },
          "",
          result.token
        );

        localStorage.removeItem("token");

        authDispatch({ type: "ALLOW_CHECK_VERIFICATION" });
        navigate("/check-verification");
        localStorage.setItem("first_login", result.user_id);
        setLoading(false);
      } else {
        setLoading(false);
        if (result.validation) {
          const keys = Object.keys(result.validation);
          for (let i = 0; i < keys.length; i++) {
            const field = keys[i];
            setError(field, {
              type: "manual",
              message: result.validation[field],
            });
          }
        }
      }
    } catch (err) {
      setLoading(false);
      setError("firstName", {
        type: "manual",
        message: err.message,
      });
    }
  }

  if (!signUpData.email) return <Navigate to={`/signup`} />;

  return (
    <>
      <section className='flex flex-col items-center justify-center bg-white md:w-1/2'>
        <form
          className='flex w-full max-w-md flex-col px-6'
          onSubmit={handleSubmit(onSubmit)}
          autoComplete='off'
        >
          <h1 className='mb-8 text-center text-5xl font-bold'>
            Finish Signing Up
          </h1>
          <div className='mb-8'>
            <input
              type='text'
              {...register("firstName")}
              className='w-full resize-none rounded-md border bg-transparent px-4 py-2 focus:outline-none active:outline-none'
              placeholder='First name'
              autoComplete='off'
            />
            <p className='mt-2 block text-xs italic text-red-500'>
              {errors.firstName?.message}
            </p>
          </div>

          <div className='mb-8'>
            <input
              type='text'
              {...register("lastName")}
              className='w-full resize-none rounded-md border bg-transparent px-4 py-2 focus:outline-none active:outline-none'
              placeholder='Last name'
              autoComplete='off'
            />
            <p className='mt-2 block text-xs italic text-red-500'>
              {errors.lastName?.message}
            </p>
          </div>

          <DatePickerV2
            control={control}
            name='dob'
            min={new Date("1950-01-01")}
            max={initialDate.current}
            setValue={(v) => setValue("dob", v)}
          />
          <p className='mt-2 block text-xs italic text-red-500'>
            {errors.dob?.message}
          </p>

          <div
            className={`${
              passwordErrors.length > 0 && dirtyFields.password
                ? "rounded-md border border-[#C42945]"
                : "borde"
            } relative mb-4 flex flex-col rounded-md bg-transparent`}
          >
            <div className='flex items-center justify-between'>
              <input
                autoComplete={showPassword ? "off" : "new-password"}
                type={showPassword ? "text" : "password"}
                {...register("password", {
                  onChange: () => {
                    trigger("password");
                  },
                })}
                className='flex-grow rounded-md border p-2 px-4 focus:outline-none active:outline-none '
                placeholder='Password'
              />
              <button
                type='button'
                onClick={() => setShowPassword((prev) => !prev)}
                className='absolute right-1 top-[20%]'
              >
                {showPassword ? (
                  <img src='/show.png' alt='' className='mr-2 w-6' />
                ) : (
                  <img src='/invisible.png' alt='' className='mr-2 w-6' />
                )}
              </button>
            </div>
            {dirtyFields.password && passwordErrors.length > 0 && (
              <ul className='ml-6 mt-2 list-disc text-xs text-red-500'>
                {passwordErrors.map((err, idx) => (
                  <li key={idx}>{err}</li>
                ))}
              </ul>
            )}
          </div>

          <p className='mb-4 text-sm normal-case text-gray-500'>
            Select and agree to{" "}
            <button
              type='button'
              onClick={() => setModalOpen(true)}
              className='underline'
              // target={"_blank"}
            >
              {" "}
              Terms and Conditions
            </button>{" "}
            to continue.{" "}
            <button
              type='button'
              onClick={() => setPrivacyModalOpen(true)}
              className='underline'
            >
              Privacy Policy
            </button>
          </p>

          <div className='mb-1 flex flex-col'>
            {" "}
            {!agreedToTerms && (
              <span className='text-xs text-red-500'>
                You must agree to the Terms and Conditions.
              </span>
            )}
            {!privacyRead && (
              <span className='text-xs text-red-500'>
                You must read the Privacy Policy to the end.
              </span>
            )}
          </div>

          <LoadingButton
            loading={loading}
            type='submit'
            className={`login-btn-gradient rounded tracking-wide text-white outline-none focus:outline-none disabled:cursor-not-allowed ${
              loading ? "py-1" : "py-2"
            }`}
            disabled={!canSubmit}
          >
            Continue
          </LoadingButton>
        </form>
      </section>
      <section
        style={{
          backgroundImage: `url(${
            role == "host" ? "/host-sign-up.jpg" : "/sign-up-bg.jpg"
          })`,
          backgroundSize: "cover",
          backgroundRepeat: "no-repeat",
          backgroundPosition: "center",
        }}
        className='hidden w-1/2 md:block'
      ></section>
      <TermsAndConditionsModal
        isOpen={modalOpen}
        closeModal={() => setModalOpen(false)}
        setIsAgreed={handleAgreeTerms}
      />
      <PrivacyAndPolicyModal
        isOpen={privacyOpen}
        closeModal={() => setPrivacyModalOpen(false)}
        onReadToEnd={handlePrivacyRead}
      />
    </>
  );
}
