import { createSlice } from '@reduxjs/toolkit';

const initialState = {
  // Core mixer collections
  chatMixer: null,
  broadcastMixer: null,
  recordingMixer: null,

  // Mixer arrays by type (populated by groupMixersByType)
  recordingTrackMixers: [],
  backingTrackMixers: [],
  jamTrackMixers: [],
  metronomeTrackMixers: [],
  adhocTrackMixers: [],

  // Master and personal mixer arrays (source data from jamClient)
  masterMixers: [],
  personalMixers: [],

  // Lookup tables (computed by organizeMixers reducer)
  allMixers: {}, // Format: { 'M123': mixer, 'P456': mixer }
  mixersByResourceId: {}, // Format: { 'rid': { master: mixer, personal: mixer } }
  mixersByTrackId: {}, // Format: { 'trackId': { master: mixer, personal: mixer } }

  // Simulated/derived mixers for category controls
  simulatedMusicCategoryMixers: {
    PERSONAL: null,
    MASTER: null
  },
  simulatedChatCategoryMixers: {
    PERSONAL: null,
    MASTER: null
  },

  // Metronome state
  metronome: null, // Current metronome mixer object
  metronomeSettings: {
    tempo: 120,
    sound: "Beep",
    cricket: false
  },

  // Media summary (open/closed states for media types)
  // This tracks what media is currently open in the session
  mediaSummary: {
    mediaOpen: false,
    backingTrackOpen: false,
    jamTrackOpen: false,
    recordingOpen: false,
    metronomeOpen: false,
    isOpener: false,
    userNeedsMediaControls: false,
    jamTrack: null
  },

  // Peer state (for managing missing audio users)
  noAudioUsers: {},
  clientsWithAudioOverride: {},
  missingMixerPeers: {},
  checkingMissingPeers: {},

  // Ready state (indicates mixers have been organized and are ready to use)
  isReady: false,

  // Loading/errors
  loading: false,
  error: null
};

export const mixersSlice = createSlice({
  name: 'mixers',
  initialState,
  reducers: {
    // Initialize from jamClient.SessionGetAllControlState
    setMasterMixers: (state, action) => {
      state.masterMixers = action.payload;
    },

    setPersonalMixers: (state, action) => {
      state.personalMixers = action.payload;
    },

    // Organize mixers - builds lookup tables (matches useMixerHelper organizeMixers logic)
    // This should be called after master/personal mixers are set
    organizeMixers: (state) => {
      const newAllMixers = {};
      const newMixersByResourceId = {};
      const newMixersByTrackId = {};

      // Process master mixers
      for (const masterMixer of state.masterMixers) {
        newAllMixers['M' + masterMixer.id] = masterMixer;

        const mixerPair = {};
        newMixersByResourceId[masterMixer.rid] = mixerPair;
        newMixersByTrackId[masterMixer.id] = mixerPair;
        mixerPair.master = masterMixer;
      }

      // Process personal mixers
      for (const personalMixer of state.personalMixers) {
        newAllMixers['P' + personalMixer.id] = personalMixer;

        let mixerPair = newMixersByResourceId[personalMixer.rid];
        if (!mixerPair) {
          // Create new pair if no master exists (e.g., MonitorGroup)
          mixerPair = {};
          newMixersByResourceId[personalMixer.rid] = mixerPair;
        }
        newMixersByTrackId[personalMixer.id] = mixerPair;
        mixerPair.personal = personalMixer;
      }

      // Update state
      state.allMixers = { ...state.allMixers, ...newAllMixers };
      state.mixersByResourceId = { ...state.mixersByResourceId, ...newMixersByResourceId };
      state.mixersByTrackId = { ...state.mixersByTrackId, ...newMixersByTrackId };
      state.isReady = true;
    },

    // Group mixers by type - categorizes mixers into recording, backing, jam, metronome, adhoc
    // This complex logic will be implemented in useMixerHelper Redux version
    // For now, just accept the categorized arrays
    setRecordingTrackMixers: (state, action) => {
      state.recordingTrackMixers = action.payload;
    },

    setBackingTrackMixers: (state, action) => {
      state.backingTrackMixers = action.payload;
    },

    setJamTrackMixers: (state, action) => {
      state.jamTrackMixers = action.payload;
    },

    setMetronomeTrackMixers: (state, action) => {
      state.metronomeTrackMixers = action.payload;
    },

    setAdhocTrackMixers: (state, action) => {
      state.adhocTrackMixers = action.payload;
    },

    // Update individual mixer (for real-time updates from jamClient)
    updateMixer: (state, action) => {
      const { mixerId, mode, updates } = action.payload;
      const key = (mode ? 'M' : 'P') + mixerId;

      if (state.allMixers[key]) {
        state.allMixers[key] = { ...state.allMixers[key], ...updates };

        // Also update in master/personal arrays
        if (mode) {
          const index = state.masterMixers.findIndex(m => m.id === mixerId);
          if (index !== -1) {
            state.masterMixers[index] = { ...state.masterMixers[index], ...updates };
          }
        } else {
          const index = state.personalMixers.findIndex(m => m.id === mixerId);
          if (index !== -1) {
            state.personalMixers[index] = { ...state.personalMixers[index], ...updates };
          }
        }
      }
    },

    // Metronome
    setMetronome: (state, action) => {
      state.metronome = action.payload;
      state.mediaSummary.metronomeOpen = !!action.payload;
    },

    setMetronomeSettings: (state, action) => {
      state.metronomeSettings = { ...state.metronomeSettings, ...action.payload };
    },

    // Media summary updates
    updateMediaSummary: (state, action) => {
      state.mediaSummary = { ...state.mediaSummary, ...action.payload };
    },

    setMediaSummary: (state, action) => {
      state.mediaSummary = action.payload;
    },

    // Chat/broadcast mixers
    setChatMixer: (state, action) => {
      state.chatMixer = action.payload;
    },

    setBroadcastMixer: (state, action) => {
      state.broadcastMixer = action.payload;
    },

    setRecordingMixer: (state, action) => {
      state.recordingMixer = action.payload;
    },

    // Simulated mixers (for category controls)
    setSimulatedMusicCategoryMixers: (state, action) => {
      state.simulatedMusicCategoryMixers = action.payload;
    },

    setSimulatedChatCategoryMixers: (state, action) => {
      state.simulatedChatCategoryMixers = action.payload;
    },

    // Peer management
    addNoAudioUser: (state, action) => {
      state.noAudioUsers[action.payload] = true;
    },

    removeNoAudioUser: (state, action) => {
      delete state.noAudioUsers[action.payload];
    },

    setNoAudioUsers: (state, action) => {
      state.noAudioUsers = action.payload;
    },

    setClientsWithAudioOverride: (state, action) => {
      state.clientsWithAudioOverride = action.payload;
    },

    setMissingMixerPeers: (state, action) => {
      state.missingMixerPeers = action.payload;
    },

    setCheckingMissingPeers: (state, action) => {
      state.checkingMissingPeers = action.payload;
    },

    // Clear on session end
    clearMixers: (state) => {
      return { ...initialState };
    }
  }
});

