import { createAsyncThunk } from "@reduxjs/toolkit";
import {
  Configuration,
  FilesApi,
  GetTemplatesResponse,
  TemplatesApi,
} from "api";
import type { RootState } from "app/store";
import { ErrorObject, createErrorObject } from "common/errors";
import { openSnackbar } from "features/ui/uiSlice";
import { getTranslationID } from "translation";
import { BlockBlobClient, ContainerClient } from "@azure/storage-blob";
import { getAccessToken } from "features/auth";

export const listTemplateAsync = createAsyncThunk<
  GetTemplatesResponse,
  void,
  {
    // rejectした時の返却値の型
    rejectValue: {
      error: ErrorObject;
    };
  }
>("workflow/listTemplateAsync", 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 templateApi = new TemplatesApi(config);

  try {
    const { data } = await templateApi.getTemplates({
      headers: { authorization: `Bearer ${accessToken}` },
    });

    return 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 uploadTemplateAsync = createAsyncThunk<
  {
    /* Empty Object */
  },
  void,
  {
    // rejectした時の返却値の型
    rejectValue: {
      error: ErrorObject;
    };
  }
>("workflow/uploadTemplateAsync", async (args, thunkApi) => {
  // apiのConfigurationを取得する
  const { getState } = thunkApi;
  const state = getState() as RootState;
  const { configuration } = state.auth;
  const accessToken = getAccessToken(state.auth);
  const { uploadFile } = state.template.apps;
  const config = new Configuration(configuration);
  const filesApi = new FilesApi(config);

  try {
    if (!uploadFile) {
      throw new Error("uploadFile is not found");
    }
    // SAS付きのURLを取得する
    const { data } = await filesApi.uploadTemplateLocation({
      headers: { authorization: `Bearer ${accessToken}` },
    });
    const { url } = data;

    // ファイルをアップロードする
    const containerClient = new ContainerClient(url);
    const blockBlobClient: BlockBlobClient = containerClient.getBlockBlobClient(
      uploadFile.name
    );
    await blockBlobClient.uploadData(uploadFile);

    await filesApi.uploadTemplateFinished(
      {
        name: uploadFile.name,
        url,
      },
      {
        headers: { authorization: `Bearer ${accessToken}` },
      }
    );
    thunkApi.dispatch(
      openSnackbar({
        level: "info",
        message: getTranslationID("common.message.success"),
      })
    );
    return {};
  } catch (e) {
    // e ⇒ errorObjectに変換"
    const error = createErrorObject(e);
    thunkApi.dispatch(
      openSnackbar({
        level: "error",
        message: getTranslationID("common.message.internalServerError"),
      })
    );
    return thunkApi.rejectWithValue({ error });
  }
});
