import { AxiosError } from "axios";
import { isError } from "lodash";
import { ErrorResponse } from "../../api";
import { errorCodes } from "./code";
import { ErrorCodeType, ErrorObject } from "./types";

export const createErrorObject = (error: unknown): ErrorObject => {
  // 最低限通常のエラーかを判定
  // Error以外のものがthrowされた場合
  // 基本的にないはずだがプログラム上あるので拾う
  if (!isError(error)) {
    return {
      message: "not error type.",
      code: "E009999",
    };
  }

  // Axiosエラー 通信してのエラーであるかを判定
  if (!isAxiosError(error)) {
    return {
      message: "not axios error.",
      code: "E009999",
    };
  }

  const errorResponse = error.response;
  if (!errorResponse) {
    return {
      message: error.message,
      code: "E009999",
      statusCode: errorResponse,
    };
  }

  const { data } = errorResponse;

  // 想定しているエラーレスポンスの型か判定
  if (!isErrorResponse(data)) {
    return {
      message: error.message,
      code: "E009999",
      statusCode: errorResponse.status,
    };
  }

  const { message, code } = data;

  // 想定しているエラーコードかを判定
  if (!isErrorCode(code)) {
    return {
      message,
      code: "E009999",
      statusCode: errorResponse.status,
    };
  }

  return {
    message,
    code,
    statusCode: errorResponse.status,
  };
};

const isAxiosError = (e: unknown): e is AxiosError => {
  const error = e as AxiosError;
  return error?.isAxiosError ?? false;
};

const isErrorResponse = (error: unknown): error is ErrorResponse => {
  const errorResponse = error as ErrorResponse;
  if (
    errorResponse === undefined ||
    errorResponse.message === undefined ||
    errorResponse.code === undefined
  ) {
    return false;
  }

  return true;
};

const isErrorCode = (errorCode: string): errorCode is ErrorCodeType =>
  errorCodes.includes(errorCode as ErrorCodeType);
