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

import { RootState } from './rootReducer';
import {
  addAgbsToFilter,
  clearTable,
  setFirstID,
  setGroupPaths,
  setLastID,
  setReadLogs,
  setTable,
  setUpcomingTasks,
  TableDataType,
} from './tableSlice';
import { getFilterState } from './localstorage';
import {
  resetSearch,
  resetStatus,
  resetTypeFilterChanged,
  setTaskState,
} from '../share/aufgaben-shared/slices/filterSlice';
import { TaskState } from "~t/DataPage/types";
import { setItemTags, fetchAllTags } from '../share/aufgaben-shared/slices/tagsSlice';

interface Response {
  creatorList: any[];
  table: any[];
  statusList: any[];
  groups: any[];
  details: any;
}
export const fetchAll = createAsyncThunk(
  'table/fetchAll',
  async (isPagination, thunkAPI) => {
    const d = thunkAPI.dispatch as AppDispatch;
    const state = thunkAPI.getState() as RootState;

    // true = kein Pagination-Call (erstes Laden, Filterwechsel, etc.)
    const isClearTableData = (isPagination as unknown as boolean) !== true;

    // 👉 Nur bei „Voll-Reloads“ und nur wenn noch nicht geladen/laufend
    if (isClearTableData) {
      const { allTags, loadingAll } = state.tags ?? { allTags: [], loadingAll: false };
      if (!loadingAll && allTags.length === 0) {
        d(fetchAllTags());
      } else {
      }
    }

    if (state.data.requestState === 'fromEmail') return;

    if (isClearTableData) {
      d(clearTable());
    }

    const filter = state.filter;
    const selectedNode = state.node;
    const selectedTypes: string[] = [];
    for (const flag in filter.typeFilter) {
      if (filter.typeFilter[flag] === false) continue;
      selectedTypes.push(flag);
    }
    if (selectedTypes.length === 0) {
      d(resetTypeFilterChanged());
      return 'nothing';
    }

    const params: any = {
      selected: selectedTypes,
      state: filter.taskState,
      orderBy: filter.orderBy,
      sortDirection: filter.sortDirection,
      limit: state.table.rowsPerPage,
      tags: filter.selectedTags.length > 0 ? filter.selectedTags.join(',') : undefined,
    };
    if (selectedNode) {
      params.type = selectedNode.type;
      params.ID = selectedNode.id;
    }
    if (filter.taskStatus !== 'none') params.status = filter.taskStatus;

    /* switch (state.table.direction) {
      case 'next': params.lastID = state.table.lastID; break;
      case 'prev': params.firstID = state.table.firstID; break;
    } */

    if (state.table.direction === 'next' && state.table.lastID) {
      params.lastID = state.table.lastID;
    }

    if (state.table.direction === 'prev' && state.table.pageStack.length > 1) {
      // Use current page's firstID to navigate backward
      params.firstID = state.table.pageStack[state.table.pageStack.length - 1].firstID;
    }

    if (filter.taskState === 'upcoming') {
      params.agbsToFilter = state.table.agbsToFilter;
    }

    const r = await axios.get<Response>('c/get', { params });
    d(resetTypeFilterChanged());

    if (filter.taskState === 'upcoming') {
      d(setUpcomingTasks(r.data.table));
      const ids = r.data.table.map(v => v.agb_id);
      d(addAgbsToFilter(ids));
    } else {
      const rows = r.data.table;
      d(setTable(rows));
      if (rows.length > 0) {
        /* d(setFirstID(rows[0].erg_id)); 
        d(setLastID(rows[rows.length - 1].erg_id));  */
      }
      r.data.table.forEach(item => {
        d(setItemTags({ itemId: item.erg_lngid, tags: item.tags || [] }));
      });
    }

    d(setGroupPaths(r.data.groups));
    d(setReadLogs(r.data.read));

    // const filterState = getFilterState();
    // const taskStatus = filterState.taskStatus ?? 'none';
    // if (!r.data.statusList.some(s => s.ID === taskStatus)) {
    //   d(resetStatus());
    // }

    return r.data as Response;
  }
);



