"use client";

import Link from "next/link";
import { useState } from "react";
import { useRouter } from "next/navigation";
import { ArrowRight, LoaderCircle, LockKeyhole, Phone } from "lucide-react";
import { authCopy } from "@/components/auth/auth-copy";
import NumericPhoneInput from "@/components/forms/NumericPhoneInput";
import { storeAuthSession } from "@/features/auth/auth-storage";
import { useLoginMutation } from "@/features/auth/auth.hooks";
import { loginSchema } from "@/features/auth/auth.schemas";
import type { AuthResponse } from "@/features/auth/auth.types";
import { getApiErrorMessage } from "@/lib/api/api-error";
import {
  getFirstFormError,
  getFormErrors,
  type FormErrors,
} from "@/lib/form-errors";
import type { Locale } from "@/lib/locales";
import { getProductId } from "@/lib/product-map";
import type { ProductSlug } from "@/lib/routes";
import { showErrorAlert, showSuccessAlert, showWarningAlert } from "@/lib/alerts";

const baseFieldClass =
  "h-11 w-full rounded-lg border bg-white px-10 text-[13px] text-[#253052] outline-none transition placeholder:text-[#a7b0c0]";

const normalFieldClass =
  "border-[#dde4f1] focus:border-[#6b72f2] focus:ring-3 focus:ring-[#e9eaff]";

const errorFieldClass =
  "border-rose-400 focus:border-rose-500 focus:ring-3 focus:ring-rose-100";

type TouchedFields = Record<string, boolean>;

export default function LoginForm({
  locale,
  productSlug,
  registerHref,
}: {
  locale: Locale;
  productSlug?: ProductSlug;
  registerHref: string;
}) {
  const copy = authCopy[locale];
  const router = useRouter();
  const loginMutation = useLoginMutation();
  const productId = productSlug ? getProductId(productSlug) : undefined;

  const [errors, setErrors] = useState<FormErrors>({});
  const [touchedFields, setTouchedFields] = useState<TouchedFields>({});
  const [submitted, setSubmitted] = useState(false);

  function getLoginErrors(form: HTMLFormElement): FormErrors {
    const parsed = loginSchema.safeParse(
      Object.fromEntries(new FormData(form)),
    );

    return parsed.success ? {} : getFormErrors(parsed.error);
  }

  function getVisibleErrors(
    allErrors: FormErrors,
    nextTouchedFields: TouchedFields,
    shouldShowAll: boolean,
  ): FormErrors {
    if (shouldShowAll) return allErrors;

    return Object.fromEntries(
      Object.entries(allErrors).filter(
        ([fieldName]) => nextTouchedFields[fieldName],
      ),
    ) as FormErrors;
  }

  function handleRealtimeValidation(
    event: React.FormEvent<HTMLFormElement>,
  ) {
    const target = event.target as
      | HTMLInputElement
      | HTMLTextAreaElement
      | HTMLSelectElement;

    const fieldName = target.name;

    if (!fieldName) return;

    const nextTouchedFields = {
      ...touchedFields,
      [fieldName]: true,
    };

    const allErrors = getLoginErrors(event.currentTarget);

    setTouchedFields(nextTouchedFields);
    setErrors(getVisibleErrors(allErrors, nextTouchedFields, submitted));
  }

  function handleSubmit(event: React.FormEvent<HTMLFormElement>) {
    event.preventDefault();

    if (loginMutation.isPending) return;

    setSubmitted(true);

    const parsed = loginSchema.safeParse(
      Object.fromEntries(new FormData(event.currentTarget)),
    );

    if (!parsed.success) {
      setErrors(getFormErrors(parsed.error));
      void showErrorAlert(getFirstFormError(parsed.error), { locale });
      return;
    }

    setErrors({});
    setTouchedFields({});

    loginMutation.mutate(parsed.data, {
      onSuccess: (response) => {
        storeAuthSession(response);

        void (async () => {
          await showSuccessAlert(response.message, { autoClose: true, locale });
          redirectAfterLogin(response, router.push);
        })();
      },
      onError: (error) =>
        void showErrorAlert(getApiErrorMessage(error, locale), { locale }),
    });
  }

  return (
    <form
      noValidate
      onBlur={handleRealtimeValidation}
      onChange={handleRealtimeValidation}
      onSubmit={handleSubmit}
      className="rounded-3xl border border-[#e2e7f2] bg-white p-5 shadow-[0_18px_50px_rgba(40,55,105,0.1)] sm:p-7"
    >
      {productId ? (
        <input type="hidden" name="product_id" value={productId} />
      ) : null}

      <div className="grid gap-3.5">
        <IconField
          autoComplete="tel"
          error={errors.phone}
          icon={Phone}
          label={copy.phone}
          name="phone"
          numericPhone
          required
        />

        <IconField
          autoComplete="current-password"
          error={errors.password}
          icon={LockKeyhole}
          label={copy.password}
          name="password"
          required
          type="password"
        />
      </div>

      <div className="mt-4 flex items-center justify-between gap-3 text-[12px]">
        <label className="flex items-center gap-2 font-semibold text-[#68748c]">
          <input type="checkbox" name="remember" className="accent-[#5c66e8]" />
          {copy.remember}
        </label>

        <button
          type="button"
          onClick={() => void showWarningAlert(copy.forgotReady, { locale })}
          className="font-extrabold text-[#5c66df]"
        >
          {copy.forgot}
        </button>
      </div>

      <button
        type="submit"
        disabled={loginMutation.isPending}
        className="mt-5 inline-flex h-12 w-full items-center justify-center gap-2 rounded-lg bg-linear-to-r from-[#5264ee] to-[#6555e9] px-5 text-[13px] font-extrabold text-white shadow-[0_8px_18px_rgba(93,91,238,0.24)] transition hover:-translate-y-0.5 disabled:cursor-wait disabled:opacity-70"
      >
        {loginMutation.isPending ? (
          <LoaderCircle size={16} className="animate-spin" />
        ) : (
          <ArrowRight size={16} />
        )}

        {loginMutation.isPending ? copy.signingIn : copy.login}
      </button>

      <p className="mt-4 text-center text-[12px] text-[#7a869d]">
        {copy.noAccount}{" "}
        <Link href={registerHref} className="font-extrabold text-[#5c66df]">
          {copy.createAccount}
        </Link>
      </p>
    </form>
  );
}

