/**
 * @fileoverview A simple global store for application context.
 * Manages shared state like current page, project, team, and selected items.
 * Used by components like ds-ai-chat to be context-aware.
 * MVP2: Extended with admin settings and project configuration context.
 *
 * ARCHITECTURE NOTE: Context store uses localStorage directly for persistence.
 * Incognito mode handling is managed at the API client layer (api-client.js).
 * This removes circular dependencies and initialization order issues.
 */

/**
 * Page-specific context prompts for the AI assistant.
 * These provide contextual awareness for each page in the admin UI.
 */
const PAGE_CONTEXT_PROMPTS = {
  dashboard: 'You are helping with the DSS dashboard. The user can see project overview, recent activity, and quick actions.',
  projects: 'You are helping manage design system projects. The user can create, configure, and monitor projects.',
  services: 'You are helping analyze design system services and integrations.',
  'quick-wins': 'You are helping find quick win opportunities for design system adoption.',
  chat: 'You are a helpful AI assistant for the Design System Server.',
  tokens: 'You are helping manage design tokens. The user can extract, validate, sync, and transform tokens between formats.',
  components: 'You are helping with React components. The user can generate, audit, and validate design system components.',
  figma: 'You are helping with Figma integration. The user can connect files, sync tokens, and view visual diffs.',
  docs: 'You are helping with DSS documentation and guides.',
  teams: 'You are helping manage team access and permissions for design system projects.',
  audit: 'You are helping with design system audits. The user can identify issues, track adoption, and create quick wins.',
  plugins: 'You are helping manage DSS plugins and extensions.',
  settings: 'You are helping configure DSS settings and preferences.',
  storybook: 'You are helping with Storybook setup. The user can generate stories and configure theme documentation.',
};

class ContextStore extends EventTarget {
  constructor() {
    super();
    this.state = {
      // MVP1 Core Context (no defaults for project - force selection)
      projectId: localStorage.getItem('current_project_id') || null,
      teamId: localStorage.getItem('current_team_id') || 'ui',
      userId: localStorage.getItem('current_user_id') || 'admin',
      capabilities: JSON.parse(localStorage.getItem('user_capabilities') || '[]'),

      // MVP2: Admin settings context
      adminSettings: {
        hostname: localStorage.getItem('admin_hostname') || 'localhost',
        port: parseInt(localStorage.getItem('admin_port')) || 6006,
        isRemote: localStorage.getItem('admin_isRemote') === 'true' || false,
        dssSetupType: localStorage.getItem('admin_setupType') || 'local',
      },

      // MVP2: Current project configuration
      currentProject: null, // Will be set from ProjectStore
      currentProjectSkin: localStorage.getItem('current_project_skin') || 'default',

      // Legacy fields (keep for backward compatibility)
      page: null,
      project: null,
      team: 'all',
      selectedItems: [], // For batch actions on lists
      pageData: null,    // Current page-specific data (tokens, components, etc.)
    };
  }

  /**
   * Updates one or more context values and dispatches an event.
   * @param {Partial<typeof this.state>} newContext - An object with keys to update.
   */
  setContext(newContext) {
    let hasChanged = false;
    const changes = {};

    for (const key in newContext) {
      if (Object.prototype.hasOwnProperty.call(this.state, key)) {
        const oldValue = this.state[key];
        const newValue = newContext[key];

        // Deep comparison for arrays/objects
        const isDifferent = Array.isArray(newValue) || typeof newValue === 'object'
          ? JSON.stringify(oldValue) !== JSON.stringify(newValue)
          : oldValue !== newValue;

        if (isDifferent) {
          this.state[key] = newValue;
          changes[key] = { oldValue, newValue };
          hasChanged = true;
        }
      }
    }

    if (hasChanged) {
      this.dispatchEvent(new CustomEvent('context-change', {
        detail: {
          state: { ...this.state },
          changes
        }
      }));
    }
  }

  /**
   * Sets a single context value
   * @param {string} key - The context key
   * @param {any} value - The new value
   */
  set(key, value) {
    this.setContext({ [key]: value });
  }

  /**
   * Gets a single context value
   * @param {string} key - The context key
   * @returns {any}
   */
  get(key) {
    return this.state[key];
  }

  /**
   * Returns the current state (shallow copy).
   * @returns {typeof this.state}
   */
  getState() {
    return { ...this.state };
  }

  /**
   * Gets a context-aware prompt for the current page.
   * Used by the AI chat to provide page-specific assistance.
   * @returns {string} A contextual prompt string.
   */
  getContextPrompt() {
    const page = this.get('page') || 'dashboard';
    return PAGE_CONTEXT_PROMPTS[page] || PAGE_CONTEXT_PROMPTS.chat;
  }

