import { createSlice, createAsyncThunk, type PayloadAction } from "@reduxjs/toolkit";
import type { ChannelDetail, ChannelDetailResponse, ChannelContentItem, ChannelContentResponse } from "@/types/api/channel.types";
import type { RootState } from "@/store/store";

// ── Fetch channel details ─────────────────────────────────────────────────────
export const fetchChannelDetails = createAsyncThunk<
  ChannelDetail,
  { channelId: number; userId: number }
>(
  "channel/fetchDetails",
  async ({ channelId, userId }, { rejectWithValue }) => {
    try {
      const { default: apiClient } = await import("@/services/api.client");
      const { API_ENDPOINTS } = await import("@/lib/constants/apiEndpoints");
      const { data } = await apiClient.post<ChannelDetailResponse>(
        API_ENDPOINTS.GET_CHANNEL_DETAILS,
        { channel_id: channelId, user_id: userId },
      );
      const channel = data.result?.[0];
      if (!channel) throw new Error("Channel not found");
      return channel;
    } catch (err) {
      return rejectWithValue((err as Error)?.message ?? "Failed to load channel.");
    }
  },
);

// ── Fetch channel content ─────────────────────────────────────────────────────
export const fetchChannelContent = createAsyncThunk<
  { channelId: number; contentType: number; items: ChannelContentItem[] },
  { channelId: number; contentType: number; userId?: number }
>(
  "channel/fetchContent",
  async ({ channelId, contentType, userId = 0 }, { rejectWithValue }) => {
    try {
      const { default: apiClient } = await import("@/services/api.client");
      const { API_ENDPOINTS } = await import("@/lib/constants/apiEndpoints");
      const { data } = await apiClient.post<ChannelContentResponse>(
        API_ENDPOINTS.GET_CHANNEL_CONTENT,
        { type: contentType, channel_id: channelId, user_id: userId },
      );
      return {
        channelId,
        contentType,
        items: (data.result ?? []).filter((i) => i.status === 1),
      };
    } catch (err) {
      return rejectWithValue((err as Error)?.message ?? "Failed to load content.");
    }
  },
);

// ── Follow / Unfollow ─────────────────────────────────────────────────────────
export const toggleFollow = createAsyncThunk<
  { channelId: number; isFollow: number },
  { channelId: number; userId: number; currentIsFollow: number }
>(
  "channel/toggleFollow",
  async ({ channelId, userId }, { rejectWithValue }) => {
    try {
      const { default: apiClient } = await import("@/services/api.client");
      const { API_ENDPOINTS } = await import("@/lib/constants/apiEndpoints");
      await apiClient.post(API_ENDPOINTS.FOLLOW_UNFOLLOW, { channel_id: channelId, user_id: userId });
      // Toggle: if was 0 → 1, if was 1 → 0
      return { channelId, isFollow: 1 }; // server will handle toggle
    } catch (err) {
      return rejectWithValue((err as Error)?.message ?? "Failed to toggle follow.");
    }
  },
);

// ── Block / Unblock ───────────────────────────────────────────────────────────
export const toggleBlock = createAsyncThunk<
  void,
  { channelId: number; userId: number }
>(
  "channel/toggleBlock",
  async ({ channelId, userId }, { rejectWithValue }) => {
    try {
      const { default: apiClient } = await import("@/services/api.client");
      const { API_ENDPOINTS } = await import("@/lib/constants/apiEndpoints");
      await apiClient.post(API_ENDPOINTS.ADD_REMOVE_BLOCK_CHANNEL, { channel_id: channelId, user_id: userId });
    } catch (err) {
      return rejectWithValue((err as Error)?.message ?? "Failed to block channel.");
    }
  },
);

// ── State ─────────────────────────────────────────────────────────────────────
type ContentKey = `${number}_${number}`; // `channelId_contentType`

interface ChannelState {
  detailById: Record<number, ChannelDetail>;
  contentByKey: Record<ContentKey, ChannelContentItem[]>;
  loadedDetails: number[];
  loadedContentKeys: ContentKey[];
  activeContentType: number;
  isLoadingDetails: boolean;
  isLoadingContent: boolean;
  error: string | null;
}

const initialState: ChannelState = {
  detailById: {},
  contentByKey: {},
  loadedDetails: [],
  loadedContentKeys: [],
  activeContentType: 1,
  isLoadingDetails: false,
  isLoadingContent: false,
  error: null,
};

export const channelSlice = createSlice({
  name: "channel",
  initialState,
  reducers: {
    setActiveContentType: (state, action: PayloadAction<number>) => {
      state.activeContentType = action.payload;
    },
    optimisticToggleFollow: (state, action: PayloadAction<number>) => {
      const ch = state.detailById[action.payload];
      if (ch) {
        ch.is_follow = ch.is_follow === 1 ? 0 : 1;
        ch.followers = ch.is_follow === 1 ? ch.followers + 1 : Math.max(0, ch.followers - 1);
      }
    },
  },
  extraReducers: (builder) => {
    builder
      .addCase(fetchChannelDetails.pending, (state) => {
        state.isLoadingDetails = true;
        state.error = null;
      })
      .addCase(fetchChannelDetails.fulfilled, (state, action) => {
        state.isLoadingDetails = false;
        const ch = action.payload;
        state.detailById[ch.id] = ch;
        if (!state.loadedDetails.includes(ch.id)) state.loadedDetails.push(ch.id);
      })
      .addCase(fetchChannelDetails.rejected, (state, action) => {
        state.isLoadingDetails = false;
        state.error = (action.payload as string) ?? "Something went wrong.";
      })
      .addCase(fetchChannelContent.pending, (state) => {
        state.isLoadingContent = true;
      })
      .addCase(fetchChannelContent.fulfilled, (state, action) => {
        state.isLoadingContent = false;
        const { channelId, contentType, items } = action.payload;
        const key: ContentKey = `${channelId}_${contentType}`;
        state.contentByKey[key] = items;
        if (!state.loadedContentKeys.includes(key)) state.loadedContentKeys.push(key);
      })
      .addCase(fetchChannelContent.rejected, (state) => {
        state.isLoadingContent = false;
      });
  },
});

export const { setActiveContentType, optimisticToggleFollow } = channelSlice.actions;
export default channelSlice.reducer;

// ── Selectors ─────────────────────────────────────────────────────────────────
export const selectChannelDetail    = (id: number) => (s: RootState) => s.channel.detailById[id] ?? null;
export const selectChannelLoaded    = (id: number) => (s: RootState) => s.channel.loadedDetails.includes(id);
export const selectChannelContent   = (id: number, type: number) => (s: RootState) => s.channel.contentByKey[`${id}_${type}` as ContentKey] ?? null;
export const selectActiveContentType = (s: RootState) => s.channel.activeContentType;
export const selectChannelLoading   = (s: RootState) => s.channel.isLoadingDetails;
export const selectContentLoading   = (s: RootState) => s.channel.isLoadingContent;