export const fetchFav = createAsyncThunk(
  'table/fetchFav',
  async (Selected: any, thunkAPI) => {
    const d = thunkAPI.dispatch;

    const state = thunkAPI.getState() as RootState;
    const filter = state.filter;
    const selectedNode = Selected;
    let selectedTypes = [];
    for (const flag in filter.typeFilter) {
      const isNotSelected = filter.typeFilter[flag] === false;
      if (isNotSelected) continue;

      selectedTypes.push(flag);
    }

    const isNothingSelected = selectedTypes.length === 0;
    if (isNothingSelected) {
      d(resetTypeFilterChanged());
      return 'nothing';
    }

    let params: any = {};
    if (selectedNode !== null) {
      params.type = selectedNode.type;
      params.ID = selectedNode.id;
    }
    params.selected = selectedTypes;

    const haveStatusFilter = filter.taskStatus !== 'none';
    if (haveStatusFilter) {
      params.status = filter.taskStatus;
    }

    params.state = filter.taskState;
    params.orderBy = filter.orderBy;
    if (filter.creator) {
      // Volltext bzw. Kürzel des Erstellers
      params.creator = encodeURIComponent(filter.creator);
    }

    const table = state.table;
    params.limit = table.rowsPerPage;
    switch (table.direction) {
      case 'next':
        params.lastID = table.lastID;
        break;
      case 'prev':
        if (table.pageStack.length > 1) {
          params.firstID = table.pageStack[table.pageStack.length - 1].firstID;
        }
        break;
      case 'none':
      default:
        break;
    }
    params.tags = filter.selectedTags.length > 0 ? filter.selectedTags.join(',') : undefined;


    const isUpcoming = state.filter.taskState === 'upcoming';
    if (isUpcoming) {
      params.agbsToFilter = state.table.agbsToFilter;
    }

    const r = await axios.get('c/get', { params });
    d(resetTypeFilterChanged());
    if (isUpcoming) {
      d(setUpcomingTasks(r.data.table));
      const ids = r.data.table.map((v) => v.agb_id);
      d(addAgbsToFilter(ids));
    } else {
      d(setTable(r.data.table));
    }
    d(setGroupPaths(r.data.groups));
    d(setReadLogs(r.data.read));

    // restore status filter
    const filterState = getFilterState();
    const taskStatus = filterState.taskStatus ?? 'none';
    const statusList = r.data.statusList;
    let isValidTaskStatus = false;
    for (const status of statusList) {
      const haveValue = status.ID === taskStatus;
      if (haveValue === false) {
        continue;
      }

      isValidTaskStatus = true;
      break;
    }
    if (isValidTaskStatus === false) {
      d(resetStatus());
    }

    return r.data as Response;
  }
);

const getResultTaskState = (table: TableDataType[]): TaskState => {
  // The single result response cases are E.g. single ticket search or navigation via ticket ID link.
  const isSingleResult = table.length === 1;
  const isDone = table[0].erg_strerl;
  const isPlanned = table[0].isPlanned;
  if (isSingleResult && isDone && !isPlanned) {
    return 'done';
  } else if (isSingleResult && !isDone && isPlanned) {
    return 'planned';
  } else {
    return 'open';
  }
};

export const fetchSearch = createAsyncThunk(
  'table/search',
  async (_arg, thunkAPI) => {
    const searchString = (thunkAPI.getState() as RootState).filter.searchString;
    if (searchString === undefined) {
      return thunkAPI.rejectWithValue('undefiend search string');
    }
    const r = await axios.get('/c/search', {
      params: { search: encodeURIComponent(searchString) },
    });

    const d = thunkAPI.dispatch;
    d(clearTable());
    d(setTaskState(getResultTaskState(r.data.table)));
    d(setTable(r.data.table));
    d(resetSearch());

    return r.data as Response;
  }
);

interface State {
  isLoading: boolean;
  selectedTableIndex: any;
  statusList: any[];
  groups: any;
  details: any;
  detailsByErgID: any;
  requestState: 'normal' | 'fromEmail';
  creatorList: string[];


}
const initialState: State = {
  isLoading: false,
  selectedTableIndex: null,
  statusList: [],
  groups: {},
  details: null,
  detailsByErgID: {}, // key like id_{id}
  requestState: 'normal',
  creatorList: [],

};

// details
// erg_id, erg_lngid, agb_name, grp_id, grp_name, agb_name_1 agb_id_1, jsonList: []

const slice = createSlice({
  name: 'DataPage/request',
  initialState,
  reducers: {
    _setSelectedTableIndex(state, action: PayloadAction<number>) {
      state.selectedTableIndex = action.payload;
    },
    _setDetails(state, action) {
      state.details = action.payload;
      state.detailsByErgID[`id_${action.payload.erg_id}`] = action.payload;
    },
    resetTableIndex(state) {
      state.selectedTableIndex = null;
      state.details = null;
    },
    setRequestFromEmail(state) {
      state.requestState = 'fromEmail';
    },
    setNormalRequest(state) {
      state.requestState = 'normal';
    },
    setCreatorList(state, action: PayloadAction<string[]>) {
      state.creatorList = action.payload;
    },

  },
  extraReducers: (builder) => {
    builder
      .addCase(fetchAll.pending, (state) => {
        state.isLoading = true;
      })
      .addCase(fetchAll.fulfilled, (state, { payload }) => {
        if (payload === 'nothing') {
          return initialState;
        }

        state.isLoading = false;
        state.statusList = payload.statusList;
        state.creatorList = payload.creatorList ?? [];

      })
      .addCase(fetchAll.rejected, () => {
        return initialState;
      });

    builder.addCase(fetchSearch.fulfilled, (state, { payload }) => {
      state.isLoading = false;
      // state.table = payload.table;
      state.statusList = payload.statusList;
      state.groups = payload.groups;
      state.details = payload.details;
      state.requestState = 'normal';
    });
    builder
      .addCase(fetchFav.pending, (state) => {
        state.isLoading = true;
      })
      .addCase(fetchFav.fulfilled, (state, { payload }) => {
        if (payload === 'nothing') {
          return initialState;
        }

        state.isLoading = false;
        state.statusList = payload.statusList;
        state.creatorList = payload.creatorList ?? [];

      })
      .addCase(fetchFav.rejected, () => {
        return initialState;
      });
  },
});

export const { resetTableIndex, setRequestFromEmail, setNormalRequest } =
  slice.actions;
export default slice.reducer;