  /**
   * A convenience method to subscribe to context changes.
   * @param {Function} callback - The function to call on change.
   * @returns {Function} An unsubscribe function.
   */
  subscribe(callback) {
    const handler = (event) => callback(event.detail);
    this.addEventListener('context-change', handler);
    // Return an unsubscribe function
    return () => this.removeEventListener('context-change', handler);
  }

  /**
   * Subscribe to changes on a specific key only
   * @param {string} key - The key to watch
   * @param {Function} callback - Called with (newValue, oldValue) when key changes
   * @returns {Function} Unsubscribe function
   */
  subscribeToKey(key, callback) {
    const handler = (event) => {
      const { changes } = event.detail;
      if (changes[key]) {
        callback(changes[key].newValue, changes[key].oldValue);
      }
    };
    this.addEventListener('context-change', handler);
    return () => this.removeEventListener('context-change', handler);
  }

  /**
   * Clears selection state
   */
  clearSelection() {
    this.setContext({ selectedItems: [] });
  }

  /**
   * Adds items to selection
   * @param {Array} items - Items to add
   */
  addToSelection(items) {
    const current = this.state.selectedItems || [];
    const newItems = Array.isArray(items) ? items : [items];
    this.setContext({
      selectedItems: [...new Set([...current, ...newItems])]
    });
  }

  /**
   * Removes items from selection
   * @param {Array} items - Items to remove
   */
  removeFromSelection(items) {
    const current = this.state.selectedItems || [];
    const toRemove = new Set(Array.isArray(items) ? items : [items]);
    this.setContext({
      selectedItems: current.filter(item => !toRemove.has(item))
    });
  }

  /**
   * MVP1: Set active project with storage persistence
   * @param {string} id - Project ID
   */
  setProject(id) {
    if (!id) {
      console.error('[ContextStore] Cannot set null projectId');
      return;
    }
    localStorage.setItem('current_project_id', id);
    this.setContext({ projectId: id, project: id }); // Update both for compatibility
  }

  /**
   * MVP1: Set active team with storage persistence
   * @param {string} id - Team ID (ui, ux, qa, admin)
   */
  setTeam(id) {
    localStorage.setItem('current_team_id', id);
    this.setContext({ teamId: id, team: id }); // Update both for compatibility
  }

  /**
   * MVP1: Check if project is selected
   * @returns {boolean}
   */
  hasProject() {
    return !!this.state.projectId;
  }

  /**
   * MVP1: Get full context for MCP tool calls
   * @returns {Object} Context object with projectId, teamId, userId
   */
  getMCPContext() {
    return {
      project_id: this.state.projectId,
      team_id: this.state.teamId,
      user_id: this.state.userId,
      capabilities: this.state.capabilities,
    };
  }

  /**
   * MVP2: Update admin settings in context
   * @param {Object} settings - Admin settings object
   */
  updateAdminSettings(settings) {
    this.setContext({
      adminSettings: {
        ...this.state.adminSettings,
        ...settings
      }
    });
  }

  /**
   * MVP2: Get current admin settings
   * @returns {Object} Admin settings
   */
  getAdminSettings() {
    return { ...this.state.adminSettings };
  }

  /**
   * MVP2: Update current project information
   * @param {Object} project - Project object from ProjectStore
   */
  setCurrentProject(project) {
    this.setContext({
      currentProject: project,
      projectId: project?.id || null,
      currentProjectSkin: project?.skinSelected || 'default'
    });
  }

  /**
   * MVP2: Get current project from context
   * @returns {Object|null} Current project or null
   */
  getCurrentProject() {
    return this.state.currentProject || null;
  }

  /**
   * MVP2: Update current project skin
   * @param {string} skin - Skin name
   */
  setCurrentProjectSkin(skin) {
    localStorage.setItem('current_project_skin', skin);
    this.setContext({
      currentProjectSkin: skin
    });
  }

  /**
   * MVP2: Check if system is configured for remote/headless mode
   * @returns {boolean}
   */
  isRemoteSetup() {
    return this.state.adminSettings.isRemote;
  }

  /**
   * MVP2: Check if system is configured for local mode
   * @returns {boolean}
   */
  isLocalSetup() {
    return !this.state.adminSettings.isRemote;
  }

  /**
   * MVP2: Get DSS setup type
   * @returns {string} 'local' or 'remote'
   */
  getDSSSetupType() {
    return this.state.adminSettings.dssSetupType;
  }
}

// Export a singleton instance
const contextStore = new ContextStore();
export default contextStore;
