"use client";

import {
  useResendOtpMutation,
  useSignupMutation,
  useVerifyEmailMutation,
} from "@/api/auth.api";
import { useGetCategoryTreeQuery } from "@/api/category.api";
import { ISignupRequest, IVerifyEmailRequest } from "@/api/types/auth";
import { parseApiError } from "@/api/utils/error-handler";
import { setAuthTokens } from "@/lib/auth-cookies";
import { useAppDispatch, useAppSelector } from "@/redux/hooks";
import { setCredentials } from "@/redux/slices/authSlice";
import Link from "next/link";
import { useRouter } from "next/navigation";
import { useEffect, useRef, useState } from "react";
import { Controller, useForm } from "react-hook-form";
import { toast } from "react-hot-toast";

import OtpInput from "@/components/common/OtpInput";
import SubscriptionRequiredModal from "@/components/Membership/SubscriptionRequiredModal";

export default function SignupPage() {
  const [step, setStep] = useState<"signup" | "verify">("signup");
  const [signUpToken, setSignUpToken] = useState<string>("");
  const [signupEmail, setSignupEmail] = useState<string>("");
  const [countdown, setCountdown] = useState(30);
  const [isRankDropdownOpen, setIsRankDropdownOpen] = useState(false);
  const [rankSearch, setRankSearch] = useState("");
  const [rankDropdownDirection, setRankDropdownDirection] = useState<
    "down" | "up"
  >("down");
  const [showPassword, setShowPassword] = useState(false);
  const [showSubModal, setShowSubModal] = useState(false);
  const rankFieldRef = useRef<HTMLDivElement>(null);

  const RANK_DROPDOWN_ESTIMATED_HEIGHT = 320;

  const toggleRankDropdown = () => {
    if (!isRankDropdownOpen && rankFieldRef.current) {
      const rect = rankFieldRef.current.getBoundingClientRect();
      const spaceBelow = window.innerHeight - rect.bottom;
      const spaceAbove = rect.top;
      setRankDropdownDirection(
        spaceBelow >= RANK_DROPDOWN_ESTIMATED_HEIGHT || spaceBelow >= spaceAbove
          ? "down"
          : "up",
      );
    }
    setIsRankDropdownOpen((prev) => !prev);
  };

  const router = useRouter();
  const dispatch = useAppDispatch();
  const { isAuthenticated } = useAppSelector((state) => state.auth);

  // Return the user to wherever they came from (e.g. a /discussion page) after
  // registering. Only relative paths are honoured to avoid open redirects.
  const [redirectTo, setRedirectTo] = useState("/");
  useEffect(() => {
    const r = new URLSearchParams(window.location.search).get("redirect");
    if (r && r.startsWith("/") && !r.startsWith("//")) setRedirectTo(r);
  }, []);

  const [signup, { isLoading: isSignupLoading }] = useSignupMutation();
  const [verifyEmail, { isLoading: isVerifyLoading }] =
    useVerifyEmailMutation();
  const [resendOtp, { isLoading: isResendLoading }] = useResendOtpMutation();

  const { data: rankCategories, isLoading: isRankLoading } =
    useGetCategoryTreeQuery("rank");

  const {
    register,
    handleSubmit,
    control,
    formState: { errors: signupErrors },
  } = useForm<ISignupRequest>({
    defaultValues: {
      firstName: "",
      lastName: "",
      email: "",
      password: "",
      rankId: "",
    },
  });

  const {
    handleSubmit: handleSubmitVerify,
    setValue,
    watch: watchVerify,
    formState: { errors: verifyErrors },
  } = useForm<IVerifyEmailRequest>({
    defaultValues: { code: "" },
  });

  const verifyCode = watchVerify("code");

  const onSignupSubmit = async (data: ISignupRequest) => {
    try {
      const response = await signup(data).unwrap();
      if (response?.signUpToken) {
        setSignUpToken(response.signUpToken);
        setSignupEmail(data.email);
        setStep("verify");
        setValue("code", "");
        setCountdown(30);
      }
    } catch (error: any) {
      toast.error(parseApiError(error));
    }
  };

  const onVerifySubmit = async (data: IVerifyEmailRequest) => {
    try {
      const response = await verifyEmail({
        signUpToken,
        code: data.code,
        type: "signup",
      }).unwrap();
      if (response?.id) {
        setAuthTokens(response.token, response.refreshToken);
        dispatch(
          setCredentials({
            user: {
              id: response.id.toString(),
              email: response.email,
              name: response.userProfile.name,
              profileImage: response.userProfile.profileImage?.filePath || null,
              rankName: response.userProfile.rank.name,
              isPremium: response.userSetting.isPremium,
              billingRegion: response.userSetting.billingRegion ?? null,
            },
          }),
        );
        toast.success("Email verified! Welcome aboard.");
        // Prompt the freshly-registered user to subscribe before sending them on.
        setShowSubModal(true);
      }
    } catch (error: any) {
      toast.error(parseApiError(error));
    }
  };

  useEffect(() => {
    // Don't bounce away while the post-signup subscription modal is showing.
    if (isAuthenticated && !showSubModal) router.push(redirectTo);
  }, [isAuthenticated, showSubModal, router, redirectTo]);

  useEffect(() => {
    let timer: NodeJS.Timeout;
    if (step === "verify" && countdown > 0) {
      timer = setTimeout(() => setCountdown((prev) => prev - 1), 1000);
    }
    return () => clearTimeout(timer);
  }, [step, countdown]);

  const onResendOtp = async () => {
    try {
      const response = await resendOtp({ signUpToken }).unwrap();
      // console.log("Resend OTP response:", response);
      setSignUpToken(response.signUpToken);
      toast.success("OTP resent successfully!");
      setCountdown(30);
    } catch (error: any) {
      toast.error(parseApiError(error));
    }
  };

  if (isAuthenticated && !showSubModal) return null;

  const closeSubModalAndGoHome = () => {
    setShowSubModal(false);
    // Returning to a specific page does a full load so it refetches with the new
    // auth token; the plain home case stays a snappy client transition.
    if (redirectTo === "/") router.push("/");
    else window.location.href = redirectTo;
  };

  if (step === "verify") {
    return (
      <div className="w-full">
        <div className="text-center mb-8">
          <h1 className="text-2xl font-bold text-[#111827]">
            Verify your email
          </h1>
          <p className="mt-1.5 text-sm text-[#6b7280]">
            Enter the 4-digit code sent to{" "}
            <span className="font-semibold text-[#111827]">{signupEmail}</span>
          </p>
        </div>

        <div className="bg-white rounded-2xl shadow-[0_25px_50px_-12px_rgba(0,0,0,0.25)] p-8">
          <form
            onSubmit={handleSubmitVerify(onVerifySubmit)}
            className="flex flex-col gap-5"
          >
            <OtpInput
              value={verifyCode}
              onChange={(val) => setValue("code", val)}
              error={verifyErrors.code}
            />
            <button
              type="submit"
              disabled={isVerifyLoading}
              className="w-full py-3 rounded-xl text-sm font-semibold text-white bg-[#3b82f6] hover:bg-[#2563eb] border-none cursor-pointer transition-colors disabled:opacity-50"
            >
              {isVerifyLoading ? "Verifying..." : "Verify"}
            </button>
          </form>

          <div className="flex items-center gap-3 my-6">
            <div className="flex-1 h-px bg-[#f3f4f6]" />
            <span className="text-xs text-[#9ca3af] whitespace-nowrap">
              Didn&apos;t receive a code?
            </span>
            <div className="flex-1 h-px bg-[#f3f4f6]" />
          </div>

          <button
            type="button"
            disabled={isResendLoading || countdown > 0}
            onClick={onResendOtp}
            className="block w-full py-2.5 rounded-xl text-sm font-semibold text-[#374151] bg-white border border-[#e5e7eb] text-center enabled:cursor-pointer hover:bg-[#f9fafb] transition-colors disabled:opacity-50 disabled:cursor-not-allowed"
          >
            {isResendLoading
              ? "Sending..."
              : countdown > 0
                ? `Resend OTP in ${countdown}s`
                : "Resend OTP"}
          </button>
        </div>

        <SubscriptionRequiredModal
          isOpen={showSubModal}
          onClose={closeSubModalAndGoHome}
          onViewPlans={() =>
            router.push(
              `/my-account?current-section=subscription&redirect=${encodeURIComponent(redirectTo)}`,
            )
          }
          title="Welcome aboard!"
          description={
            <>
              <span className="text-neutral-500 font-normal">
                Your account is ready. Subscribe to a plan to unlock{" "}
              </span>
              <span className="text-black font-semibold">full access</span>
              <span className="text-neutral-500 font-normal">
                {" "}
                to premium articles and our expert Q&amp;A community.
              </span>
            </>
          }
        />
      </div>
    );
  }

  return (
    <div className="w-full">
      <div className="text-center mb-8">
        <h1 className="text-2xl leading-[normal] font-bold text-[#111827]">
          Join MySeaTime
        </h1>
        <p className="mt-1.5 text-sm leading-[normal] text-[#6b7280]">
          Create your free account and start learning
        </p>
      </div>

      <div className="bg-white rounded-2xl shadow-[0_25px_50px_-12px_rgba(0,0,0,0.25)] p-8">
        <form
          onSubmit={handleSubmit(onSignupSubmit)}
          className="flex flex-col gap-4"
        >
          {/* First Name */}
          <div>
            <label className="block text-sm leading-[normal] font-semibold text-[#374151] mb-1.5">
              First Name
            </label>
            <div className="relative">
              <span className="absolute left-3.5 top-1/2 -translate-y-1/2 flex items-center pointer-events-none text-[#9ca3af]">
                <svg
                  width="16"
                  height="16"
                  fill="none"
                  stroke="currentColor"
                  strokeWidth="2"
                  viewBox="0 0 24 24"
                >
                  <path
                    strokeLinecap="round"
                    strokeLinejoin="round"
                    d="M16 7a4 4 0 11-8 0 4 4 0 018 0zM12 14a7 7 0 00-7 7h14a7 7 0 00-7-7z"
                  />
                </svg>
              </span>
              <input
                type="text"
                placeholder="James"
                autoComplete="given-name"
                {...register("firstName", {
                  required: "First name is required",
                })}
                className={`w-full py-2.5 pl-10 pr-4 text-sm leading-[normal] border rounded-xl bg-white text-[#111827] placeholder:text-[#d1d5db] outline-none transition-all focus:border-transparent focus:ring-2 focus:ring-[#60a5fa] ${signupErrors.firstName ? "border-red-400" : "border-[#e5e7eb]"}`}
              />
            </div>
            {signupErrors.firstName && (
              <p className="mt-1 text-xs leading-[normal] text-[#ef4444]">
                {signupErrors.firstName.message}
              </p>
            )}
          </div>

          {/* Last Name */}
          <div>
            <label className="block text-sm leading-[normal] font-semibold text-[#374151] mb-1.5">
              Last Name
            </label>
            <div className="relative">
              <span className="absolute left-3.5 top-1/2 -translate-y-1/2 flex items-center pointer-events-none text-[#9ca3af]">
                <svg
                  width="16"
                  height="16"
                  fill="none"
                  stroke="currentColor"
                  strokeWidth="2"
                  viewBox="0 0 24 24"
                >
                  <path
                    strokeLinecap="round"
                    strokeLinejoin="round"
                    d="M16 7a4 4 0 11-8 0 4 4 0 018 0zM12 14a7 7 0 00-7 7h14a7 7 0 00-7-7z"
                  />
                </svg>
              </span>
              <input
                type="text"
                placeholder="Mitchell"
                autoComplete="family-name"
                {...register("lastName", { required: "Last name is required" })}
                className={`w-full py-2.5 pl-10 pr-4 text-sm leading-[normal] border rounded-xl bg-white text-[#111827] placeholder:text-[#d1d5db] outline-none transition-all focus:border-transparent focus:ring-2 focus:ring-[#60a5fa] ${signupErrors.lastName ? "border-red-400" : "border-[#e5e7eb]"}`}
              />
            </div>
            {signupErrors.lastName && (
              <p className="mt-1 text-xs leading-[normal] text-[#ef4444]">
                {signupErrors.lastName.message}
              </p>
            )}
          </div>

          {/* Email */}
          <div>
            <label className="block text-sm leading-[normal] font-semibold text-[#374151] mb-1.5">
              Email address
            </label>
            <div className="relative">
              <span className="absolute left-3.5 top-1/2 -translate-y-1/2 flex items-center pointer-events-none text-[#9ca3af]">
                <svg
                  width="16"
                  height="16"
                  fill="none"
                  stroke="currentColor"
                  strokeWidth="2"
                  viewBox="0 0 24 24"
                >
                  <path
                    strokeLinecap="round"
                    strokeLinejoin="round"
                    d="M3 8l7.89 5.26a2 2 0 002.22 0L21 8M5 19h14a2 2 0 002-2V7a2 2 0 00-2-2H5a2 2 0 00-2 2v10a2 2 0 002 2z"
                  />
                </svg>
              </span>
              <input
                type="email"
                placeholder="you@example.com"
                autoComplete="email"
                {...register("email", {
                  required: "Email is required",
                  pattern: {
                    value: /^[^\s@]+@[^\s@]+\.[^\s@]+$/,
                    message: "Invalid email format",
                  },
                })}
                className={`w-full py-2.5 pl-10 pr-4 text-sm leading-[normal] border rounded-xl bg-white text-[#111827] placeholder:text-[#d1d5db] outline-none transition-all focus:border-transparent focus:ring-2 focus:ring-[#60a5fa] ${signupErrors.email ? "border-red-400" : "border-[#e5e7eb]"}`}
              />
            </div>
            {signupErrors.email && (
              <p className="mt-1 text-xs leading-[normal] text-[#ef4444]">
                {signupErrors.email.message}
              </p>
            )}
          </div>

          {/* Password */}
          <div>
            <label className="block text-sm leading-[normal] font-semibold text-[#374151] mb-1.5">
              Password
            </label>
            <div className="relative">
              <span className="absolute left-3.5 top-1/2 -translate-y-1/2 flex items-center pointer-events-none text-[#9ca3af]">
                <svg
                  width="16"
                  height="16"
                  fill="none"
                  stroke="currentColor"
                  strokeWidth="2"
                  viewBox="0 0 24 24"
                >
                  <rect x="3" y="11" width="18" height="11" rx="2" />
                  <path d="M7 11V7a5 5 0 0110 0v4" />
                </svg>
              </span>
              <input
                type={showPassword ? "text" : "password"}
                placeholder="Minimum 8 characters"
                autoComplete="new-password"
                {...register("password", {
                  required: "Password is required",
                  pattern: {
                    value: /^(?=.*[a-z])(?=.*[A-Z])(?=.*\d).{8,}$/,
                    message:
                      "Minimum 8 characters, including 1 number, 1 uppercase & 1 lowercase letter.",
                  },
                })}
                className={`w-full py-2.5 pl-10 pr-10 text-sm leading-[normal] border rounded-xl bg-white text-[#111827] placeholder:text-[#d1d5db] outline-none transition-all focus:border-transparent focus:ring-2 focus:ring-[#60a5fa] ${signupErrors.password ? "border-red-400" : "border-[#e5e7eb]"}`}
              />
              <button
                type="button"
                onClick={() => setShowPassword(!showPassword)}
                className="absolute right-3.5 top-1/2 -translate-y-1/2 bg-transparent border-none cursor-pointer text-[#9ca3af] hover:text-[#6b7280] flex items-center p-0.5 transition-colors"
              >
                {showPassword ? (
                  <svg
                    width="16"
                    height="16"
                    fill="none"
                    stroke="currentColor"
                    strokeWidth="2"
                    viewBox="0 0 24 24"
                  >
                    <path
                      strokeLinecap="round"
                      strokeLinejoin="round"
                      d="M13.875 18.825A10.05 10.05 0 0112 19c-4.478 0-8.268-2.943-9.543-7a9.97 9.97 0 011.563-3.029m5.858.908a3 3 0 114.243 4.243M9.878 9.878l4.242 4.242M9.88 9.88l-3.29-3.29m7.532 7.532l3.29 3.29M3 3l3.59 3.59m0 0A9.953 9.953 0 0112 5c4.478 0 8.268 2.943 9.543 7a10.025 10.025 0 01-4.132 5.411m0 0L21 21"
                    />
                  </svg>
                ) : (
                  <svg
                    width="16"
                    height="16"
                    fill="none"
                    stroke="currentColor"
                    strokeWidth="2"
                    viewBox="0 0 24 24"
                  >
                    <path
                      strokeLinecap="round"
                      strokeLinejoin="round"
                      d="M15 12a3 3 0 11-6 0 3 3 0 016 0z"
                    />
                    <path
                      strokeLinecap="round"
                      strokeLinejoin="round"
                      d="M2.458 12C3.732 7.943 7.523 5 12 5c4.478 0 8.268 2.943 9.542 7-1.274 4.057-5.064 7-9.542 7-4.477 0-8.268-2.943-9.542-7z"
                    />
                  </svg>
                )}
              </button>
            </div>
            <p
              className={`mt-1 text-xs leading-[normal] ${signupErrors.password ? "text-[#ef4444]" : "text-[#9ca3af]"}`}
            >
              {signupErrors.password?.message ??
                "Minimum 8 characters, including 1 number, 1 uppercase & 1 lowercase letter."}
            </p>
          </div>

          {/* Rank */}
          <div>
            <label className="block text-sm leading-[normal] font-semibold text-[#374151] mb-1.5">
              Rank
            </label>
            <Controller
              name="rankId"
              control={control}
              rules={{ required: "Rank selection is required" }}
              render={({ field }) => {
                const selectedRankName = field.value
                  ? rankCategories
                      ?.flatMap((p: any) => [p, ...(p.childCategories || [])])
                      ?.find((c: any) => c.id?.toString() === field.value)
                      ?.name || "Select your rank..."
                  : "Select your rank...";

                return (
                  <div className="relative">
                    <div
                      ref={rankFieldRef}
                      onClick={toggleRankDropdown}
                      className={`flex items-center py-2.5 pl-3.5 pr-10 text-sm leading-[normal] border rounded-xl bg-white cursor-pointer transition-all outline-none ${
                        isRankDropdownOpen
                          ? "border-transparent ring-2 ring-[#60a5fa]"
                          : signupErrors.rankId
                            ? "border-red-400"
                            : "border-[#e5e7eb]"
                      }`}
                    >
                      <span
                        className={
                          field.value ? "text-[#111827]" : "text-[#d1d5db]"
                        }
                      >
                        {isRankLoading ? "Loading..." : selectedRankName}
                      </span>
                      <span className="absolute right-3.5 top-1/2 -translate-y-1/2 pointer-events-none text-[#9ca3af]">
                        <svg
                          width="16"
                          height="16"
                          fill="none"
                          stroke="currentColor"
                          strokeWidth="2"
                          viewBox="0 0 24 24"
                          className={`transition-transform duration-200 ${isRankDropdownOpen ? "rotate-180" : ""}`}
                        >
                          <path
                            strokeLinecap="round"
                            strokeLinejoin="round"
                            d="M19 9l-7 7-7-7"
                          />
                        </svg>
                      </span>
                    </div>

                    {isRankDropdownOpen && (
                      <div
                        className="fixed inset-0 z-40"
                        onClick={() => setIsRankDropdownOpen(false)}
                      />
                    )}

                    {isRankDropdownOpen && (
                      <div
                        className={`absolute ${
                          rankDropdownDirection === "up"
                            ? "bottom-full mb-2"
                            : "top-full mt-2"
                        } left-0 w-full bg-white rounded-xl border border-[#e5e7eb] shadow-lg z-40 overflow-hidden flex flex-col`}
                      >
                        <div className="p-3 border-b border-[#e5e7eb]">
                          <input
                            type="text"
                            placeholder="Search rank..."
                            value={rankSearch}
                            onChange={(e) => setRankSearch(e.target.value)}
                            onClick={(e) => e.stopPropagation()}
                            className="w-full px-3 py-2 border border-[#e5e7eb] rounded-lg outline-none focus:border-[#60a5fa] text-sm text-[#111827]"
                          />
                        </div>
                        <div className="max-h-62.5 overflow-y-auto p-2">
                          {rankCategories?.map((parent: any) => {
                            const searchLower = rankSearch.toLowerCase();
                            const parentMatches = parent.name
                              ?.toLowerCase()
                              .includes(searchLower);
                            const hasChildren =
                              (parent.childCategories?.length ?? 0) > 0;

                            if (!hasChildren) {
                              if (rankSearch && !parentMatches) return null;
                              return (
                                <div
                                  key={parent.id}
                                  onClick={() => {
                                    field.onChange(parent.id?.toString());
                                    setIsRankDropdownOpen(false);
                                    setRankSearch("");
                                  }}
                                  className={`px-3 py-2 cursor-pointer rounded-lg text-sm transition-colors ${
                                    field.value === parent.id?.toString()
                                      ? "bg-[#3b82f6] text-white"
                                      : "text-[#374151] hover:bg-[#f3f4f6]"
                                  }`}
                                >
                                  {parent.name}
                                </div>
                              );
                            }

                            const matchingChildren =
                              parent.childCategories?.filter((child: any) =>
                                child.name?.toLowerCase().includes(searchLower),
                              ) || [];
                            const childrenToShow = parentMatches
                              ? parent.childCategories || []
                              : matchingChildren;
                            if (childrenToShow.length === 0 && !parentMatches)
                              return null;

                            return (
                              <div key={parent.id} className="mb-2">
                                <div className="px-3 py-2 font-bold text-[#374151] text-sm bg-[#f9fafb] rounded-lg">
                                  {parent.name}
                                </div>
                                {childrenToShow.map((child: any) => (
                                  <div
                                    key={child.id}
                                    onClick={() => {
                                      field.onChange(child.id?.toString());
                                      setIsRankDropdownOpen(false);
                                      setRankSearch("");
                                    }}
                                    className={`px-4 py-2 ml-2 cursor-pointer rounded-lg text-sm transition-colors ${
                                      field.value === child.id?.toString()
                                        ? "bg-[#3b82f6] text-white"
                                        : "text-[#374151] hover:bg-[#f3f4f6]"
                                    }`}
                                  >
                                    {child.name}
                                  </div>
                                ))}
                              </div>
                            );
                          })}
                          {(!rankCategories || rankCategories.length === 0) &&
                            !isRankLoading && (
                              <div className="p-3 text-center text-[#9ca3af] text-sm">
                                No ranks found.
                              </div>
                            )}
                        </div>
                      </div>
                    )}
                  </div>
                );
              }}
            />
            {signupErrors.rankId && (
              <p className="mt-1 text-xs leading-[normal] text-[#ef4444]">
                {signupErrors.rankId.message}
              </p>
            )}
          </div>

          <button
            type="submit"
            disabled={isSignupLoading}
            className="w-full py-3 mt-1 rounded-xl text-sm leading-[normal] font-semibold text-white bg-[#3b82f6] hover:bg-[#2563eb] border-none cursor-pointer transition-colors disabled:opacity-50"
          >
            {isSignupLoading ? "Creating account..." : "Create account"}
          </button>
        </form>

        <div className="flex items-center gap-3 my-5">
          <div className="flex-1 h-px bg-[#f3f4f6]" />
          <span className="text-xs leading-[normal] text-[#9ca3af] whitespace-nowrap">
            Already have an account?
          </span>
          <div className="flex-1 h-px bg-[#f3f4f6]" />
        </div>

        <Link
          href={`/login?redirect=${encodeURIComponent(redirectTo)}`}
          className="block w-full py-2.5 rounded-xl text-sm leading-[normal] font-semibold text-[#374151] bg-white border border-[#e5e7eb] text-center no-underline hover:bg-[#f9fafb] transition-colors"
        >
          Sign in instead
        </Link>
      </div>

      <p className="mt-6 text-center text-xs leading-[normal] text-[#9ca3af]">
        By creating an account you agree to our{" "}
        <Link href="/legal" className="text-[#6b7280] underline">
          Terms of Service
        </Link>{" "}
        and{" "}
        <Link href="/legal" className="text-[#6b7280] underline">
          Privacy Policy
        </Link>
        .
      </p>
    </div>
  );
}
