
// resources\assets\ts\DataPage\commentsSlice.ts
import {
  PayloadAction,
  createAsyncThunk,
  createEntityAdapter,
  createSlice,
} from '@reduxjs/toolkit';
import axios from 'B/axios';

// import { RootState } from '../../../DataPage/rootReducer'; // Changed from DataPage-specific RootState to generic RootStateWithSlice

interface RootStateWithSlice {
  comments: any;  // or pictures, points, filter depending on the slice
}

export interface Comment {
  id: number;
  sign: string;
  timestamp: string;
  link?: string;
  content: string;
  type: 'file' | 'pdf' | 'img' | 'string' | 'url' | 'html';
}

const commentsAdapter = createEntityAdapter<Comment>();

export const fetchComments = createAsyncThunk(
  'monitor/fetchComments',
  async (arg: number, thunkAPI) => {
    const haveComment =
      // (thunkAPI.getState() as RootState).comments.ergs[arg] !== undefined;
      (thunkAPI.getState() as RootStateWithSlice).comments.ergs[arg]
    if (haveComment) {
      return { comments: [], ergID: arg, isFromServer: false };
    }

    const r = await axios.get(`c/${arg}/comments`);

    return {
      comments: r.data as Comment[],
      ergID: arg,
      isFromServer: true,
    };
  },
);

export const deleteComment = createAsyncThunk(
  'monitor/deleteComments',
  async ({ sak_id, erg_id }: { sak_id: number; erg_id: number }, thunkAPI) => {
    const res = await axios.post('/commission/deletesak', {
      sakid: sak_id,
    });

    const isFail = res.status !== 200;
    if (isFail) return thunkAPI.rejectWithValue('Delete comment failed');

    return { sak_id, erg_id };
  },
);

export const addComment = createAsyncThunk(
  'monitor/addComment',
  async ({ comment, ergID }: { comment: string; ergID: number }, thunkAPI) => {
    if (comment === '') {
      return thunkAPI.rejectWithValue('Empty comment');
    }

    const commentForm = new FormData();
    commentForm.append('ergid', ergID.toString());
    commentForm.append('bemerkung', comment);
    await axios.post('/commission/savesak', commentForm);
    const r = await axios.get(`c/${ergID}/comments`);

    return { comments: r.data as Comment[], ergID };
  },
);

export const addCommentFile = createAsyncThunk(
  'monitor/addCommentFile',
  async ({ file, ergID }: { file: File; ergID: number }, thunkAPI) => {
    if (file === undefined) {
      return thunkAPI.rejectWithValue('Empty comment file');
    }

    const fileForm = new FormData();
    fileForm.append('file', file);
    fileForm.append('ergid', ergID.toString());
    await axios.post('/comment/file', fileForm);
    const r = await axios.get(`c/${ergID}/comments`);

    return { comments: r.data as Comment[], ergID };
  },
);

const slice = createSlice({
  name: 'data/comments',
  initialState: commentsAdapter.getInitialState({
    ergs: {},
    isUploadDialogOpen: false,
    uploadErgID: null,
  }),
  reducers: {
    openUploadDialog(state, { payload }) {
      state.isUploadDialogOpen = true;
      state.uploadErgID = payload;
    },
    closeUploadDialog(state) {
      state.isUploadDialogOpen = false;
      state.uploadErgID = null;
    },
  },
  extraReducers: (builder) => {
    builder.addCase(fetchComments.fulfilled, (state, { payload }) => {
      const isClose = payload.isFromServer === false;
      if (isClose) {
        delete state.ergs[payload.ergID];
        return;
      }

      commentsAdapter.upsertMany(state, payload.comments);
      state.ergs[payload.ergID] = payload.comments.map((c) => c.id);
    });

    builder.addCase(deleteComment.fulfilled, (state, { payload }) => {
      commentsAdapter.removeOne(state, payload.sak_id);

      const sakIds = state.ergs[payload.erg_id];
      if (sakIds === undefined) return;

      let newSak = [];
      for (let id of sakIds) {
        if (id === payload.sak_id) continue;
        newSak.push(id);
      }

      state.ergs[payload.erg_id] = newSak;
    });

    builder
      .addCase(addComment.fulfilled, (state, { payload }) => {
        commentsAdapter.upsertMany(state, payload.comments);
        state.ergs[payload.ergID] = payload.comments.map((c) => c.id);
      })
      .addCase(addCommentFile.fulfilled, (state, { payload }) => {
        commentsAdapter.upsertMany(state, payload.comments);
        state.ergs[payload.ergID] = payload.comments.map((c) => c.id);
      });
  },
});

export const { openUploadDialog, closeUploadDialog } = slice.actions;
export default slice.reducer;
