"use client";

import { FormHelperText, IconButton, InputAdornment } from "@mui/material";
import Button from "@mui/material/Button";
import Stack from "@mui/material/Stack";
import TextField from "@mui/material/TextField";
import Typography from "@mui/material/Typography";
import { TFunction } from "i18next";
import { Session } from "next-auth";
import { getSession, signIn } from "next-auth/react";
import { useRouter } from "next/navigation";
import { useEffect, useState } from "react";
import { SubmitHandler, useForm } from "react-hook-form";
import { useTranslation } from "react-i18next";
import { SetupAxiosInterceptors } from "@/app/(main)/axios/axiosInstance";
import { useToken } from "@/app/(main)/axios/AxiosProvider";
import { Visibility, VisibilityOff } from "@mui/icons-material";

type LoginFields = {
  username: string;
  password: string;
};

type SessionWithAbilities =
  | ({
      abilities: string[];
      accessToken?: string;
    } & Session)
  | null;

// Error codes in https://next-auth.js.org/configuration/pages#sign-in-page
const getHumanFriendlyErrorMessage = (
  t: TFunction,
  serverError: string,
): string => {
  switch (serverError) {
    case "CredentialsSignin":
      return t("Invalid username or password.");
    case "Default":
    default:
      return t("Something went wrong. Please try again later.");
  }
};

const LoginForm: React.FC = () => {
  const { t } = useTranslation("login");
  const {
    register,
    handleSubmit,
    formState: { errors, isSubmitting },
  } = useForm<LoginFields>();

  const [serverError, setServerError] = useState<string>();

  const router = useRouter();
  const { setAccessToken } = useToken();

  const [showPassword, setShowPassword] = useState(false);
  const handleClickShowPassword = () => setShowPassword(!showPassword);
  const handleMouseDownPassword = () => setShowPassword(!showPassword);

  const onSubmit: SubmitHandler<LoginFields> = async (data) => {
    console.log(data);
    const res = await signIn("credentials", {
      redirect: false,
      ...data,
    });

    if (res?.error) {
      setServerError(res.error);
      return;
    }

    // set auth to local storage
    const session = (await getSession()) as SessionWithAbilities;
    // @ts-ignore
    window.localStorage.setItem("accessToken", session?.accessToken ?? "");
    setAccessToken(session?.accessToken ?? null);
    SetupAxiosInterceptors(session?.accessToken ?? null);
    // console.log(session)
    window.localStorage.setItem(
      "abilities",
      JSON.stringify(session?.abilities),
    );

    const callbackUrl =
      new URLSearchParams(window.location.search).get("callbackUrl") || "/";

    router.push(callbackUrl);
  };

  useEffect(() => {
    // clean abilities before login
    window.localStorage.removeItem("abilities");
  }, []);

  return (
    <Stack
      spacing={3}
      margin={5}
      component="form"
      onSubmit={handleSubmit(onSubmit)}
    >
      <Typography variant="h1">{t("Sign In")}</Typography>
      <TextField
        label={t("Username")}
        {...register("username", { required: t("Please enter a username") })}
        error={Boolean(errors.username)}
        helperText={errors.username?.message}
      />
      <TextField
        label={t("Password")}
        type={showPassword ? "text" : "password"}
        {...register("password", { required: t("Please enter a password") })}
        error={Boolean(errors.password)}
        helperText={errors.password?.message}
        InputProps={{
          endAdornment: (
            <InputAdornment position="end">
              <IconButton
                aria-label={t("toggle password visibility")}
                onClick={handleClickShowPassword}
                onMouseDown={handleMouseDownPassword}
              >
                {showPassword ? <Visibility /> : <VisibilityOff />}
              </IconButton>
            </InputAdornment>
          ),
        }}
      />
      {serverError && (
        <FormHelperText error>
          {getHumanFriendlyErrorMessage(t, serverError)}
        </FormHelperText>
      )}
      <Button
        variant="contained"
        size="large"
        type="submit"
        disabled={isSubmitting}
      >
        {t("Login")}
      </Button>
    </Stack>
  );
};

export default LoginForm;
