import { createAsyncThunk } from "@reduxjs/toolkit";
import type { RootState } from "app/store";
import { ErrorObject, createErrorObject } from "common/errors";
import { getTranslationID } from "translation";
import { openSnackbar } from "features/ui/uiSlice";
import { getAccessToken } from "features/auth";
import {
  AccountsApi,
  UpdateAccountInfoRequest,
  UsersApi,
  DeleteAccountRequest,
} from "../../api/api";
import { Configuration } from "../../api/configuration";
import { ViewAccountRelationsInfo } from "./types";

export const getAccountRelationsAsync = createAsyncThunk<
  // 正常時の戻り値の型
  ViewAccountRelationsInfo,
  void,
  {
    // rejectした時の返却値の型
    rejectValue: {
      error: ErrorObject;
    };
  }
>("accounts/getAccountRelationsAsync", async (_args, thunkApi) => {
  // apiのConfigurationを取得する
  const { getState } = thunkApi;
  const state = getState() as RootState;
  const { configuration } = state.auth;
  const accessToken = getAccessToken(state.auth);
  const config = new Configuration(configuration);
  const accountsApi = new AccountsApi(config);
  const usersApi = new UsersApi(config);

  try {
    const accountInfo = await accountsApi.getMyAccount({
      headers: { authorization: `Bearer ${accessToken}` },
    });
    const dealers = await accountsApi.getDealers();
    const users = await usersApi.getUsers({
      headers: { authorization: `Bearer ${accessToken}` },
    });
    return {
      accountInfo: accountInfo.data,
      dealers: dealers.data,
      users: users.data,
    };
  } catch (e) {
    // e ⇒ errorObjectに変換"
    const error = createErrorObject(e);
    thunkApi.dispatch(
      openSnackbar({
        level: "error",
        message: getTranslationID("common.message.internalServerError"),
      })
    );
    return thunkApi.rejectWithValue({ error });
  }
});

export const updateAccountInfoAsync = createAsyncThunk<
  {
    /* Empty Object */
  },
  UpdateAccountInfoRequest,
  {
    // rejectした時の返却値の型
    rejectValue: {
      error: ErrorObject;
    };
  }
>("accounts/updateAccountInfoAsync", async (args, thunkApi) => {
  // apiのConfigurationを取得する
  const { getState } = thunkApi;
  const state = getState() as RootState;
  const { configuration } = state.auth;
  const accessToken = getAccessToken(state.auth);
  const config = new Configuration(configuration);
  const accountApi = new AccountsApi(config);

  try {
    await accountApi.updateAccountInfo(args, {
      headers: { authorization: `Bearer ${accessToken}` },
    });
    thunkApi.dispatch(
      openSnackbar({
        level: "info",
        message: getTranslationID("common.message.success"),
      })
    );
    return {};
  } catch (e) {
    const error = createErrorObject(e);

    let errorMessage = getTranslationID("common.message.internalServerError");

    if (error.code === "E010502") {
      errorMessage = getTranslationID(
        "accountPage.message.updateAccountFailedError"
      );
    }

    thunkApi.dispatch(
      openSnackbar({
        level: "error",
        message: errorMessage,
      })
    );

    return thunkApi.rejectWithValue({ error });
  }
});

export const deleteAccountAsync = createAsyncThunk<
  {
    /* Empty Object */
  },
  DeleteAccountRequest,
  {
    // rejectした時の返却値の型
    rejectValue: {
      error: ErrorObject;
    };
  }
>("account/deleteAccountAsync", async (args, thunkApi) => {
  const deleteAccounRequest = args;
  // apiのConfigurationを取得する
  const { getState } = thunkApi;
  const state = getState() as RootState;
  const { configuration } = state.auth;
  const accessToken = getAccessToken(state.auth);
  const config = new Configuration(configuration);
  const accountApi = new AccountsApi(config);

  try {
    await accountApi.deleteAccountAndData(deleteAccounRequest, {
      headers: { authorization: `Bearer ${accessToken}` },
    });

    return {};
  } catch (e) {
    const error = createErrorObject(e);

    thunkApi.dispatch(
      openSnackbar({
        level: "error",
        message: getTranslationID("common.message.internalServerError"),
      })
    );

    return thunkApi.rejectWithValue({ error });
  }
});
