/**
 * store.mjs — Lightweight reactive state store
 * Redux-inspired dispatch/subscribe with selector-based subscriptions
 */

const INITIAL_STATE = {
  ui: {
    currentView: 'chat',
    theme: localStorage.getItem('aido-theme') || 'dark',
    sidebarCollapsed: false,
    rightPanelCollapsed: false,
    focusMode: false,
    isMobile: false
  },
  voice: {
    status: 'idle', // idle | listening | processing | speaking
    audioLevel: 0,
    enabled: false
  },
  chat: {
    messages: [],
    streaming: false,
    streamText: '',
    streamAbortController: null
  },
  agent: {
    status: 'unknown', // running | paused | idle | busy | unknown
    loopRunning: false,
    uptime: 0,
    lastLoop: null,
    activeTasks: []
  },
  persona: {
    name: 'AI-Do',
    greeting: 'Hello! I\'m AI-Do, your personal AI.',
    avatarStyle: 'default',
    traits: { creativity: 0.7, verbosity: 0.5, formality: 0.3, humor: 0.5 }
  },
  activity: {
    feed: [],
    maxItems: 100
  },
  skills: {
    list: [],
    palette: [],
    running: null
  },
  workspaces: {
    list: [],
    active: null
  },
  knowledge: {
    stats: null,
    searchResults: []
  },
  settings: {}
};

function deepClone(obj) {
  return JSON.parse(JSON.stringify(obj));
}

function getByPath(obj, path) {
  return path.split('.').reduce((curr, key) => curr?.[key], obj);
}

const reducers = {
  // UI
  SET_VIEW: (state, view) => ({ ...state, ui: { ...state.ui, currentView: view } }),
  SET_THEME: (state, theme) => {
    localStorage.setItem('aido-theme', theme);
    document.documentElement.setAttribute('data-theme', theme);
    return { ...state, ui: { ...state.ui, theme } };
  },
  TOGGLE_SIDEBAR: (state) => ({ ...state, ui: { ...state.ui, sidebarCollapsed: !state.ui.sidebarCollapsed } }),
  TOGGLE_RIGHT_PANEL: (state) => ({ ...state, ui: { ...state.ui, rightPanelCollapsed: !state.ui.rightPanelCollapsed } }),
  SET_FOCUS_MODE: (state, enabled) => ({ ...state, ui: { ...state.ui, focusMode: enabled } }),
  SET_MOBILE: (state, isMobile) => ({ ...state, ui: { ...state.ui, isMobile } }),

  // Voice
  SET_VOICE_STATUS: (state, status) => ({ ...state, voice: { ...state.voice, status } }),
  SET_AUDIO_LEVEL: (state, level) => ({ ...state, voice: { ...state.voice, audioLevel: level } }),
  SET_VOICE_ENABLED: (state, enabled) => ({ ...state, voice: { ...state.voice, enabled } }),

  // Chat
  ADD_MESSAGE: (state, msg) => ({
    ...state,
    chat: { ...state.chat, messages: [...state.chat.messages, { ...msg, id: msg.id || Date.now() }] }
  }),
  SET_MESSAGES: (state, messages) => ({ ...state, chat: { ...state.chat, messages } }),
  CLEAR_MESSAGES: (state) => ({ ...state, chat: { ...state.chat, messages: [] } }),
  SET_STREAMING: (state, streaming) => ({
    ...state,
    chat: { ...state.chat, streaming, streamText: streaming ? state.chat.streamText : '' }
  }),
  APPEND_STREAM: (state, text) => ({ ...state, chat: { ...state.chat, streamText: text } }),
  SET_STREAM_ABORT: (state, controller) => ({ ...state, chat: { ...state.chat, streamAbortController: controller } }),

  // Agent
  SET_AGENT_STATUS: (state, data) => {
    const info = typeof data === 'string' ? { status: data } : { ...data };
    // The backend sends a 'state' field (e.g. 'idle', 'processing_messages', 'thinking').
    // Map it to a normalised 'status' for the UI.
    if (info.state && !info.status) {
      const s = info.state;
      if (s === 'idle' || s === 'loop_start' || s === 'loop_disabled' || s === 'checking_health') {
        info.status = 'idle';
      } else if (s === 'paused' || s === 'autonomy_paused') {
        info.status = 'paused';
      } else {
        info.status = 'running';
      }
    }
    return { ...state, agent: { ...state.agent, ...info } };
  },

  // Persona
  SET_PERSONA: (state, persona) => ({ ...state, persona: { ...state.persona, ...persona } }),

  // Activity
  ADD_ACTIVITY: (state, event) => {
    const feed = [event, ...state.activity.feed].slice(0, state.activity.maxItems);
    return { ...state, activity: { ...state.activity, feed } };
  },
  SET_ACTIVITY_FEED: (state, feed) => ({ ...state, activity: { ...state.activity, feed } }),

  // Skills
  SET_SKILLS: (state, list) => ({ ...state, skills: { ...state.skills, list } }),
  SET_SKILL_PALETTE: (state, palette) => ({ ...state, skills: { ...state.skills, palette } }),
  SET_SKILL_RUNNING: (state, name) => ({ ...state, skills: { ...state.skills, running: name } }),

  // Workspaces
  SET_WORKSPACES: (state, list) => ({ ...state, workspaces: { ...state.workspaces, list } }),
  SET_ACTIVE_WORKSPACE: (state, active) => ({ ...state, workspaces: { ...state.workspaces, active } }),

  // Knowledge
  SET_KG_STATS: (state, stats) => ({ ...state, knowledge: { ...state.knowledge, stats } }),
  SET_KG_RESULTS: (state, results) => ({ ...state, knowledge: { ...state.knowledge, searchResults: results } }),

  // Settings
  SET_SETTINGS: (state, settings) => ({ ...state, settings: { ...state.settings, ...settings } }),

  // Batch
  BATCH_UPDATE: (state, updates) => {
    let next = state;
    for (const [action, payload] of updates) {
      if (reducers[action]) {
        next = reducers[action](next, payload);
      }
    }
    return next;
  }
};

class Store {
  constructor() {
    this._state = deepClone(INITIAL_STATE);
    this._subscribers = [];
    this._middlewares = [];
    this._customReducers = {};
  }

  getState() {
    return this._state;
  }

  dispatch(action, payload) {
    const prev = this._state;

    // Run middlewares
    for (const mw of this._middlewares) {
      const result = mw(action, payload, prev);
      if (result === false) return; // middleware can cancel
    }

    const reducer = reducers[action] || this._customReducers[action];
    if (!reducer) {
      console.warn(`[store] Unknown action: ${action}`);
      return;
    }

    this._state = reducer(prev, payload);

    // Notify subscribers
    for (const sub of this._subscribers) {
      try {
        const prevVal = sub.selector(prev);
        const nextVal = sub.selector(this._state);
        if (prevVal !== nextVal) {
          sub.callback(nextVal, prevVal);
        }
      } catch (err) {
        console.error('[store] Subscriber error:', err);
      }
    }
  }

  subscribe(selector, callback) {
    const sub = { selector, callback };
    this._subscribers.push(sub);
    return () => {
      const idx = this._subscribers.indexOf(sub);
      if (idx !== -1) this._subscribers.splice(idx, 1);
    };
  }

  use(middleware) {
    this._middlewares.push(middleware);
  }

  addReducer(action, reducer) {
    this._customReducers[action] = reducer;
  }
}

// Singleton
const store = new Store();
export default store;
export { INITIAL_STATE };
