import {isDevMode} from '@angular/core';
import {ActionReducerMap, MetaReducer} from '@ngrx/store';
import {filterType, inputModeChoicesType} from '../services/AirWatchState';
import {ChatbotConversation} from '../services/conversations.service';
import {initialState} from '../redux/initialState';
import {ChatbotMessage} from '../services/chatbot.message.type';

// Define action types
export enum ActionTypes {
  UPDATE_USER = '[User] Update User',
  UPDATE_APP = '[App] Update App',
  UPDATE_CONVERSATIONS_LIST = '[Conversations] Update Conversations List',
  UPDATE_ACTIVE_CONVERSATION = '[Conversations] Update Active Conversation',
  POST_MESSAGE_TO_ACTIVE_CONVERSATION = '[Conversations] Post message to Active Conversation',
  UPDATE_LAST_SEEN_MESSAGE = '[Conversations] Update Last Seen Message',
  TOGGLE_CONVERSATIONS_LIST_PANEL = '[App] displayConversationListPanelLarge',
  UPDATE_SINGLE_CONVERSATION = '[Conversations] Update Single Conversation',
  SEND_USER_FEEDBACK = '[App] Send User Feedback',
  SWITCH_TO_NEXT_THEME = '[App] Switch To Next Theme',
  SWITCH_TO_NEXT_LANGUAGE = '[App] Switch To Next Language'
}

export interface PostMessageToActiveConversationAction {
  type: ActionTypes.POST_MESSAGE_TO_ACTIVE_CONVERSATION;
  payload: {
    message: ChatbotMessage;
  };
}

// Define action interfaces
export interface UpdateUserAction {
  type: ActionTypes.UPDATE_USER;
  payload: {
    isAuthenticated: boolean;
    id: string;
  };
}

export interface UpdateAppAction {
  type: ActionTypes.UPDATE_APP;
  payload: {
    backendAPIRoot?: string;
    displayConversationListPanelLarge?: boolean;
    displayFeedBackPanel?: boolean;
    displayErrorResponse?: boolean;
    displaySourcesPanelLarge?: boolean;
    displayTour?: boolean;
    displayWarningAIMaturing?: boolean;
    feedBackInput?: string;
    filters?: Array<filterType>;
    input?: string;
    inputMode?: inputModeChoicesType;
    lang?: string;
    notifications?: any[];
    ollamaAvailable?: boolean;
    searchInput?: string;
    version?: string;
  };
}

export interface UpdateConversationsListAction {
  type: ActionTypes.UPDATE_CONVERSATIONS_LIST;
  payload: Array<ChatbotConversation>;
}

export interface UpdateActiveConversationAction {
  type: ActionTypes.UPDATE_ACTIVE_CONVERSATION;
  payload: ChatbotConversation | Object;
}

export interface UpdateConversationPanelAction {
  type: ActionTypes.TOGGLE_CONVERSATIONS_LIST_PANEL;
  payload: boolean | null;
}

export interface UpdateLastSeenMessageAction {
  type: ActionTypes.UPDATE_LAST_SEEN_MESSAGE;
  payload: ChatbotMessage | Object;
}

export interface UpdateSingleConversationAction {
  type: ActionTypes.UPDATE_SINGLE_CONVERSATION;
  payload: {
    conversation: ChatbotConversation;
  };
}

export interface SendUserFeedbackAction {
  type: ActionTypes.SEND_USER_FEEDBACK;
  payload: {
    feedback: string;
  };
}

export interface SwitchToNextThemeAction {
  type: ActionTypes.SWITCH_TO_NEXT_THEME;
}

export interface SwitchToNextLanguageAction {
  type: ActionTypes.SWITCH_TO_NEXT_LANGUAGE;
}

export type AppActions =
  | UpdateUserAction
  | UpdateAppAction
  | UpdateConversationsListAction
  | UpdateActiveConversationAction
  | UpdateConversationPanelAction
  | PostMessageToActiveConversationAction
  | UpdateLastSeenMessageAction
  | UpdateSingleConversationAction
  | SendUserFeedbackAction
  | SwitchToNextThemeAction
  | SwitchToNextLanguageAction;

