/**
 * Copyright 2024 Phenix Real Time Solutions, Inc. Confidential and Proprietary. All Rights Reserved.
 */
import {createAsyncThunk, createSelector} from '@reduxjs/toolkit';
import channelService, {CreateChannelParams, DeleteChannelParams, ForkChannelParams, KillChannelParams} from '../../services/channel.service';
import {RootState} from '../index';
import {IChannelsState} from '../slices/Channels.slice';

// Selectors
export const channelsSelector = (state: RootState): IChannelsState => state.channels;

export const selectChannelList = createSelector(
  [channelsSelector],
  (channels: IChannelsState) => channels.channels
);

export const selectChannelsLoading = createSelector(
  [channelsSelector], 
  (channels: IChannelsState) => channels.isLoading
);

export const selectChannelsError = createSelector(
  [channelsSelector],
  (channels: IChannelsState) => channels.error
);

export const selectSelectedChannel = createSelector(
  [channelsSelector],
  (channels: IChannelsState) => channels.selectedChannel
);

// Async thunks for channel operations
export const listChannels = createAsyncThunk(
  'channels/listChannels',
  async (_, {rejectWithValue}) => {
    try {
      const channels = await channelService.listChannels();
      return channels;
    } catch (error) {
      return rejectWithValue(error instanceof Error ? error.message : 'Failed to fetch channels');
    }
  }
);

export const createChannelThunk = createAsyncThunk(
  'channels/createChannel',
  async (params: CreateChannelParams, {rejectWithValue, dispatch}) => {
    try {
      const newChannel = await channelService.createChannel(params);
      // Refresh the channel list after creation
      dispatch(listChannels());
      return newChannel;
    } catch (error) {
      return rejectWithValue(error instanceof Error ? error.message : 'Failed to create channel');
    }
  }
);

export const deleteChannelThunk = createAsyncThunk(
  'channels/deleteChannel',
  async (params: DeleteChannelParams, {rejectWithValue, dispatch}) => {
    try {
      await channelService.deleteChannel(params);
      // Refresh the channel list after deletion
      dispatch(listChannels());
      return params.channelId;
    } catch (error) {
      return rejectWithValue(error instanceof Error ? error.message : 'Failed to delete channel');
    }
  }
);

export const forkChannelThunk = createAsyncThunk(
  'channels/forkChannel',
  async (params: ForkChannelParams, {rejectWithValue, dispatch}) => {
    try {
      await channelService.forkChannel(params);
      // Refresh the channel list after forking
      dispatch(listChannels());
      return params;
    } catch (error) {
      return rejectWithValue(error instanceof Error ? error.message : 'Failed to fork channel');
    }
  }
);

export const killChannelThunk = createAsyncThunk(
  'channels/killChannel',
  async (params: KillChannelParams, {rejectWithValue, dispatch}) => {
    try {
      await channelService.killChannel(params);
      // Refresh the channel list after killing
      dispatch(listChannels());
      return params.channelId;
    } catch (error) {
      return rejectWithValue(error instanceof Error ? error.message : 'Failed to kill channel');
    }
  }
);

export const getChannelThunk = createAsyncThunk(
  'channels/getChannel',
  async (channelId: string, {rejectWithValue}) => {
    try {
      const channel = await channelService.getChannel(channelId);
      return channel;
    } catch (error) {
      return rejectWithValue(error instanceof Error ? error.message : 'Failed to get channel');
    }
  }
);

export const getPublisherCountThunk = createAsyncThunk(
  'channels/getPublisherCount',
  async (channelId: string, {rejectWithValue}) => {
    try {
      const count = await channelService.getPublisherCount(channelId);
      return {channelId, count};
    } catch (error) {
      return rejectWithValue(error instanceof Error ? error.message : 'Failed to get publisher count');
    }
  }
);

// Export all actions and selectors
export * from '../slices/Channels.slice';