import { createSlice, createAsyncThunk, type PayloadAction } from "@reduxjs/toolkit";
import type { SearchContentItem, SearchContentResponse } from "@/types/api/search.types";
import type { RootState } from "@/store/store";

/** type=0 means "All" — fetches types 1, 3, 4 in parallel and merges */
export const searchContent = createAsyncThunk(
  "search/searchContent",
  async (
    { query, type, userId }: { query: string; type: number; userId: number },
    { rejectWithValue },
  ) => {
    if (!query.trim()) return { results: [], totalRows: 0 };
    try {
      const { default: apiClient } = await import("@/services/api.client");
      const { API_ENDPOINTS } = await import("@/lib/constants/apiEndpoints");

      const payload = (t: number) => ({ type: t, title: query.trim(), user_id: userId });

      // Stamp each item with the requested type — the API does not return a
      // `type` field on result objects for Live News (3) and Show (4).
      const stamp = (items: SearchContentItem[], t: number) =>
        items.filter((r) => r.status === 1).map((r) => ({ ...r, type: t }));

      if (type === 0) {
        const [articles, live, shows] = await Promise.all([
          apiClient.post<SearchContentResponse>(API_ENDPOINTS.SEARCH_CONTENT, payload(1)),
          apiClient.post<SearchContentResponse>(API_ENDPOINTS.SEARCH_CONTENT, payload(3)),
          apiClient.post<SearchContentResponse>(API_ENDPOINTS.SEARCH_CONTENT, payload(4)),
        ]);
        const results = [
          ...stamp(articles.data.result ?? [], 1),
          ...stamp(live.data.result ?? [], 3),
          ...stamp(shows.data.result ?? [], 4),
        ];
        return {
          results,
          totalRows: articles.data.total_rows + live.data.total_rows + shows.data.total_rows,
        };
      }

      const { data } = await apiClient.post<SearchContentResponse>(
        API_ENDPOINTS.SEARCH_CONTENT,
        payload(type),
      );
      return {
        results: stamp(data.result ?? [], type),
        totalRows: data.total_rows,
      };
    } catch (err) {
      return rejectWithValue((err as Error)?.message ?? "Search failed");
    }
  },
);

interface SearchState {
  results: SearchContentItem[];
  query: string;
  activeType: number; // 0=All, 1=Article, 3=Live News, 4=Show
  totalRows: number;
  isLoading: boolean;
  error: string | null;
}

const initialState: SearchState = {
  results: [],
  query: "",
  activeType: 0,
  totalRows: 0,
  isLoading: false,
  error: null,
};

export const searchSlice = createSlice({
  name: "search",
  initialState,
  reducers: {
    setQuery: (state, action: PayloadAction<string>) => {
      state.query = action.payload;
    },
    setActiveType: (state, action: PayloadAction<number>) => {
      state.activeType = action.payload;
    },
    clearSearch: (state) => {
      state.results = [];
      state.query = "";
      state.totalRows = 0;
      state.error = null;
    },
  },
  extraReducers: (builder) => {
    builder
      .addCase(searchContent.pending, (state) => {
        state.isLoading = true;
        state.error = null;
      })
      .addCase(searchContent.fulfilled, (state, action) => {
        state.isLoading = false;
        state.results = action.payload.results;
        state.totalRows = action.payload.totalRows;
      })
      .addCase(searchContent.rejected, (state, action) => {
        state.isLoading = false;
        state.error = (action.payload as string) ?? "Something went wrong.";
      });
  },
});

export const { setQuery, setActiveType, clearSearch } = searchSlice.actions;
export default searchSlice.reducer;

export const selectSearchResults  = (s: RootState) => s.search.results;
export const selectSearchQuery    = (s: RootState) => s.search.query;
export const selectSearchType     = (s: RootState) => s.search.activeType;
export const selectSearchLoading  = (s: RootState) => s.search.isLoading;
export const selectSearchTotal    = (s: RootState) => s.search.totalRows;