const BUILDPRO_DASHBOARD_URL =
  "https://sitsoftwares.co.in/Builderpro/dashboard.php";

const SOCIETYPRO_DASHBOARD_URL =
  "https://sitsoftwares.co.in/Society_Management_System/society_onboarding_form.php";

const PUREESTATE_DASHBOARD_URL =
  "https://sitsoftwares.co.in/Estate_Ninja/main_dashboard.php";

function redirectAfterLogin(
  response: AuthResponse,
  push: (href: string) => void,
) {
  const productName = response.user.product_name?.toLowerCase().trim();
  const productId = response.user.product_id;

  if (productName === "pureestate" || productId === 1) {
    window.location.replace(PUREESTATE_DASHBOARD_URL);
    return;
  }

  if (productName === "buildpro" || productId === 2) {
    window.location.replace(BUILDPRO_DASHBOARD_URL);
    return;
  }

  if (productName === "societypro" || productId === 3) {
    window.location.replace(SOCIETYPRO_DASHBOARD_URL);
    return;
  }

  const redirectUrl = response.redirect?.url;

  if (!redirectUrl) return;

  // Prevent purchase redirect
  if (redirectUrl === "/purchase/" || redirectUrl === "/purchase") {
    return;
  }

  if (/^https?:\/\//i.test(redirectUrl)) {
    window.location.replace(redirectUrl);
  } else {
    push(redirectUrl);
  }
}

function IconField({
  autoComplete,
  error,
  icon: Icon,
  label,
  name,
  numericPhone = false,
  required,
  type = "text",
}: {
  autoComplete: string;
  error?: string[];
  icon: typeof Phone;
  label: string;
  name: string;
  numericPhone?: boolean;
  required?: boolean;
  type?: string;
}) {
  const hasError = Boolean(error?.[0]);

  const fieldClass = `${baseFieldClass} ${
    hasError ? errorFieldClass : normalFieldClass
  }`;

  return (
    <label className="text-[12px] font-bold text-[#34405d]">
      {label}

      <span className="relative mt-1.5 block">
        <Icon
          size={16}
          className={`pointer-events-none absolute left-3 top-1/2 -translate-y-1/2 ${
            hasError ? "text-rose-500" : "text-[#8b96aa]"
          }`}
        />

        {numericPhone ? (
          <NumericPhoneInput
            autoComplete={autoComplete}
            className={fieldClass}
            name={name}
            required={required}
          />
        ) : (
          <input
            autoComplete={autoComplete}
            className={fieldClass}
            name={name}
            required={required}
            type={type}
          />
        )}
      </span>

      <ErrorText errors={error} />
    </label>
  );
}

function ErrorText({ errors }: { errors?: string[] }) {
  return errors?.[0] ? (
    <span className="mt-1 block text-[11px] font-semibold text-rose-600">
      {errors[0]}
    </span>
  ) : null;
}