export const {
  setMasterMixers,
  setPersonalMixers,
  organizeMixers,
  setRecordingTrackMixers,
  setBackingTrackMixers,
  setJamTrackMixers,
  setMetronomeTrackMixers,
  setAdhocTrackMixers,
  updateMixer,
  setMetronome,
  setMetronomeSettings,
  updateMediaSummary,
  setMediaSummary,
  setChatMixer,
  setBroadcastMixer,
  setRecordingMixer,
  setSimulatedMusicCategoryMixers,
  setSimulatedChatCategoryMixers,
  addNoAudioUser,
  removeNoAudioUser,
  setNoAudioUsers,
  setClientsWithAudioOverride,
  setMissingMixerPeers,
  setCheckingMissingPeers,
  clearMixers
} = mixersSlice.actions;

export default mixersSlice.reducer;

// Selectors
export const selectAllMixers = (state) => state.mixers.allMixers;
export const selectMasterMixers = (state) => state.mixers.masterMixers;
export const selectPersonalMixers = (state) => state.mixers.personalMixers;
export const selectMixersByResourceId = (state) => state.mixers.mixersByResourceId;
export const selectMixersByTrackId = (state) => state.mixers.mixersByTrackId;

export const selectChatMixer = (state) => state.mixers.chatMixer;
export const selectBroadcastMixer = (state) => state.mixers.broadcastMixer;
export const selectRecordingMixer = (state) => state.mixers.recordingMixer;

export const selectMetronome = (state) => state.mixers.metronome;
export const selectMetronomeSettings = (state) => state.mixers.metronomeSettings;
export const selectMediaSummary = (state) => state.mixers.mediaSummary;

export const selectMixersReady = (state) => state.mixers.isReady;

export const selectBackingTrackMixers = (state) => state.mixers.backingTrackMixers;
export const selectJamTrackMixers = (state) => state.mixers.jamTrackMixers;
export const selectRecordingTrackMixers = (state) => state.mixers.recordingTrackMixers;
export const selectMetronomeTrackMixers = (state) => state.mixers.metronomeTrackMixers;
export const selectAdhocTrackMixers = (state) => state.mixers.adhocTrackMixers;

export const selectSimulatedMusicCategoryMixers = (state) => state.mixers.simulatedMusicCategoryMixers;
export const selectSimulatedChatCategoryMixers = (state) => state.mixers.simulatedChatCategoryMixers;

export const selectNoAudioUsers = (state) => state.mixers.noAudioUsers;
export const selectClientsWithAudioOverride = (state) => state.mixers.clientsWithAudioOverride;
export const selectMissingMixerPeers = (state) => state.mixers.missingMixerPeers;
export const selectCheckingMissingPeers = (state) => state.mixers.checkingMissingPeers;

// Computed selector for getting a specific mixer by ID and mode
export const selectMixer = (mixerId, mode) => (state) => {
  const key = (mode ? 'M' : 'P') + mixerId;
  return state.mixers.allMixers[key];
};

// Computed selector for getting mixer pair by resource ID
export const selectMixerPairByResourceId = (resourceId) => (state) => {
  return state.mixers.mixersByResourceId[resourceId];
};

// Computed selector for getting mixer pair by track ID
export const selectMixerPairByTrackId = (trackId) => (state) => {
  return state.mixers.mixersByTrackId[trackId];
};
