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 { getIdTokenFromLocalStorage } from "common/token";
import { TIERS } from "components/auth/constants";
import { getAccessToken } from "features/auth";
import {
  UsersApi,
  GetAccountInfoMinimalAccessResponse,
  AccountsApi,
  TermsApi,
  GetTermsInfoResponse,
} from "../../api/api";
import { Configuration } from "../../api/configuration";

export const getAccountInfoMinimalAccessAsync = createAsyncThunk<
  GetAccountInfoMinimalAccessResponse,
  {
    localStorageKeyforIdToken: string;
  },
  {
    // rejectした時の返却値の型
    rejectValue: {
      error: ErrorObject;
    };
  }
>("accept/getAccountInfoMinimalAccessAsync", async (args, thunkApi) => {
  const { localStorageKeyforIdToken } = 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 {
    // IDトークンの取得
    const idToken = getIdTokenFromLocalStorage(localStorageKeyforIdToken);

    // IDトークンが取得できない場合エラーとする
    if (!idToken) {
      throw new Error("Unable to retrieve the ID token.");
    }
    const res = await accountApi.getAccountInfoMinimalAccess(
      { idToken },
      {
        headers: { authorization: `Bearer ${accessToken}` },
      }
    );
    return res.data;
  } catch (e) {
    const error = createErrorObject(e);
    thunkApi.dispatch(
      openSnackbar({
        level: "error",
        message: getTranslationID("common.message.internalServerError"),
      })
    );
    return thunkApi.rejectWithValue({ error });
  }
});

export const getTermsInfoAsync = createAsyncThunk<
  GetTermsInfoResponse,
  void,
  {
    // rejectした時の返却値の型
    rejectValue: {
      error: ErrorObject;
    };
  }
>("accept/getTermsInfoAsync", 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 termsApi = new TermsApi(config);

  try {
    const termsInfo = await termsApi.getTermsInfo({
      headers: { authorization: `Bearer ${accessToken}` },
    });

    return termsInfo.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 updateAcceptedVersionAsync = createAsyncThunk<
  {
    /* Empty Object */
  },
  {
    tier: number;
    localStorageKeyforIdToken: string;
    updateAccceptVersions: {
      acceptedVerDPA: string;
      acceptedVerEULA: string;
      acceptedVerPrivacyNotice: string;
    };
  },
  {
    // rejectした時の返却値の型
    rejectValue: {
      error: ErrorObject;
    };
  }
>("accept/UpdateAcceptedVersionAsync", async (args, thunkApi) => {
  const { tier, localStorageKeyforIdToken, updateAccceptVersions } = 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 userApi = new UsersApi(config);

  try {
    // IDトークンの取得
    const idToken = getIdTokenFromLocalStorage(localStorageKeyforIdToken);

    // IDトークンが取得できない場合エラーとする
    if (!idToken) {
      throw new Error("Unable to retrieve the ID token.");
    }
    await userApi.updateAcceptedVersion(
      {
        idToken,
        acceptedEULAVersion: updateAccceptVersions.acceptedVerEULA,
        acceptedPrivacyNoticeVersion:
          updateAccceptVersions.acceptedVerPrivacyNotice,
        acceptedDPAVersion: !(TIERS.TIER5 === tier.toString())
          ? updateAccceptVersions.acceptedVerDPA
          : undefined,
      },
      {
        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 });
  }
});
