import { ChangeEvent, FormEvent, useEffect, useState } from "react";
import toast from "react-hot-toast";
import { useTranslation } from "react-i18next";
import { FetchBaseQueryError } from "@reduxjs/toolkit/dist/query";

import BASE_URL from "@/app/config";
import { useLoginMutation, usePasskeyLoginStartMutation, usePasskeyLoginFinishMutation } from "@/app/services/auth";
import { useGetLoginConfigQuery, useGetSMTPStatusQuery } from "@/app/services/server";
import { useAppSelector } from "@/app/store";
import Divider from "@/components/Divider";
import Button from "@/components/styled/Button";
import Input from "@/components/styled/Input";
import StyledLabel from "@/components/styled/Label";
import IconBack from "@/assets/icons/arrow.left.svg";
import MagicLinkLogin from "./MagicLinkLogin";
import SignUpLink from "./SignUpLink";
import SocialLoginButtons from "./SocialLoginButtons";
import { shallowEqual } from "react-redux";
import SelectLanguage from "../../components/Language";
import Downloads from "../../components/Downloads";
import { startPasskeyLogin, isWebAuthnSupported } from "@/passkey";
import ServerVersionChecker from "@/components/ServerVersionChecker";

const defaultInput = {
  email: "",
  password: "",
};
export default function LoginPage() {
  const { name: serverName, logo } = useAppSelector((store) => store.server, shallowEqual);
  const { t } = useTranslation("auth");
  const { t: ct } = useTranslation();
  const { data: enableSMTP, isLoading: loadingSMTPStatus } = useGetSMTPStatusQuery();
  const [login, { isSuccess, isLoading, error }] = useLoginMutation();
  const { data: loginConfig, isSuccess: loginConfigSuccess } = useGetLoginConfigQuery();
  const [emailInputted, setEmailInputted] = useState(false);
  const [input, setInput] = useState(defaultInput);
  const [passkeyLoginStart] = usePasskeyLoginStartMutation();
  const [passkeyLoginFinish] = usePasskeyLoginFinishMutation();
  const [isPasskeyLoading, setIsPasskeyLoading] = useState(false);

  useEffect(() => {
    const query = new URLSearchParams(location.search);
    const code = query.get("code");
    const state = query.get("state");
    const magic_token = query.get("magic_token");
    const exists = query.get("exists");
    // oidc
    const fromOIDC = code && state;
    if (fromOIDC) {
      login({
        code,
        state,
        type: "oidc",
      });
    }
    // magic link
    if (magic_token && typeof exists !== "undefined") {
      const isLogin = exists == "true";
      if (isLogin) {
        // login
        login({
          magic_token,
          type: "magiclink",
        });
      } else {
        // reg with magic link and set name only
        // navigate(`/register/set_name/login?magic_token=${magic_token}`);
        location.href = `/#/register/set_name/login?magic_token=${magic_token}`;
      }
    }
  }, []);

  useEffect(() => {
    if (error) {
      switch ((error as FetchBaseQueryError).status) {
        case 401:
        case 404:
          toast.error("Username or Password incorrect");
          break;
        case 403:
          toast.error("Login method does not supported");
          break;
        case 410:
          toast.error(
            "No associated account found, please contact user admin for an invitation link to join."
          );
          break;
        // 451 有解析错误，暂时先客户端处理
        case "PARSING_ERROR":
          break;
        default:
          toast.error("Something Error");
          break;
      }
      return;
    }
  }, [error]);
  useEffect(() => {
    console.log("login success", isSuccess);
    if (isSuccess) {
      toast.success(ct("tip.login"));
      // setInput(defaultInput);
      // navigateTo("/");
    }
  }, [isSuccess]);

  const handleLogin = (evt: FormEvent<HTMLFormElement>) => {
    evt.preventDefault();
    const enableMagicLink = enableSMTP && loginConfig?.magic_link;
    if (enableMagicLink && !emailInputted) {
      setEmailInputted(true);
      return;
    }
    login({
      ...input,
      type: "password",
    });
  };

  const handleInput = (evt: ChangeEvent<HTMLInputElement>) => {
    const { type } = evt.target.dataset as { type?: "email" | "password" };
    const { value } = evt.target;
    if (!type) return;
    const newInput = { ...input, [type]: value };
    setInput(newInput);
  };
  const handleBack = () => {
    setEmailInputted(false);
  };

  const handlePasskeyLogin = async () => {
    if (!isWebAuthnSupported()) {
      toast.error(t("login.passkey_error_not_supported"));
      return;
    }

    setIsPasskeyLoading(true);
    try {
      const { challenge_id, options } = await passkeyLoginStart({}).unwrap();
      
      const credential = await startPasskeyLogin(options);
      
      await passkeyLoginFinish({ challenge_id, authentication: credential }).unwrap();
      
      toast.success(ct("tip.login"));
    } catch (error: any) {
      if (error.name === 'NotAllowedError') {
        toast.error(t("login.passkey_error_cancelled"));
      } else if (error.status === 404) {
        toast.error(t("login.passkey_error_no_passkey"));
      } else {
        toast.error(t("login.passkey_error_failed"));
      }
      console.error("Passkey login error:", error);
    } finally {
      setIsPasskeyLoading(false);
    }
  };

  const { email, password } = input;
  if (!loginConfigSuccess) return null;

  const { magic_link, who_can_sign_up: whoCanSignUp, passkey } = loginConfig;

  const enableMagicLink = enableSMTP && magic_link;
  const hideSocials = (enableMagicLink && emailInputted) || whoCanSignUp == "InvitationOnly";
  const showSignIn = !enableMagicLink || emailInputted;
  if (loadingSMTPStatus) return null;

  return (
    <div className="flex-center h-screen dark:bg-gray-700">
      <div className="relative py-8 px-10 shadow-md rounded-xl">
        {emailInputted && (
          <IconBack
            role="button"
            className="absolute left-7 top-8 w-10 h-10 stroke-gray-300"
            onClick={handleBack}
          />
        )}
        <div className="flex-center flex-col pb-6 w-full">
          <img
            src={logo || `${BASE_URL}/resource/organization/logo?t=${Date.now()}`}
            alt="logo"
            className="w-14 h-14 mb-3 md:mb-7 rounded-full"
          />
          <h2 className="font-semibold text-center text-balance text-2xl max-w-[420px] text-gray-800 dark:text-white">
            {t("login.title", { name: serverName })}
          </h2>
        </div>
        <form
          className="flex flex-col gap-5 md:min-w-[360px] w-full"
          autoComplete="false"
          onSubmit={handleLogin}
        >
          {!emailInputted && (
            <div className="flex flex-col gap-1">
              <StyledLabel>Email</StyledLabel>
              <Input
                autoFocus
                className="large"
                name="email"
                value={email}
                type="email"
                required
                placeholder={t("placeholder_email")}
                data-type="email"
                onChange={handleInput}
              />
            </div>
          )}
          {(!enableMagicLink || emailInputted) && (
            <div className="">
              <StyledLabel>Password</StyledLabel>
              <Input
                className="large"
                type="password"
                value={password}
                name="password"
                required
                data-type="password"
                onChange={handleInput}
                placeholder={t("placeholder_pwd")}
              />
            </div>
          )}
          {showSignIn ? (
            <Button type="submit" disabled={isLoading}>
              {isLoading ? "Signing" : t("sign_in")}
            </Button>
          ) : (
            <Button type="submit">{t("continue")}</Button>
          )}
        </form>
        <Divider content="OR" />
        <div className="socials flex flex-col gap-3">
          {passkey && (
            <ServerVersionChecker empty version="0.5.5">
              <Button 
                onClick={handlePasskeyLogin} 
                disabled={isPasskeyLoading || isLoading}
                className="w-full"
              >
                {isPasskeyLoading ? t("login.passkey_authenticating") : t("login.passkey")}
              </Button>
            </ServerVersionChecker>
          )}
          {emailInputted && <MagicLinkLogin email={input.email} />}
          {!hideSocials && <SocialLoginButtons />}
        </div>
        {whoCanSignUp === "EveryOne" && <SignUpLink />}
        <Downloads />
      </div>
      <SelectLanguage />
    </div>
  );
}
