/**
 * MyUIbrix Editor Controller
 * Manages editor state, variant changes, and real-time preview
 */

export interface ElementConfig {
  element_name: string;
  variant: string;
  visible: boolean;
  display_order: number;
  custom_styles?: Record<string, any>;
}

export interface EditorState {
  isEditing: boolean;
  selectedElement: string | null;
  configs: Record<string, ElementConfig>;
  isDirty: boolean;
  lastSaved: Date | null;
}

export class EditorController {
  private state: EditorState;
  private listeners: Set<(state: EditorState) => void>;
  private saveTimeout: NodeJS.Timeout | null = null;
  
  constructor() {
    this.state = {
      isEditing: false,
      selectedElement: null,
      configs: {},
      isDirty: false,
      lastSaved: null,
    };
    this.listeners = new Set();
  }

  /**
   * Subscribe to state changes
   */
  subscribe(listener: (state: EditorState) => void): () => void {
    this.listeners.add(listener);
    return () => this.listeners.delete(listener);
  }

  /**
   * Get current state
   */
  getState(): EditorState {
    return { ...this.state };
  }

  /**
   * Update variant for an element with immediate visual feedback
   */
  updateVariant(elementName: string, variant: string): void {
    console.log(`[EditorController] Updating variant: ${elementName} -> ${variant}`);
    
    const config = this.state.configs[elementName] || {
      element_name: elementName,
      variant: 'default',
      visible: true,
      display_order: 0,
    };

    this.state = {
      ...this.state,
      configs: {
        ...this.state.configs,
        [elementName]: {
          ...config,
          variant,
        },
      },
      isDirty: true,
    };

    this.notifyListeners();
    this.dispatchVariantChange(elementName, variant);
    this.scheduleAutoSave();
  }

  /**
   * Toggle element visibility
   */
  toggleVisibility(elementName: string): void {
    const config = this.state.configs[elementName];
    if (!config) return;

    const newVisible = !config.visible;
    
    this.state = {
      ...this.state,
      configs: {
        ...this.state.configs,
        [elementName]: {
          ...config,
          visible: newVisible,
        },
      },
      isDirty: true,
    };

    this.notifyListeners();
    this.dispatchVisibilityChange(elementName, newVisible);
    this.scheduleAutoSave();
  }

  /**
   * Reorder elements
   */
  reorderElements(newOrder: string[]): void {
    console.log('[EditorController] Reordering elements:', newOrder);
    
    const updatedConfigs = { ...this.state.configs };
    newOrder.forEach((elementName, index) => {
      if (updatedConfigs[elementName]) {
        updatedConfigs[elementName] = {
          ...updatedConfigs[elementName],
          display_order: index,
        };
      }
    });

    this.state = {
      ...this.state,
      configs: updatedConfigs,
      isDirty: true,
    };

    this.notifyListeners();
    this.dispatchReorderChange(newOrder);
    this.scheduleAutoSave();
  }

  /**
   * Update custom styles for an element
   */
  updateStyles(elementName: string, styles: Record<string, any>): void {
    const config = this.state.configs[elementName];
    if (!config) return;

    this.state = {
      ...this.state,
      configs: {
        ...this.state.configs,
        [elementName]: {
          ...config,
          custom_styles: styles,
        },
      },
      isDirty: true,
    };

    this.notifyListeners();
    this.dispatchStyleChange(elementName, styles);
    this.scheduleAutoSave();
  }

  /**
   * Set selected element
   */
  selectElement(elementName: string | null): void {
    this.state = {
      ...this.state,
      selectedElement: elementName,
    };
    this.notifyListeners();
  }

  /**
   * Enter edit mode
   */
  startEditing(initialConfigs: Record<string, ElementConfig>): void {
    console.log('[EditorController] Starting edit mode');
    this.state = {
      ...this.state,
      isEditing: true,
      configs: initialConfigs,
      isDirty: false,
    };
    this.notifyListeners();
  }

  /**
   * Exit edit mode
   */
  stopEditing(): void {
    console.log('[EditorController] Stopping edit mode');
    if (this.saveTimeout) {
      clearTimeout(this.saveTimeout);
      this.saveTimeout = null;
    }
    
    this.state = {
      ...this.state,
      isEditing: false,
      selectedElement: null,
    };
    this.notifyListeners();
  }

  /**
   * Save current state
   */
  async save(): Promise<boolean> {
    if (!this.state.isDirty) {
      console.log('[EditorController] No changes to save');
      return true;
    }

    try {
      console.log('[EditorController] Saving changes...');
      const configs = Object.values(this.state.configs);
      
      // TODO: Replace with actual API call
      const response = await fetch('/api/v1/admin/page-elements/batch', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        credentials: 'include',
        body: JSON.stringify({ configs }),
      });

      if (!response.ok) {
        throw new Error('Save failed');
      }

      this.state = {
        ...this.state,
        isDirty: false,
        lastSaved: new Date(),
      };
      this.notifyListeners();
      
      console.log('[EditorController] Changes saved successfully');
      return true;
    } catch (error) {
      console.error('[EditorController] Save failed:', error);
      return false;
    }
  }

  /**
   * Force refresh of all elements
   */
  forceRefresh(): void {
    console.log('[EditorController] Force refreshing all elements');
    window.dispatchEvent(new CustomEvent('myuibrix-force-refresh', {
      detail: { timestamp: Date.now() }
    }));
  }

  // Private methods

  private notifyListeners(): void {
    this.listeners.forEach(listener => {
      try {
        listener(this.getState());
      } catch (error) {
        console.error('[EditorController] Listener error:', error);
      }
    });
  }

  private dispatchVariantChange(elementName: string, variant: string): void {
    const config = this.state.configs[elementName];
    window.dispatchEvent(new CustomEvent('myuibrix-change', {
      detail: {
        elementName,
        variant,
        visible: config?.visible ?? true,
        previewMode: true,
        timestamp: Date.now(),
      }
    }));
  }

  private dispatchVisibilityChange(elementName: string, visible: boolean): void {
    const config = this.state.configs[elementName];
    window.dispatchEvent(new CustomEvent('myuibrix-change', {
      detail: {
        elementName,
        variant: config?.variant ?? 'default',
        visible,
        previewMode: true,
        timestamp: Date.now(),
      }
    }));
  }

  private dispatchReorderChange(order: string[]): void {
    window.dispatchEvent(new CustomEvent('myuibrix-reorder', {
      detail: {
        order,
        previewMode: true,
        timestamp: Date.now(),
      }
    }));
  }

  private dispatchStyleChange(elementName: string, styles: Record<string, any>): void {
    window.dispatchEvent(new CustomEvent('myuibrix-style-change', {
      detail: {
        elementName,
        styles,
        previewMode: true,
        timestamp: Date.now(),
      }
    }));
  }

  private scheduleAutoSave(): void {
    if (this.saveTimeout) {
      clearTimeout(this.saveTimeout);
    }

    // Auto-save after 2 seconds of inactivity
    this.saveTimeout = setTimeout(() => {
      this.save();
    }, 2000);
  }
}

// Singleton instance
export const editorController = new EditorController();
