import { getSessionUser } from "@/lib/auth";
import {
  sendSignupRecoveryEmailVerification,
  updateRecoveryEmailByEmail,
  verifySignupRecoveryEmailCode,
} from "@/lib/official-mail";

export const runtime = "nodejs";
export const dynamic = "force-dynamic";

const NO_STORE_HEADERS = { "Cache-Control": "no-store, max-age=0" };

type RecoveryEmailRequestBody = {
  challengeId?: number | null;
  code?: string;
  recoveryEmail?: string;
};

function mapRecoveryEmailError(error: unknown) {
  const code = error instanceof Error ? error.message : "system";

  if (code.startsWith("recovery-email-resend-cooldown:")) {
    const secondsRemaining = Math.max(1, Number(code.split(":")[1] ?? "1"));
    return {
      code: "recovery-email-resend-cooldown",
      message: `${secondsRemaining}초 뒤에 인증번호를 다시 받을 수 있습니다.`,
      status: 429,
    };
  }

  const messages: Record<string, { message: string; status: number }> = {
    expired: {
      message: "인증시간이 만료되었습니다. 인증번호를 다시 받아주세요.",
      status: 400,
    },
    "invalid-code": {
      message: "인증번호가 일치하지 않습니다.",
      status: 400,
    },
    "not-found": {
      message: "인증요청을 찾지 못했습니다. 인증번호를 다시 받아주세요.",
      status: 404,
    },
    "recovery-email-invalid": {
      message: "보조 이메일 형식이 올바르지 않습니다.",
      status: 400,
    },
    "recovery-email-must-differ": {
      message: "로그인 계정과 다른 이메일 주소를 입력해주세요.",
      status: 400,
    },
    "recovery-email-required": {
      message: "보조 이메일을 입력해주세요.",
      status: 400,
    },
    "recovery-email-send-failed": {
      message: "인증번호를 보내지 못했습니다. 잠시 후 다시 시도해주세요.",
      status: 502,
    },
    "recovery-email-unverified": {
      message: "보조 이메일 인증을 다시 진행해주세요.",
      status: 400,
    },
    required: {
      message: "인증번호를 입력해주세요.",
      status: 400,
    },
    "user-not-found": {
      message: "계정 정보를 찾지 못했습니다. 다시 로그인해주세요.",
      status: 404,
    },
  };
  const resolved = messages[code] ?? {
    message: "보조 이메일을 변경하지 못했습니다. 잠시 후 다시 시도해주세요.",
    status: 500,
  };

  return { code, ...resolved };
}

async function readBody(request: Request) {
  try {
    return (await request.json()) as RecoveryEmailRequestBody;
  } catch {
    return null;
  }
}

export async function POST(request: Request) {
  const user = await getSessionUser();

  if (!user) {
    return Response.json(
      { error: "unauthorized", message: "로그인이 필요합니다." },
      { status: 401, headers: NO_STORE_HEADERS },
    );
  }

  const body = await readBody(request);

  if (!body) {
    return Response.json(
      { error: "invalid-json", message: "요청 형식이 올바르지 않습니다." },
      { status: 400, headers: NO_STORE_HEADERS },
    );
  }

  try {
    const result = await sendSignupRecoveryEmailVerification({
      challengeId: body.challengeId ?? null,
      recoveryEmail: String(body.recoveryEmail ?? ""),
    });

    return Response.json(
      { ok: true, ...result },
      { headers: NO_STORE_HEADERS },
    );
  } catch (error) {
    console.error("Recovery email verification send failed", error);
    const resolved = mapRecoveryEmailError(error);
    return Response.json(
      { error: resolved.code, message: resolved.message },
      { status: resolved.status, headers: NO_STORE_HEADERS },
    );
  }
}

export async function PATCH(request: Request) {
  const user = await getSessionUser();

  if (!user) {
    return Response.json(
      { error: "unauthorized", message: "로그인이 필요합니다." },
      { status: 401, headers: NO_STORE_HEADERS },
    );
  }

  const body = await readBody(request);

  if (!body) {
    return Response.json(
      { error: "invalid-json", message: "요청 형식이 올바르지 않습니다." },
      { status: 400, headers: NO_STORE_HEADERS },
    );
  }

  try {
    const recoveryEmail = String(body.recoveryEmail ?? "");
    const verification = await verifySignupRecoveryEmailCode({
      challengeId: Number(body.challengeId ?? 0),
      code: String(body.code ?? ""),
      recoveryEmail,
    });
    const saved = await updateRecoveryEmailByEmail({
      accountEmail: user.email,
      recoveryEmail,
      recoveryVerificationId: verification.challengeId,
      recoveryVerificationToken: verification.verificationToken,
    });

    return Response.json(
      {
        ok: true,
        recoveryEmail: saved.email,
        verified: saved.verified,
        message: "보조 이메일을 저장했습니다.",
      },
      { headers: NO_STORE_HEADERS },
    );
  } catch (error) {
    console.error("Recovery email update failed", error);
    const resolved = mapRecoveryEmailError(error);
    return Response.json(
      { error: resolved.code, message: resolved.message },
      { status: resolved.status, headers: NO_STORE_HEADERS },
    );
  }
}
