import { createSlice, createAsyncThunk, PayloadAction } from "@reduxjs/toolkit";
import { notificationService, NotificationItem } from "@/services/notificationService";

interface NotificationState {
  items: NotificationItem[];
  isLoading: boolean;
  isLoadingMore: boolean;
  error: string | null;
  currentPage: number;
  hasMore: boolean;
  totalRows: number;
  unreadCount: number;
}

const initialState: NotificationState = {
  items: [],
  isLoading: false,
  isLoadingMore: false,
  error: null,
  currentPage: 1,
  hasMore: false,
  totalRows: 0,
  unreadCount: 0,
};

export const fetchNotifications = createAsyncThunk(
  "notifications/fetch",
  async (pageNo: number, { rejectWithValue }) => {
    try {
      const res = await notificationService.getNotifications(pageNo);
      return { data: res, pageNo };
    } catch {
      return rejectWithValue("Failed to load notifications.");
    }
  },
);

export const markAsRead = createAsyncThunk(
  "notifications/markRead",
  async (notificationId: string, { rejectWithValue }) => {
    try {
      await notificationService.readNotification(notificationId);
      return notificationId;
    } catch {
      return rejectWithValue("Failed to mark as read.");
    }
  },
);

const notificationSlice = createSlice({
  name: "notifications",
  initialState,
  reducers: {
    markAllReadLocally: (state) => {
      state.items = state.items.map((n) => ({ ...n, isRead: true }));
      state.unreadCount = 0;
    },
  },
  extraReducers: (builder) => {
    builder
      // fetch
      .addCase(fetchNotifications.pending, (state, action) => {
        if (action.meta.arg === 1) state.isLoading = true;
        else state.isLoadingMore = true;
        state.error = null;
      })
      .addCase(fetchNotifications.fulfilled, (state, action) => {
        state.isLoading = false;
        state.isLoadingMore = false;
        const { data, pageNo } = action.payload;
        const mapped = data.result.map(notificationService.mapNotification);
        state.items = pageNo === 1 ? mapped : [...state.items, ...mapped];
        state.currentPage = data.current_page;
        state.hasMore = data.more_page;
        state.totalRows = data.total_rows;
        state.unreadCount = state.items.filter((n) => !n.isRead).length;
      })
      .addCase(fetchNotifications.rejected, (state, action) => {
        state.isLoading = false;
        state.isLoadingMore = false;
        state.error = action.payload as string;
      })
      // mark read
      .addCase(markAsRead.fulfilled, (state, action: PayloadAction<string>) => {
        const item = state.items.find((n) => n.id === action.payload);
        if (item && !item.isRead) {
          item.isRead = true;
          state.unreadCount = Math.max(0, state.unreadCount - 1);
        }
      });
  },
});

export const { markAllReadLocally } = notificationSlice.actions;
export default notificationSlice.reducer;
