import { getSessionUser } from "@/lib/auth";
import {
  createManagedMemberWithImmediateChargeByOwnerEmail,
  deleteManagedMemberWithBillingByOwnerEmail,
} from "@/lib/mail-member-billing";
import {
  getManagedMembersByOwnerEmail,
  updateManagedMemberByOwnerEmail,
} from "@/lib/mail-automation";
import { assertMailBillingManagementAccessByEmail } from "@/lib/toss-pay";

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

function mapCreateMemberError(error: unknown) {
  const code = error instanceof Error ? error.message : "member-create-failed";

  switch (code) {
    case "billing-management-forbidden":
      return {
        error: code,
        message: "멤버 관리는 대표 관리자 계정에서만 진행할 수 있습니다.",
        status: 403,
      };
    case "growth-plan-required":
      return {
        error: code,
        message: "새 멤버 추가는 성장 플랜 구독 중일 때만 가능합니다.",
        status: 409,
      };
    case "billing-profile-inactive":
      return {
        error: code,
        message: "등록된 결제수단을 먼저 확인해 주세요.",
        status: 409,
      };
    case "member-required":
      return {
        error: code,
        message: "멤버 이름, 메일 아이디, 비밀번호를 모두 입력해 주세요.",
        status: 400,
      };
    case "member-display-name-too-long":
      return {
        error: code,
        message: "멤버 이름은 191자 이내로 입력해 주세요.",
        status: 400,
      };
    case "invalid-local-part":
      return {
        error: code,
        message: "메일 아이디는 영문 소문자, 숫자, 점(.), 하이픈(-), 밑줄(_)만 사용할 수 있습니다.",
        status: 400,
      };
    case "member-mailbox-taken":
      return {
        error: code,
        message: "이미 사용 중인 멤버 메일 주소입니다.",
        status: 409,
      };
    case "mailcow-auth-failed":
      return {
        error: code,
        message: "메일 서버 인증에 실패했습니다. 잠시 후 다시 시도해 주세요.",
        status: 502,
      };
    case "member-charge-failed":
      return {
        error: code,
        message: "멤버 추가 결제 승인에 실패했습니다. 결제수단 상태를 확인해 주세요.",
        status: 402,
      };
    case "member-create-refunded":
      return {
        error: code,
        message: "멤버 생성 중 오류가 발생해 방금 결제는 자동으로 취소했습니다.",
        status: 500,
      };
    case "member-charge-refund-failed":
      return {
        error: code,
        message:
          "멤버 생성에 실패했고 결제 취소까지 자동 완료되지 않았습니다. 결제내역을 바로 확인해 주세요.",
        status: 500,
      };
    default:
      return {
        error: code,
        message: "멤버 메일함 추가 중 오류가 발생했습니다.",
        status: 500,
      };
  }
}

function mapManageMemberError(error: unknown) {
  const code = error instanceof Error ? error.message : "member-update-failed";
  const messages: Record<string, string> = {
    "billing-management-forbidden": "멤버 관리는 대표 관리자 계정에서만 진행할 수 있습니다.",
    "mailbox-auth-missing": "멤버 계정의 보안 정보를 확인할 수 없습니다.",
    "mailcow-auth-failed": "메일 서버 인증에 실패했습니다. 잠시 후 다시 시도해 주세요.",
    "member-disabled": "사용이 중지된 멤버 계정입니다.",
    "member-display-name-too-long": "멤버 이름은 191자 이내로 입력해 주세요.",
    "member-not-found": "멤버 계정을 찾지 못했습니다.",
    "member-required": "멤버 정보를 확인해 주세요.",
  };

  return {
    code,
    message:
      messages[code] ??
      (code.startsWith("mailcow-")
        ? "메일 서버에서 멤버 계정을 처리하지 못했습니다. 잠시 후 다시 시도해 주세요."
        : "멤버 계정을 처리하지 못했습니다."),
    status:
      code === "billing-management-forbidden"
        ? 403
        : code === "member-not-found"
          ? 404
          : code.startsWith("mailcow-")
            ? 502
            : 400,
  };
}

export async function GET() {
  const user = await getSessionUser();

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

  try {
    await assertMailBillingManagementAccessByEmail(user.email);
    return Response.json(
      { ok: true, members: await getManagedMembersByOwnerEmail(user.email) },
      { headers: NO_STORE_HEADERS },
    );
  } catch (error) {
    const mapped = mapManageMemberError(error);
    return Response.json(
      { error: mapped.code, message: mapped.message },
      { status: mapped.status, headers: NO_STORE_HEADERS },
    );
  }
}

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

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

  const body = await request.json().catch(() => null);
  const displayName = typeof body?.displayName === "string" ? body.displayName : "";
  const localPart = typeof body?.localPart === "string" ? body.localPart : "";
  const password = typeof body?.password === "string" ? body.password : "";
  const passwordConfirm = typeof body?.passwordConfirm === "string" ? body.passwordConfirm : "";

  if (password.trim() !== passwordConfirm.trim()) {
    return Response.json(
      {
        error: "member-password-mismatch",
        message: "멤버 메일 비밀번호와 확인 값이 서로 다릅니다.",
      },
      { status: 400 },
    );
  }

  try {
    await assertMailBillingManagementAccessByEmail(user.email);

    const charge = await createManagedMemberWithImmediateChargeByOwnerEmail(user.email, {
      displayName,
      localPart,
      password,
    });

    return Response.json({
      charge,
      message: "멤버 메일함을 추가했습니다.",
      ok: true,
    });
  } catch (error) {
    const mapped = mapCreateMemberError(error);

    return Response.json(
      {
        error: mapped.error,
        message: mapped.message,
      },
      { status: mapped.status },
    );
  }
}

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 request.json().catch(() => null);
  const memberId = Number(body?.memberId);
  const displayName = typeof body?.displayName === "string" ? body.displayName : "";
  const password = typeof body?.password === "string" ? body.password : "";
  const passwordConfirm =
    typeof body?.passwordConfirm === "string" ? body.passwordConfirm : "";

  if (password.trim() && password.trim() !== passwordConfirm.trim()) {
    return Response.json(
      {
        error: "member-password-mismatch",
        message: "멤버 메일 비밀번호와 확인 값이 서로 다릅니다.",
      },
      { status: 400, headers: NO_STORE_HEADERS },
    );
  }

  try {
    await assertMailBillingManagementAccessByEmail(user.email);
    await updateManagedMemberByOwnerEmail(user.email, {
      displayName,
      memberId,
      password,
    });
    return Response.json(
      {
        message: "멤버 계정 정보를 변경했습니다.",
        members: await getManagedMembersByOwnerEmail(user.email),
        ok: true,
      },
      { headers: NO_STORE_HEADERS },
    );
  } catch (error) {
    const mapped = mapManageMemberError(error);
    return Response.json(
      { error: mapped.code, message: mapped.message },
      { status: mapped.status, headers: NO_STORE_HEADERS },
    );
  }
}

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

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

  const body = await request.json().catch(() => null);
  const memberId = Number(body?.memberId);

  try {
    await assertMailBillingManagementAccessByEmail(user.email);
    await deleteManagedMemberWithBillingByOwnerEmail(user.email, memberId);
    return Response.json(
      {
        message: "멤버 계정을 삭제했습니다.",
        members: await getManagedMembersByOwnerEmail(user.email),
        ok: true,
      },
      { headers: NO_STORE_HEADERS },
    );
  } catch (error) {
    const mapped = mapManageMemberError(error);
    return Response.json(
      { error: mapped.code, message: mapped.message },
      { status: mapped.status, headers: NO_STORE_HEADERS },
    );
  }
}
