import { PayloadAction, createSlice } from "@reduxjs/toolkit";
import { Typist } from "api";
import { TypistGroupState } from "./state";
import {
  getTypistGroupAsync,
  listTypistGroupsAsync,
  listTypistsAsync,
  updateTypistGroupAsync,
} from "./operations";

const initialState: TypistGroupState = {
  apps: {
    isLoading: false,
    selectedTypists: [],
    groupName: "",
  },
  domain: {
    typistGroups: [],
    typists: [],
  },
};

export const typistGroupSlice = createSlice({
  name: "typistGroup",
  initialState,
  reducers: {
    cleanupTypistGroup: (state) => {
      state.apps.groupName = "";
      state.apps.selectedTypists = [];
      state.apps.updateTypistGroupId = undefined;
      state.domain.typists = [];
    },
    addSelectedTypist: (state, action: PayloadAction<{ typist: Typist }>) => {
      const { typist } = action.payload;

      const selectedTypists = [...state.apps.selectedTypists, typist];
      if (!state.apps.selectedTypists.find((x) => x.id === typist.id)) {
        state.apps.selectedTypists = selectedTypists.sort(
          (a, b) => a.id - b.id
        );
      }
    },
    removeSelectedTypist: (
      state,
      action: PayloadAction<{ typist: Typist }>
    ) => {
      const { typist } = action.payload;

      const selectedTypists = state.apps.selectedTypists.filter(
        (x) => x.id !== typist.id
      );
      state.apps.selectedTypists = selectedTypists.sort((a, b) => a.id - b.id);
    },
    changeGroupName: (state, action: PayloadAction<{ groupName: string }>) => {
      const { groupName } = action.payload;
      state.apps.groupName = groupName;
    },
  },
  extraReducers: (builder) => {
    builder.addCase(listTypistGroupsAsync.pending, (state) => {
      state.apps.isLoading = true;
    });
    builder.addCase(listTypistGroupsAsync.fulfilled, (state, action) => {
      state.domain.typistGroups = action.payload.typistGroups;
      state.apps.isLoading = false;
    });
    builder.addCase(listTypistGroupsAsync.rejected, (state) => {
      state.apps.isLoading = false;
    });
    builder.addCase(listTypistsAsync.pending, (state) => {
      state.apps.isLoading = true;
    });
    builder.addCase(listTypistsAsync.fulfilled, (state, action) => {
      state.domain.typists = action.payload.typists;
      state.apps.isLoading = false;
    });
    builder.addCase(listTypistsAsync.rejected, (state) => {
      state.apps.isLoading = false;
    });
    builder.addCase(getTypistGroupAsync.rejected, (state) => {
      state.apps.isLoading = false;
    });
    builder.addCase(getTypistGroupAsync.pending, (state) => {
      state.apps.isLoading = true;
    });
    builder.addCase(getTypistGroupAsync.fulfilled, (state, action) => {
      const { typistGroup, selectedTypistIds, typists } = action.payload;
      // 対象タイピストグループのID・名前を設定
      state.apps.updateTypistGroupId = typistGroup.id;
      state.apps.groupName = typistGroup.name;

      // 選択済みのタイピストを設定
      state.apps.selectedTypists = typists
        .filter((x) => selectedTypistIds.includes(x.id))
        .sort((a, b) => a.id - b.id);
      // すべてのタイピストを設定
      state.domain.typists = typists;
      state.apps.isLoading = false;
    });
    builder.addCase(updateTypistGroupAsync.pending, (state) => {
      state.apps.isLoading = true;
    });
    builder.addCase(updateTypistGroupAsync.fulfilled, (state) => {
      state.apps.isLoading = false;
    });
    builder.addCase(updateTypistGroupAsync.rejected, (state) => {
      state.apps.isLoading = false;
    });
  },
});

export const {
  cleanupTypistGroup,
  addSelectedTypist,
  removeSelectedTypist,
  changeGroupName,
} = typistGroupSlice.actions;

export default typistGroupSlice.reducer;
