import { createAsyncThunk, createSlice, type PayloadAction } from "@reduxjs/toolkit";
import { getCategories, getNewsroomList } from "@/api/newsroom";
import type { NewsroomCategory, NewsroomItem, NewsroomPagination } from "@/types/newsroom";
import type { RootState } from "../index";

const DEFAULT_LIMIT = 6;

export interface NewsroomState {
  categories: NewsroomCategory[];
  selectedCategory: string; // "" means "All"
  articles: NewsroomItem[];
  latestRecord: NewsroomItem | null;
  latestRecords: NewsroomItem[];
  archiveYears: (number | string)[];
  page: number;
  limit: number;
  totalPages: number;
  totalDocs: number;
  hasNextPage: boolean;
  loading: boolean;
  loadingMore: boolean;
  error: string | null;
}

const initialState: NewsroomState = {
  categories: [],
  selectedCategory: "",
  articles: [],
  latestRecord: null,
  latestRecords: [],
  archiveYears: [],
  page: 1,
  limit: DEFAULT_LIMIT,
  totalPages: 1,
  totalDocs: 0,
  hasNextPage: false,
  loading: false,
  loadingMore: false,
  error: null,
};

/**
 * Refresh newsrooms to guarantee the freshest articles are displayed on visit/navigation.
 */
export const refreshNewsrooms = createAsyncThunk<
  {
    categories?: NewsroomCategory[];
    pagination: NewsroomPagination;
    latestRecord: NewsroomItem | null;
    latestRecords: NewsroomItem[];
    archiveYears?: (number | string)[];
  },
  string | undefined,
  { state: RootState; rejectValue: string }
>("newsroom/refreshNewsrooms", async (categoryArg, { getState, rejectWithValue }) => {
  try {
    const { newsroom } = getState();
    const currentLimit = newsroom.limit || DEFAULT_LIMIT;
    const targetCategory = categoryArg !== undefined ? categoryArg : newsroom.selectedCategory;
    const [categoriesRes, listRes] = await Promise.all([
      getCategories().catch(() => null),
      getNewsroomList({
        page: 1,
        limit: currentLimit,
        category: targetCategory || "",
      }),
    ]);
    return {
      categories: categoriesRes || undefined,
      pagination: listRes.pagination,
      latestRecord: listRes.latestRecord,
      latestRecords: listRes.latestRecords || (listRes.latestRecord ? [listRes.latestRecord] : []),
      archiveYears: listRes.archiveYears || undefined,
    };
  } catch (error) {
    const message = error instanceof Error ? error.message : "Failed to refresh newsrooms.";
    return rejectWithValue(message);
  }
});

/**
 * Filter newsrooms by category (resets to page 1, keeping current per-page limit).
 */
export const filterByCategory = createAsyncThunk<
  {
    pagination: NewsroomPagination;
    latestRecord: NewsroomItem | null;
    latestRecords: NewsroomItem[];
    category: string;
  },
  string,
  { state: RootState; rejectValue: string }
>("newsroom/filterByCategory", async (category, { getState, rejectWithValue }) => {
  try {
    const { newsroom } = getState();
    const currentLimit = newsroom.limit || DEFAULT_LIMIT;
    const res = await getNewsroomList({
      page: 1,
      limit: currentLimit,
      category,
    });
    return {
      pagination: res.pagination,
      latestRecord: res.latestRecord,
      latestRecords: res.latestRecords || (res.latestRecord ? [res.latestRecord] : []),
      category,
    };
  } catch (error) {
    const message = error instanceof Error ? error.message : "Failed to filter newsrooms.";
    return rejectWithValue(message);
  }
});

/**
 * Load more newsrooms (pagination on "View More" click).
 * Appends the next page of articles to existing list.
 */
export const loadMoreNewsrooms = createAsyncThunk<
  NewsroomPagination,
  void,
  { state: RootState; rejectValue: string }
>(
  "newsroom/loadMoreNewsrooms",
  async (_, { getState, rejectWithValue }) => {
    try {
      const { newsroom } = getState();
      const nextPage = (newsroom.page || 1) + 1;
      const currentLimit = newsroom.limit || DEFAULT_LIMIT;
      const res = await getNewsroomList({
        page: nextPage,
        limit: currentLimit,
        category: newsroom.selectedCategory,
      });
      return res.pagination;
    } catch (error) {
      const message = error instanceof Error ? error.message : "Failed to load more newsrooms.";
      return rejectWithValue(message);
    }
  },
  {
    condition: (_, { getState }) => {
      const { newsroom } = getState();
      // Prevent duplicate fetches if already loading or no next page
      if (newsroom.loadingMore || !newsroom.hasNextPage) {
        return false;
      }
    },
  },
);

