import { createAsyncThunk, createSlice, PayloadAction } from "@reduxjs/toolkit";
import { serverUrl } from "../utils/request";
import { NewsItemPagination } from "../model/NewsItemPagination";
import { NewsItem } from "../model/NewsItem";

interface NewsItemState {
    all: NewsItemPagination;
    newsItem: NewsItem;
    status: string;
}

const initialState: NewsItemState = {
    all: { data: [], pagination: { page: 0, page_size: 0 } } as NewsItemPagination,
    newsItem: {} as NewsItem,
    status: "idle",
};

const TIMEOUT = 5000;

type PaginationQuery = {
    page: number,
    limit: number,
};

export const fetchNewsItems = createAsyncThunk<
    NewsItemPagination,
    PaginationQuery
>('newsItems', async ({ page, limit } : PaginationQuery) => {
    const controller = new AbortController();
    const id = setTimeout(() => controller.abort(), TIMEOUT);

    const response = await fetch(serverUrl() + `/api/news?page=${page}&limit=${limit}`, { signal: controller.signal });
    clearTimeout(id);

    return (await response.json()).pagination as NewsItemPagination;
});

export const fetchNewsItem = createAsyncThunk<
    NewsItem,
    number
>('newsItem', async (id: number) => {
    const controller = new AbortController();
    const idTimeout = setTimeout(() => controller.abort(), TIMEOUT);

    const response = await fetch(serverUrl() + `/api/news/${id}`, { signal: controller.signal });
    clearTimeout(idTimeout);

    return (await response.json()).newsItem as NewsItem;
});

export const newsItemSlice = createSlice({
    name: "newsItem",
    initialState,
    reducers: {
        setAll(state: NewsItemState, action: PayloadAction<NewsItemPagination>) {
            state.all = action.payload;
        },
        setNewsItem(state: NewsItemState, action: PayloadAction<NewsItem>) {
            state.newsItem = action.payload;
        },
    },
    extraReducers: (builder) => {
        builder
            .addCase(fetchNewsItems.pending, (state: NewsItemState) => {
                state.status = 'loading';
            })
            .addCase(fetchNewsItems.fulfilled, (state: NewsItemState, action: PayloadAction<NewsItemPagination>) => {
                state.all = action.payload;
                state.status = 'idle';
            })
            .addCase(fetchNewsItems.rejected, (state: NewsItemState) => {
                state.status = 'failed';
            })
            .addCase(fetchNewsItem.pending, (state: NewsItemState) => {
                state.status = 'loading';
            })
            .addCase(fetchNewsItem.fulfilled, (state: NewsItemState, action: PayloadAction<NewsItem>) => {
                state.newsItem = action.payload;
                state.status = 'idle';
            })
            .addCase(fetchNewsItem.rejected, (state: NewsItemState) => {
                state.status = 'failed';
            });
    },
});

export default newsItemSlice.reducer;
