"use server";

import { revalidatePath } from "next/cache";
import { AppwriteException, AuthenticatorType } from "node-appwrite";

import { createSessionClient } from "./server";

export type MfaEnrollState = {
  ok: boolean;
  error?: string;
  /** otpauth:// URI for QR; only set on enroll start. */
  uri?: string;
  /** Plain TOTP secret as a fallback if the QR can't be scanned. */
  secret?: string;
};

export const initialMfaEnrollState: MfaEnrollState = { ok: false };

export type MfaActionState = {
  ok: boolean;
  error?: string;
  /** Recovery codes returned right after enable; show once, never stored again. */
  recoveryCodes?: string[];
};

export const initialMfaActionState: MfaActionState = { ok: false };

function appwriteError(e: unknown, fallback = "Beklenmeyen bir hata oluştu."): string {
  if (e instanceof AppwriteException) return e.message || fallback;
  return process.env.NODE_ENV !== "production" && e instanceof Error
    ? `${fallback} (${e.message})`
    : fallback;
}

/**
 * Step 1 of TOTP enroll: produce a fresh secret and otpauth URI for the
 * user's authenticator app. Calling this when an authenticator already
 * exists yields the same secret back.
 */
export async function startMfaEnrollAction(): Promise<MfaEnrollState> {
  try {
    const { account } = await createSessionClient();
    const res = await account.createMFAAuthenticator(AuthenticatorType.Totp);
    return { ok: true, uri: res.uri, secret: res.secret };
  } catch (e) {
    return { ok: false, error: appwriteError(e, "MFA başlatılamadı.") };
  }
}

/**
 * Step 2 of TOTP enroll: user scanned the QR, opened their authenticator,
 * typed the 6-digit code. We verify, then flip account.mfa = true so
 * future sign-ins require the second factor. Returns recovery codes —
 * shown once.
 */
export async function verifyMfaEnrollAction(
  _prev: MfaActionState,
  formData: FormData,
): Promise<MfaActionState> {
  const otp = String(formData.get("otp") ?? "").trim();
  if (!otp || otp.length < 6) {
    return { ok: false, error: "6 haneli kodu girin." };
  }
  try {
    const { account } = await createSessionClient();
    await account.updateMFAAuthenticator(AuthenticatorType.Totp, otp);
    await account.updateMFA(true);
    const codes = await account.createMFARecoveryCodes();
    return { ok: true, recoveryCodes: codes.recoveryCodes };
  } catch (e) {
    return { ok: false, error: appwriteError(e, "Doğrulanamadı.") };
  }
}

/**
 * Disable MFA: turn the account flag off and remove the TOTP authenticator
 * so the user can re-enroll later with a fresh secret. Requires a current
 * authenticated session.
 */
export async function disableMfaAction(): Promise<MfaActionState> {
  try {
    const { account } = await createSessionClient();
    await account.updateMFA(false);
    try {
      await account.deleteMFAAuthenticator(AuthenticatorType.Totp);
    } catch {
      // Already removed — ignore.
    }
    revalidatePath("/settings/security");
    return { ok: true };
  } catch (e) {
    return { ok: false, error: appwriteError(e, "Devre dışı bırakılamadı.") };
  }
}

export async function regenerateRecoveryCodesAction(): Promise<MfaActionState> {
  try {
    const { account } = await createSessionClient();
    const codes = await account.updateMFARecoveryCodes();
    return { ok: true, recoveryCodes: codes.recoveryCodes };
  } catch (e) {
    return { ok: false, error: appwriteError(e, "Yedek kodlar üretilemedi.") };
  }
}
