export type RegistrationErrorReason =
  | "invite_not_found"
  | "invite_expired"
  | "invite_disabled"
  | "invite_exhausted"
  | "stage_limit_reached"
  | "email_already_registered"
  | "challenge_invalid"
  | "challenge_expired"
  | "privacy_consent_required"
  | "privacy_notice_version_invalid"
  | "profile_invalid"
  | "idempotency_conflict"
  | "registration_login_required"
  | "login_registration_required"
  | "account_suspended"
  | "login_admin_required"
  | "admin_not_allowed"
  | "resend_too_soon"
  | "too_many_attempts"
  | "csrf_invalid"
  | "deletion_confirmation_invalid"
  | "session_invalid";

export type RegistrationErrorCode =
  | "REGISTRATION_REJECTED"
  | "REGISTRATION_REQUEST_INVALID"
  | "IDEMPOTENCY_KEY_CONFLICT"
  | "AUTH_ENTRY_REJECTED"
  | "AUTH_RATE_LIMITED"
  | "AUTH_CSRF_INVALID"
  | "AUTH_SESSION_INVALID";

export class RegistrationError extends Error {
  readonly code: RegistrationErrorCode;
  readonly httpStatus: 400 | 401 | 403 | 409 | 429;
  readonly reason: RegistrationErrorReason;

  constructor(code: RegistrationErrorCode, reason: RegistrationErrorReason) {
    super(code);
    this.code = code;
    this.httpStatus = code === "REGISTRATION_REQUEST_INVALID"
      ? 400
      : code === "AUTH_SESSION_INVALID"
        ? 401
      : code === "AUTH_CSRF_INVALID"
        ? 403
        : code === "AUTH_RATE_LIMITED"
          ? 429
          : 409;
    this.reason = reason;
  }
}

export function registrationFieldError(reason: RegistrationErrorReason) {
  const entries: Record<RegistrationErrorReason, { field: string; message_key: string }> = {
    challenge_expired: { field: "verification_code", message_key: "auth.challenge.expired" },
    challenge_invalid: { field: "verification_code", message_key: "auth.challenge.invalid" },
    email_already_registered: { field: "email", message_key: "auth.email.already_registered" },
    idempotency_conflict: { field: "idempotency_key", message_key: "request.idempotency_conflict" },
    invite_disabled: { field: "invite_code", message_key: "auth.invite.disabled" },
    invite_exhausted: { field: "invite_code", message_key: "auth.invite.exhausted" },
    invite_expired: { field: "invite_code", message_key: "auth.invite.expired" },
    invite_not_found: { field: "invite_code", message_key: "auth.invite.not_found" },
    privacy_consent_required: { field: "privacy_consent_accepted", message_key: "auth.privacy.consent_required" },
    privacy_notice_version_invalid: { field: "privacy_notice_version", message_key: "auth.privacy.notice_version_invalid" },
    profile_invalid: { field: "profile", message_key: "auth.profile.invalid" },
    stage_limit_reached: { field: "invite_code", message_key: "auth.registration.stage_limit_reached" },
    registration_login_required: { field: "email", message_key: "auth.registration.login_required" },
    login_registration_required: { field: "email", message_key: "auth.login.registration_required" },
    account_suspended: { field: "email", message_key: "auth.account.suspended" },
    login_admin_required: { field: "email", message_key: "auth.login.admin_required" },
    admin_not_allowed: { field: "email", message_key: "admin.auth.not_allowed" },
    resend_too_soon: { field: "verification_code", message_key: "auth.challenge.resend_too_soon" },
    too_many_attempts: { field: "verification_code", message_key: "auth.challenge.too_many_attempts" },
    csrf_invalid: { field: "csrf_token", message_key: "auth.csrf.invalid" },
    deletion_confirmation_invalid: { field: "confirmation", message_key: "account.deletion.confirmation_invalid" },
    session_invalid: { field: "session", message_key: "auth.session.invalid" },
  };
  return entries[reason];
}
