import { FormEvent, useState } from "react";
import { Link, Navigate } from "react-router-dom";

import AuthCard from "@/components/auth/AuthCard";
import CodeInput, { CODE_LENGTH } from "@/components/CodeInput";
import { useAuthActions } from "@/hooks/useAuthActions";
import { useAuthFlow } from "@/hooks/useAuthFlow";
import { useAuthStore } from "@/stores/useAuthStore";

type Step = "code" | "email";

const LoginCodePage = () => {
    const { requestLoginCode, verifyLoginCode } = useAuthActions();
    const {
        flowState,
        from,
        initialEmail,
        isAdminUser,
        isAuthenticated,
        redirectAfterLogin,
    } = useAuthFlow();
    const { error, isLoggingIn } = useAuthStore();
    const [step, setStep] = useState<Step>("email");
    const [email, setEmail] = useState(initialEmail);
    const [code, setCode] = useState("");
    const [notice, setNotice] = useState("");

    const sendCode = async (resent = false) => {
        const sent = await requestLoginCode(email);

        if (sent) {
            setCode("");
            setStep("code");
            setNotice(resent ? "We sent you a new code." : "");
        }
    };

    const handleEmail = async (event: FormEvent<HTMLFormElement>) => {
        event.preventDefault();

        await sendCode();
    };

    const verify = async (submitted: string) => {
        const authenticated = await verifyLoginCode({
            code: submitted,
            email,
        });

        if (authenticated) {
            redirectAfterLogin(authenticated);
        }
    };

    const handleCode = async (event: FormEvent<HTMLFormElement>) => {
        event.preventDefault();

        await verify(code);
    };

    if (isAuthenticated) {
        return isAdminUser ? null : <Navigate to={from} replace />;
    }

    // Step two: the code we just emailed.
    if (step === "code") {
        return (
            <AuthCard
                error={error}
                footer={
                    <button
                        className="login-link"
                        onClick={() => {
                            setNotice("");
                            setStep("email");
                        }}
                        type="button"
                    >
                        Use a different email
                    </button>
                }
                notice={notice}
                subtitle={
                    <>
                        If <strong>{email}</strong> belongs to an account, a
                        6-digit code is on its way. It expires in 10 minutes.
                    </>
                }
                title="Check your email"
            >
                <form className="login-form" onSubmit={handleCode}>
                    <CodeInput
                        autoFocus
                        disabled={isLoggingIn}
                        label="Login code"
                        onChange={setCode}
                        onComplete={(submitted) => {
                            if (!isLoggingIn) {
                                void verify(submitted);
                            }
                        }}
                        value={code}
                    />

                    <button
                        className="btn btn-dark w-100"
                        disabled={isLoggingIn || code.length < CODE_LENGTH}
                        type="submit"
                    >
                        {isLoggingIn ? "Please wait..." : "Sign In"}
                    </button>

                    <p className="login-form__alt">
                        <button
                            className="login-link"
                            disabled={isLoggingIn}
                            onClick={() => void sendCode(true)}
                            type="button"
                        >
                            Resend code
                        </button>
                    </p>
                </form>
            </AuthCard>
        );
    }

    return (
        <AuthCard
            error={error}
            footer={
                <Link
                    className="login-link"
                    state={flowState(email)}
                    to="/login"
                >
                    Back to sign in
                </Link>
            }
            subtitle="We'll email you a one-time code so you can sign in without a password."
            title="Sign in with a code"
        >
            <form className="login-form" onSubmit={handleEmail}>
                <label className="form-field d-block">
                    <span>Email</span>
                    <input
                        autoComplete="email"
                        autoFocus
                        className="form-control"
                        onChange={(event) => setEmail(event.target.value)}
                        required
                        type="email"
                        value={email}
                    />
                </label>

                <button
                    className="btn btn-dark w-100"
                    disabled={isLoggingIn || !email}
                    type="submit"
                >
                    {isLoggingIn ? "Please wait..." : "Send Login Code"}
                </button>
            </form>
        </AuthCard>
    );
};

export default LoginCodePage;
