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

export const getLicenseOrderHistoriesAsync = createAsyncThunk<
  // 正常時の戻り値の型
  OrderHistoryView,
  {
    // パラメータ
    limit: number;
    offset: number;
  },
  {
    // rejectした時の返却値の型
    rejectValue: {
      error: ErrorObject;
    };
  }
>("licenses/licenseOrderHisotyAsync", async (args, thunkApi) => {
  const { limit, offset } = 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 accountsApi = new AccountsApi(config);

  try {
    const { selectedRow } = state.partnerLicense.apps;
    let accountId = 0;
    let companyName = "";
    // 他の画面から指定されていない場合はログインアカウントのidを取得する
    if (!selectedRow) {
      const getMyAccountResponse = await accountsApi.getMyAccount({
        headers: { authorization: `Bearer ${accessToken}` },
      });
      // アカウントID,アカウント名を返す
      accountId = getMyAccountResponse.data.account.accountId;
      companyName = getMyAccountResponse.data.account.companyName;
    } else {
      accountId = selectedRow.accountId;
      companyName = selectedRow.companyName;
    }

    const res = await accountsApi.getOrderHistories(
      {
        limit,
        offset,
        accountId,
      },
      {
        headers: { authorization: `Bearer ${accessToken}` },
      }
    );
    const ret = {
      histories: res.data,
      companyName,
    };
    return ret;
  } catch (e) {
    // e ⇒ errorObjectに変換"
    const error = createErrorObject(e);
    thunkApi.dispatch(
      openSnackbar({
        level: "error",
        message: getTranslationID("common.message.internalServerError"),
      })
    );
    return thunkApi.rejectWithValue({ error });
  }
});

export const issueLicenseAsync = createAsyncThunk<
  {
    /* Empty Object */
  },
  {
    // パラメータ
    orderedAccountId: number;
    poNumber: string;
  },
  {
    // rejectした時の返却値の型
    rejectValue: {
      error: ErrorObject;
    };
  }
>("licenses/issueLicenseAsync", async (args, thunkApi) => {
  const { orderedAccountId, poNumber } = 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 accountsApi = new AccountsApi(config);

  try {
    await accountsApi.issueLicense(
      {
        orderedAccountId,
        poNumber,
      },
      {
        headers: { authorization: `Bearer ${accessToken}` },
      }
    );
    thunkApi.dispatch(
      openSnackbar({
        level: "info",
        message: getTranslationID("common.message.success"),
      })
    );
    return {};
  } catch (e) {
    // e ⇒ errorObjectに変換"
    const error = createErrorObject(e);

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

    if (error.code === "E010803") {
      errorMessage = getTranslationID(
        "orderHistoriesPage.message.alreadyIssueLicense"
      );
    } else if (error.code === "E010804") {
      errorMessage = getTranslationID(
        "orderHistoriesPage.message.notEnoughOfNumberOfLicense"
      );
    }
    thunkApi.dispatch(
      openSnackbar({
        level: "error",
        message: errorMessage,
      })
    );

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

export const cancelOrderAsync = createAsyncThunk<
  {
    /* Empty Object */
  },
  {
    // パラメータ
    poNumber: string;
  },
  {
    // rejectした時の返却値の型
    rejectValue: {
      error: ErrorObject;
    };
  }
>("licenses/cancelOrderAsync", async (args, thunkApi) => {
  const { poNumber } = 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 licensesApi = new LicensesApi(config);

  try {
    await licensesApi.cancelOrder(
      {
        poNumber,
      },
      {
        headers: { authorization: `Bearer ${accessToken}` },
      }
    );
    thunkApi.dispatch(
      openSnackbar({
        level: "info",
        message: getTranslationID("common.message.success"),
      })
    );
    return {};
  } catch (e) {
    // e ⇒ errorObjectに変換"
    const error = createErrorObject(e);

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

    if (error.code === "E010808") {
      errorMessage = getTranslationID(
        "orderHistoriesPage.message.alreadyLicenseIssueOrCancel"
      );
    }
    thunkApi.dispatch(
      openSnackbar({
        level: "error",
        message: errorMessage,
      })
    );

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

export const cancelIssueAsync = createAsyncThunk<
  {
    /* Empty Object */
  },
  {
    // パラメータ
    orderedAccountId: number;
    poNumber: string;
  },
  {
    // rejectした時の返却値の型
    rejectValue: {
      error: ErrorObject;
    };
  }
>("licenses/cancelIssueAsync", async (args, thunkApi) => {
  const { orderedAccountId, poNumber } = 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 accountsApi = new AccountsApi(config);

  try {
    await accountsApi.cancelIssue(
      {
        orderedAccountId,
        poNumber,
      },
      {
        headers: { authorization: `Bearer ${accessToken}` },
      }
    );
    thunkApi.dispatch(
      openSnackbar({
        level: "info",
        message: getTranslationID("common.message.success"),
      })
    );
    return {};
  } catch (e) {
    // e ⇒ errorObjectに変換"
    const error = createErrorObject(e);

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

    if (error.code === "E010809") {
      errorMessage = getTranslationID(
        "orderHistoriesPage.message.alreadyLicenseStatusChanged"
      );
    } else if (error.code === "E010810") {
      errorMessage = getTranslationID(
        "orderHistoriesPage.message.expiredSinceIssued"
      );
    } else if (error.code === "E010811") {
      errorMessage = getTranslationID(
        "orderHistoriesPage.message.alreadyLicenseAllocated"
      );
    }
    thunkApi.dispatch(
      openSnackbar({
        level: "error",
        message: errorMessage,
      })
    );

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