export const newsroomSlice = createSlice({
  name: "newsroom",
  initialState,
  reducers: {
    initializeNewsroom: (
      state,
      action: PayloadAction<{
        categories: NewsroomCategory[];
        articles: NewsroomItem[];
        latestRecord: NewsroomItem | null;
        latestRecords?: NewsroomItem[];
        pagination: NewsroomPagination;
        archiveYears?: (number | string)[];
      }>,
    ) => {
      state.categories = action.payload.categories;
      state.articles = action.payload.articles;
      state.latestRecord = action.payload.latestRecord;
      state.latestRecords =
        action.payload.latestRecords && action.payload.latestRecords.length > 0
          ? action.payload.latestRecords
          : action.payload.latestRecord
          ? [action.payload.latestRecord]
          : action.payload.articles.slice(0, 3);
      if (action.payload.archiveYears && action.payload.archiveYears.length > 0) {
        state.archiveYears = action.payload.archiveYears;
      }
      state.page = action.payload.pagination.page || 1;
      state.limit = action.payload.pagination.limit || state.limit || DEFAULT_LIMIT;
      state.totalPages = action.payload.pagination.totalPages || 1;
      state.totalDocs = action.payload.pagination.totalDocs || 0;
      state.hasNextPage = Boolean(action.payload.pagination.hasNextPage);
      state.selectedCategory = "";
      state.loading = false;
      state.loadingMore = false;
      state.error = null;
    },
    setSelectedCategory: (state, action: PayloadAction<string>) => {
      state.selectedCategory = action.payload;
    },
  },
  extraReducers: (builder) => {
    // Refresh Newsrooms
    builder
      .addCase(refreshNewsrooms.pending, (state) => {
        state.loading = state.articles.length === 0;
        state.error = null;
      })
      .addCase(refreshNewsrooms.fulfilled, (state, action) => {
        state.loading = false;
        if (action.payload.categories && action.payload.categories.length > 0) {
          state.categories = action.payload.categories;
        }
        state.articles = action.payload.pagination.docs || [];
        state.page = action.payload.pagination.page || 1;
        state.limit = action.payload.pagination.limit || state.limit;
        state.totalPages = action.payload.pagination.totalPages || 1;
        state.totalDocs = action.payload.pagination.totalDocs || 0;
        state.hasNextPage = Boolean(action.payload.pagination.hasNextPage);
        state.latestRecord = action.payload.latestRecord;
        if (action.payload.latestRecords && action.payload.latestRecords.length > 0) {
          state.latestRecords = action.payload.latestRecords;
        }
        if (action.payload.archiveYears && action.payload.archiveYears.length > 0) {
          state.archiveYears = action.payload.archiveYears;
        }
      })
      .addCase(refreshNewsrooms.rejected, (state, action) => {
        state.loading = false;
        state.error = action.payload ?? "Failed to refresh newsrooms.";
      });

    // Filter by Category
    builder
      .addCase(filterByCategory.pending, (state, action) => {
        state.loading = true;
        state.selectedCategory = action.meta.arg;
        state.error = null;
      })
      .addCase(filterByCategory.fulfilled, (state, action) => {
        state.loading = false;
        state.articles = action.payload.pagination.docs || [];
        state.page = action.payload.pagination.page || 1;
        state.limit = action.payload.pagination.limit || state.limit;
        state.totalPages = action.payload.pagination.totalPages || 1;
        state.totalDocs = action.payload.pagination.totalDocs || 0;
        state.hasNextPage = Boolean(action.payload.pagination.hasNextPage);
        if (action.payload.latestRecord) {
          state.latestRecord = action.payload.latestRecord;
        }
        if (action.payload.latestRecords && action.payload.latestRecords.length > 0) {
          state.latestRecords = action.payload.latestRecords;
        }
      })
      .addCase(filterByCategory.rejected, (state, action) => {
        state.loading = false;
        state.error = action.payload ?? "Failed to load newsrooms.";
      });

    // Load More (Pagination)
    builder
      .addCase(loadMoreNewsrooms.pending, (state) => {
        state.loadingMore = true;
        state.error = null;
      })
      .addCase(loadMoreNewsrooms.fulfilled, (state, action) => {
        state.loadingMore = false;
        const newDocs = action.payload.docs || [];
        // Prevent duplicate items when appending
        const existingIds = new Set(
          state.articles.map((item) => item._id || item.sl || item.t)
        );
        const uniqueNewDocs = newDocs.filter((item) => {
          const key = item._id || item.sl || item.t;
          return !existingIds.has(key);
        });
        state.articles = [...state.articles, ...uniqueNewDocs];
        state.page = action.payload.page;
        state.limit = action.payload.limit || state.limit;
        state.totalPages = action.payload.totalPages;
        state.totalDocs = action.payload.totalDocs;
        state.hasNextPage = Boolean(action.payload.hasNextPage);
      })
      .addCase(loadMoreNewsrooms.rejected, (state, action) => {
        state.loadingMore = false;
        state.error = action.payload ?? "Failed to load more newsrooms.";
      });
  },
});

export const { initializeNewsroom, setSelectedCategory } = newsroomSlice.actions;

export const selectNewsroom = (state: RootState) => state.newsroom;

export default newsroomSlice.reducer;
