import { useState } from "react";

import CodeInput, { CODE_LENGTH } from "@/components/CodeInput";
import PageHeader from "@/components/PageHeader";
import { useLogout } from "@/hooks/useLogout";
import { useTwoFactorActions } from "@/hooks/useTwoFactorActions";
import useAxios from "@/hooks/useAxios";
import { profileService } from "@/services/profileService";
import { useAuthStore } from "@/stores/useAuthStore";
import { usePortalProfileStore } from "@/stores/usePortalProfileStore";
import { notify } from "@/stores/useToastStore";
import { useTwoFactorStore } from "@/stores/useTwoFactorStore";
import logoutIcon from "../../images/icons/log-out.svg";

interface PasswordForm {
    confirmPassword: string;
    currentPassword: string;
    newPassword: string;
}

const initialPasswordForm: PasswordForm = {
    confirmPassword: "",
    currentPassword: "",
    newPassword: "",
};

const SettingsPage = () => {
    const axios = useAxios();
    const logOut = useLogout();
    const {
        confirmTwoFactor,
        disableTwoFactor,
        enableTwoFactor,
        loadRecoveryCodes,
    } = useTwoFactorActions();
    const contactEmail = usePortalProfileStore(
        (state) => state.profile.billingEmail,
    );
    const user = useAuthStore((state) => state.user);
    const twoFactor = useTwoFactorStore();
    const [form, setForm] = useState<PasswordForm>(initialPasswordForm);
    const [showRecoveryCodes, setShowRecoveryCodes] = useState(false);
    const [twoFactorCode, setTwoFactorCode] = useState("");
    const [isConfirmingPassword, setIsConfirmingPassword] = useState(false);
    const [setupPassword, setSetupPassword] = useState("");
    const [isDisabling, setIsDisabling] = useState(false);
    const [disableCode, setDisableCode] = useState("");
    const [isSaving, setIsSaving] = useState(false);
    const [message, setMessage] = useState("");

    const updateField = (field: keyof PasswordForm, value: string) => {
        setForm((current) => ({ ...current, [field]: value }));
        setMessage("");
    };

    const updatePassword = async () => {
        if (!form.currentPassword) {
            setMessage("Enter your current password.");
            return;
        }

        if (form.newPassword.length < 12) {
            setMessage("Use at least 12 characters.");
            return;
        }

        if (form.newPassword !== form.confirmPassword) {
            setMessage("New password and confirmation must match.");
            return;
        }

        setIsSaving(true);
        setMessage("");

        try {
            await profileService.update(axios, {
                current_password: form.currentPassword,
                password: form.newPassword,
                password_confirmation: form.confirmPassword,
            });

            setForm(initialPasswordForm);
            notify("Password updated.");
        } catch {
            setMessage(
                "Unable to update password. Check your current password.",
            );
        } finally {
            setIsSaving(false);
        }
    };

    const startTwoFactorSetup = async () => {
        const setup = await enableTwoFactor(setupPassword);

        if (setup) {
            setShowRecoveryCodes(false);
            setTwoFactorCode("");
            setSetupPassword("");
            setIsConfirmingPassword(false);
        }
    };

    const confirmSetup = async () => {
        const setup = await confirmTwoFactor(twoFactorCode);

        if (setup) {
            setShowRecoveryCodes(true);
            setTwoFactorCode("");
        }
    };

    const confirmDisable = async () => {
        const disabled = await disableTwoFactor(disableCode);

        if (disabled) {
            setShowRecoveryCodes(false);
            setIsDisabling(false);
            setDisableCode("");
        }
    };

    const toggleRecoveryCodes = async () => {
        if (showRecoveryCodes) {
            setShowRecoveryCodes(false);
            return;
        }

        if (!twoFactor.recoveryCodes.length) {
            const codes = await loadRecoveryCodes();

            if (!codes) {
                return;
            }
        }

        setShowRecoveryCodes(true);
    };

    return (
        <article className="portal-card account-page settings-page">
            <PageHeader
                eyebrowParent="Account"
                eyebrowCurrent="Settings"
                title="Account settings"
                description="Manage your password, sessions, and notifications."
            />

            <section className="account-panel settings-panel">
                <h2 className="account-section-title">Update password</h2>
                <p className="account-section-copy">
                    Use at least 12 characters with a mix of letters, numbers,
                    and symbols
                </p>

                <div className="account-divider" />

                <form
                    className="settings-form d-flex flex-column"
                    onSubmit={(event) => {
                        event.preventDefault();
                        void updatePassword();
                    }}
                >
                    <label className="form-field d-block">
                        <span>Current Password</span>
                        <input
                            className="form-control"
                            onChange={(event) =>
                                updateField(
                                    "currentPassword",
                                    event.target.value,
                                )
                            }
                            type="password"
                            value={form.currentPassword}
                        />
                    </label>

                    <label className="form-field d-block">
                        <span>New Password</span>
                        <input
                            className="form-control"
                            onChange={(event) =>
                                updateField("newPassword", event.target.value)
                            }
                            placeholder="At least 12 characters"
                            type="password"
                            value={form.newPassword}
                        />
                    </label>

                    <label className="form-field d-block">
                        <span>Confirm New Password</span>
                        <input
                            className="form-control"
                            onChange={(event) =>
                                updateField(
                                    "confirmPassword",
                                    event.target.value,
                                )
                            }
                            placeholder="Re-enter new password"
                            type="password"
                            value={form.confirmPassword}
                        />
                    </label>

                    <button
                        className="btn btn-outline-dark settings-form__button"
                        disabled={isSaving}
                        type="submit"
                    >
                        {isSaving ? "Updating..." : "Update Password"}
                    </button>

                    {message ? (
                        <p
                            className="settings-form__message mb-0"
                            role="status"
                        >
                            {message}
                        </p>
                    ) : null}
                </form>
            </section>

            <section className="account-panel settings-panel">
                <h2 className="account-section-title">
                    Two-factor authentication
                </h2>
                <p className="account-section-copy">
                    Add an authenticator app code to protect this account.
                </p>

                <div className="account-divider" />

                {twoFactor.error ? (
                    <p className="alert alert-danger mb-4" role="alert">
                        {twoFactor.error}
                    </p>
                ) : null}

                {twoFactor.message ? (
                    <p className="alert alert-success mb-4" role="status">
                        {twoFactor.message}
                    </p>
                ) : null}

                {user?.two_factor_enabled ? (
                    <div className="two-factor-block d-flex flex-column gap-4">
                        <p className="settings-session__email">
                            Status: <strong>Enabled</strong>
                        </p>

                        {isDisabling ? (
                            <form
                                className="d-flex flex-column gap-4"
                                onSubmit={(event) => {
                                    event.preventDefault();
                                    void confirmDisable();
                                }}
                            >
                                <p className="account-section-copy mb-0">
                                    Enter the current code from your
                                    authenticator app to turn two-factor
                                    authentication off.
                                </p>

                                <div className="form-field">
                                    <span>Authenticator Code</span>
                                    <CodeInput
                                        autoFocus
                                        disabled={twoFactor.isLoading}
                                        label="Authenticator code"
                                        onChange={setDisableCode}
                                        value={disableCode}
                                    />
                                </div>

                                <div className="d-flex flex-column flex-sm-row gap-3">
                                    <button
                                        className="btn btn-outline-dark settings-form__button"
                                        disabled={
                                            twoFactor.isLoading ||
                                            disableCode.length < CODE_LENGTH
                                        }
                                        type="submit"
                                    >
                                        {twoFactor.isLoading
                                            ? "Disabling..."
                                            : "Confirm & Disable"}
                                    </button>

                                    <button
                                        className="btn btn-outline-dark settings-form__button"
                                        disabled={twoFactor.isLoading}
                                        type="button"
                                        onClick={() => {
                                            setIsDisabling(false);
                                            setDisableCode("");
                                        }}
                                    >
                                        Cancel
                                    </button>
                                </div>
                            </form>
                        ) : null}

                        {showRecoveryCodes && twoFactor.recoveryCodes.length ? (
                            <div className="two-factor-codes">
                                {twoFactor.recoveryCodes.map((code) => (
                                    <code key={code}>{code}</code>
                                ))}
                            </div>
                        ) : null}

                        <div className="d-flex flex-column flex-sm-row gap-3">
                            {showRecoveryCodes ? (
                                <button
                                    className="btn btn-outline-dark settings-form__button"
                                    disabled={twoFactor.isLoading}
                                    type="button"
                                    onClick={() => setShowRecoveryCodes(false)}
                                >
                                    {twoFactor.isLoading
                                        ? "Please wait..."
                                        : "Hide Recovery Codes"}
                                </button>
                            ) : (
                                <button
                                    className="btn btn-outline-dark settings-form__button"
                                    disabled={twoFactor.isLoading}
                                    type="button"
                                    onClick={() => void toggleRecoveryCodes()}
                                >
                                    {twoFactor.isLoading
                                        ? "Loading..."
                                        : "Show Recovery Codes"}
                                </button>
                            )}

                            {isDisabling ? null : (
                                <button
                                    className="btn btn-outline-dark settings-form__button"
                                    disabled={twoFactor.isLoading}
                                    type="button"
                                    onClick={() => setIsDisabling(true)}
                                >
                                    Disable Two-Factor
                                </button>
                            )}
                        </div>
                    </div>
                ) : twoFactor.secretKey ? (
                    <div className="two-factor-block d-flex flex-column gap-4">
                        {twoFactor.qrCode ? (
                            <div
                                className="two-factor-qr"
                                dangerouslySetInnerHTML={{
                                    __html: twoFactor.qrCode,
                                }}
                            />
                        ) : null}

                        <label className="form-field d-block">
                            <span>Secret Key</span>
                            <input
                                className="form-control"
                                readOnly
                                value={twoFactor.secretKey}
                            />
                        </label>

                        <div className="form-field">
                            <span>Authenticator Code</span>
                            <CodeInput
                                disabled={twoFactor.isLoading}
                                label="Authenticator code"
                                onChange={setTwoFactorCode}
                                value={twoFactorCode}
                            />
                        </div>

                        <button
                            className="btn btn-outline-dark settings-form__button"
                            disabled={
                                twoFactor.isLoading ||
                                twoFactorCode.length < CODE_LENGTH
                            }
                            type="button"
                            onClick={() => void confirmSetup()}
                        >
                            {twoFactor.isLoading
                                ? "Confirming..."
                                : "Confirm Two-Factor"}
                        </button>
                    </div>
                ) : isConfirmingPassword ? (
                    <form
                        className="two-factor-block d-flex flex-column gap-4"
                        onSubmit={(event) => {
                            event.preventDefault();
                            void startTwoFactorSetup();
                        }}
                    >
                        <p className="account-section-copy mb-0">
                            Confirm your password to set up an authenticator
                            app.
                        </p>

                        <label className="form-field d-block">
                            <span>Current Password</span>
                            <input
                                autoComplete="current-password"
                                autoFocus
                                className="form-control"
                                onChange={(event) =>
                                    setSetupPassword(event.target.value)
                                }
                                required
                                type="password"
                                value={setupPassword}
                            />
                        </label>

                        <div className="d-flex flex-column flex-sm-row gap-3">
                            <button
                                className="btn btn-outline-dark settings-form__button"
                                disabled={twoFactor.isLoading || !setupPassword}
                                type="submit"
                            >
                                {twoFactor.isLoading
                                    ? "Confirming..."
                                    : "Continue"}
                            </button>

                            <button
                                className="btn btn-outline-dark settings-form__button"
                                disabled={twoFactor.isLoading}
                                type="button"
                                onClick={() => {
                                    setIsConfirmingPassword(false);
                                    setSetupPassword("");
                                }}
                            >
                                Cancel
                            </button>
                        </div>
                    </form>
                ) : (
                    <button
                        className="btn btn-outline-dark settings-form__button"
                        disabled={twoFactor.isLoading}
                        type="button"
                        onClick={() => setIsConfirmingPassword(true)}
                    >
                        Enable Two-Factor
                    </button>
                )}
            </section>

            <section className="account-panel settings-panel">
                <h2 className="account-section-title">Sign out</h2>
                <p className="account-section-copy">
                    Sign out of this browser session
                </p>

                <div className="account-divider" />

                <div className="settings-session d-flex flex-column flex-lg-row align-items-lg-center justify-content-lg-between gap-4">
                    <div>
                        <p className="settings-session__email">
                            Signed in as <strong>{contactEmail}</strong>
                        </p>
                        <p className="settings-session__meta">
                            Last sign-in: today at 9:14 AM &middot; Chrome on
                            macOS
                        </p>
                    </div>

                    <button
                        className="btn btn-outline-dark d-inline-flex align-items-center justify-content-center gap-2 settings-logout"
                        type="button"
                        onClick={() => void logOut()}
                    >
                        <span>Log Out</span>
                        <img src={logoutIcon} alt="" aria-hidden="true" />
                    </button>
                </div>

                <p className="visually-hidden" aria-live="polite" />
            </section>
        </article>
    );
};

export default SettingsPage;
