import { sendOtt } from "@/accounts/api/user";
import { PAGES } from "@/accounts/constants/pages";
import { sharedCryptoWorker } from "@/base/crypto";
import log from "@/base/log";
import { ensure } from "@/utils/ensure";
import { VerticallyCentered } from "@ente/shared/components/Container";
import FormPaper from "@ente/shared/components/Form/FormPaper";
import FormPaperFooter from "@ente/shared/components/Form/FormPaper/Footer";
import FormPaperTitle from "@ente/shared/components/Form/FormPaper/Title";
import LinkButton from "@ente/shared/components/LinkButton";
import SingleInputForm, {
    type SingleInputFormProps,
} from "@ente/shared/components/SingleInputForm";
import {
    decryptAndStoreToken,
    saveKeyInSessionStore,
} from "@ente/shared/crypto/helpers";
import { LS_KEYS, getData, setData } from "@ente/shared/storage/localStorage";
import { SESSION_KEYS, getKey } from "@ente/shared/storage/sessionStorage";
import type { KeyAttributes, User } from "@ente/shared/user/types";
import { t } from "i18next";
import { useRouter } from "next/router";
import { useEffect, useState } from "react";
import { appHomeRoute, stashRedirect } from "../services/redirect";
import type { PageProps } from "../types/page";

const bip39 = require("bip39");
// mobile client library only supports english.
bip39.setDefaultWordlist("english");

const Page: React.FC<PageProps> = ({ appContext }) => {
    const { showNavBar, setDialogBoxAttributesV2 } = appContext;

    const [keyAttributes, setKeyAttributes] = useState<
        KeyAttributes | undefined
    >();

    const router = useRouter();

    useEffect(() => {
        const user: User = getData(LS_KEYS.USER);
        const keyAttributes: KeyAttributes = getData(LS_KEYS.KEY_ATTRIBUTES);
        const key = getKey(SESSION_KEYS.ENCRYPTION_KEY);
        if (!user?.email) {
            router.push("/");
            return;
        }
        if (!user?.encryptedToken && !user?.token) {
            sendOtt(user.email);
            stashRedirect(PAGES.RECOVER);
            router.push(PAGES.VERIFY);
            return;
        }
        if (!keyAttributes) {
            router.push(PAGES.GENERATE);
        } else if (key) {
            router.push(appHomeRoute);
        } else {
            setKeyAttributes(keyAttributes);
        }
        showNavBar(true);
    }, []);

    const recover: SingleInputFormProps["callback"] = async (
        recoveryKey: string,
        setFieldError,
    ) => {
        try {
            recoveryKey = recoveryKey
                .trim()
                .split(" ")
                .map((part) => part.trim())
                .filter((part) => !!part)
                .join(" ");
            // check if user is entering mnemonic recovery key
            if (recoveryKey.indexOf(" ") > 0) {
                if (recoveryKey.split(" ").length !== 24) {
                    throw new Error("recovery code should have 24 words");
                }
                recoveryKey = bip39.mnemonicToEntropy(recoveryKey);
            }
            const cryptoWorker = await sharedCryptoWorker();
            const keyAttr = ensure(keyAttributes);
            const masterKey = await cryptoWorker.decryptB64(
                keyAttr.masterKeyEncryptedWithRecoveryKey,
                keyAttr.masterKeyDecryptionNonce,
                await cryptoWorker.fromHex(recoveryKey),
            );
            await saveKeyInSessionStore(SESSION_KEYS.ENCRYPTION_KEY, masterKey);
            await decryptAndStoreToken(keyAttr, masterKey);

            setData(LS_KEYS.SHOW_BACK_BUTTON, { value: false });
            router.push(PAGES.CHANGE_PASSWORD);
        } catch (e) {
            log.error("password recovery failed", e);
            setFieldError(t("INCORRECT_RECOVERY_KEY"));
        }
    };

    const showNoRecoveryKeyMessage = () =>
        setDialogBoxAttributesV2({
            title: t("SORRY"),
            close: {},
            content: t("NO_RECOVERY_KEY_MESSAGE"),
        });

    return (
        <VerticallyCentered>
            <FormPaper>
                <FormPaperTitle>{t("RECOVER_ACCOUNT")}</FormPaperTitle>
                <SingleInputForm
                    callback={recover}
                    fieldType="text"
                    placeholder={t("RECOVERY_KEY_HINT")}
                    buttonText={t("RECOVER")}
                    disableAutoComplete
                />
                <FormPaperFooter style={{ justifyContent: "space-between" }}>
                    <LinkButton onClick={showNoRecoveryKeyMessage}>
                        {t("NO_RECOVERY_KEY")}
                    </LinkButton>
                    <LinkButton onClick={router.back}>
                        {t("GO_BACK")}
                    </LinkButton>
                </FormPaperFooter>
            </FormPaper>
        </VerticallyCentered>
    );
};

export default Page;