// Define the State interface
export interface StateInterface {
  user: {
    isAuthenticated: boolean;
    id: string;
  };
  app: {
    backendAPIRoot: string;
    displayConversationListPanelLarge: boolean;
    displayFeedBackPanel: boolean;
    displaySourcesPanelLarge: boolean;
    displayErrorResponse: boolean;
    demoMode: boolean;
    displayTour: boolean;
    displayWarningAIMaturing: boolean;
    feedBackInput: string;
    filters: Array<filterType>;
    input: string;
    inputMode: inputModeChoicesType;
    lang: string;
    langsList: Array<string>;
    loading: boolean;
    activeTheme: string;
    themesList: Array<string>;
    notifications: any[];
    ollamaAvailable: boolean; // Whether the Ollama backend is available
    searchInput: string;
    version: string;
    averageResponseTime: number; // Average backend response time in milliseconds
  };
  lastSeenMessage: ChatbotMessage | Object;
  conversationsList: Array<ChatbotConversation>;
  activeConversation: ChatbotConversation | Object;
}

// Define reducers
function userReducer(state = initialState.user, action: AppActions) {
  switch (action.type) {
    case ActionTypes.UPDATE_USER:
      return {
        ...state,
        ...action.payload
      };
    default:
      return state;
  }
}

function appReducer(state = initialState.app, action: AppActions) {
  switch (action.type) {
    case ActionTypes.UPDATE_APP:
      return {
        ...state,
        ...action.payload
      };
    case ActionTypes.SWITCH_TO_NEXT_THEME:
      // Find the main-button of the current active theme
      const currentThemeIndex = state.themesList.indexOf(state.activeTheme);
      // Calculate the main-button of the next theme (or go back to the first theme if at the end)
      const nextThemeIndex = (currentThemeIndex + 1) % state.themesList.length;
      // Get the next theme
      const nextTheme = state.themesList[nextThemeIndex];

      // Return a new state with the updated activeTheme
      return {
        ...state,
        activeTheme: nextTheme
      };
    case ActionTypes.SWITCH_TO_NEXT_LANGUAGE:
      // Find the main-button of the current language
      const currentLangIndex = state.langsList.indexOf(state.lang);
      // Calculate the main-button of the next language (or go back to the first language if at the end)
      const nextLangIndex = (currentLangIndex + 1) % state.langsList.length;
      // Get the next language
      const nextLang = state.langsList[nextLangIndex];

      // Return a new state with the updated lang
      return {
        ...state,
        lang: nextLang
      };
    default:
      return state;
  }
}

function conversationsListReducer(state = initialState.conversationsList, action: AppActions) {
  switch (action.type) {
    case ActionTypes.UPDATE_CONVERSATIONS_LIST:
      return [...action.payload];
    case ActionTypes.UPDATE_SINGLE_CONVERSATION:
      return state.map(conversation => {
        // If this is the conversation we want to update, replace it with the updated version
        if (conversation === action.payload.conversation) {
          return action.payload.conversation;
        }
        // Otherwise, keep the conversation unchanged
        return conversation;
      });
    default:
      return state;
  }
}

function activeConversationReducer(state = initialState.activeConversation, action: AppActions) {
  switch (action.type) {
    case ActionTypes.UPDATE_ACTIVE_CONVERSATION:
      return {...action.payload};
    case ActionTypes.POST_MESSAGE_TO_ACTIVE_CONVERSATION:
      // Create a new conversation object based on the current state
      const updatedConversation = {...state} as ChatbotConversation;

      if (!updatedConversation.messages) {
        updatedConversation.messages = [];
      } else {
        updatedConversation.messages = [...updatedConversation.messages];
      }

      const messageToAdd = action.payload.message || action.payload;
      console.log('messageToAdd', messageToAdd)
      updatedConversation.messages.push(messageToAdd);

      return updatedConversation;
    default:
      return state;
  }
}

function lastSeenMessageReducer(state = initialState.lastSeenMessage, action: AppActions) {
  switch (action.type) {
    case ActionTypes.UPDATE_LAST_SEEN_MESSAGE:
      return {...action.payload};
    default:
      return state;
  }
}

// Add reducers to ActionReducerMap
export const reducers: ActionReducerMap<StateInterface, AppActions> = {
  user: userReducer,
  app: appReducer,
  conversationsList: conversationsListReducer,
  activeConversation: activeConversationReducer,
  lastSeenMessage: lastSeenMessageReducer
};

export const metaReducers: MetaReducer<StateInterface, AppActions>[] = isDevMode() ? [] : [];
