import type {
  IServiceStatus,
  IIncidentDetails,
  IStatusPageConfig,
  IMonitorFormData,
  IIncidentFormData,
} from '../interfaces/index.js';

type TStateChangeListener<T> = (data: T) => void;

/**
 * Simple observable implementation for state changes
 */
class SimpleObservable<T> {
  private listeners: Set<TStateChangeListener<T>> = new Set();

  subscribe(listener: TStateChangeListener<T>): () => void {
    this.listeners.add(listener);
    return () => this.listeners.delete(listener);
  }

  next(value: T): void {
    for (const listener of this.listeners) {
      listener(value);
    }
  }
}

/**
 * Centralized state management for the admin dashboard.
 * Handles cross-view data passing and state synchronization.
 */
export class AdminState {
  // Observable subjects for reactive updates
  public monitors$ = new SimpleObservable<IServiceStatus[]>();
  public incidents$ = new SimpleObservable<IIncidentDetails[]>();
  public config$ = new SimpleObservable<IStatusPageConfig>();

  // Current data
  private _monitors: IServiceStatus[] = [];
  private _incidents: IIncidentDetails[] = [];
  private _config: IStatusPageConfig | null = null;

  // Selected items for navigation context
  private _selectedMonitor: IServiceStatus | null = null;
  private _selectedIncident: IIncidentDetails | null = null;

  // Monitors
  get monitors(): IServiceStatus[] {
    return this._monitors;
  }

  set monitors(value: IServiceStatus[]) {
    this._monitors = value;
    this.monitors$.next(value);
  }

  // Incidents
  get incidents(): IIncidentDetails[] {
    return this._incidents;
  }

  set incidents(value: IIncidentDetails[]) {
    this._incidents = value;
    this.incidents$.next(value);
  }

  // Config
  get config(): IStatusPageConfig | null {
    return this._config;
  }

  set config(value: IStatusPageConfig | null) {
    this._config = value;
    if (value) {
      this.config$.next(value);
    }
  }

  // Selected monitor for edit navigation
  setSelectedMonitor(monitor: IServiceStatus | null): void {
    this._selectedMonitor = monitor;
  }

  getSelectedMonitor(): IServiceStatus | null {
    return this._selectedMonitor;
  }

  clearSelectedMonitor(): void {
    this._selectedMonitor = null;
  }

  // Selected incident for edit navigation
  setSelectedIncident(incident: IIncidentDetails | null): void {
    this._selectedIncident = incident;
  }

  getSelectedIncident(): IIncidentDetails | null {
    return this._selectedIncident;
  }

  clearSelectedIncident(): void {
    this._selectedIncident = null;
  }

  // Helper methods
  getCategories(): string[] {
    const categories = new Set<string>();
    for (const monitor of this._monitors) {
      if (monitor.category) {
        categories.add(monitor.category);
      }
    }
    return Array.from(categories).sort();
  }

  getAvailableServices(): IServiceStatus[] {
    return [...this._monitors];
  }

  getMonitorById(id: string): IServiceStatus | undefined {
    return this._monitors.find(m => m.id === id);
  }

  getIncidentById(id: string): IIncidentDetails | undefined {
    return this._incidents.find(i => i.id === id);
  }

  getActiveIncidents(): IIncidentDetails[] {
    return this._incidents.filter(
      i => !['resolved', 'postmortem'].includes(i.status)
    );
  }

  getPastIncidents(): IIncidentDetails[] {
    return this._incidents.filter(
      i => ['resolved', 'postmortem'].includes(i.status)
    );
  }

  // CRUD operations (these would typically call an API)
  addMonitor(monitor: IServiceStatus): void {
    this.monitors = [...this._monitors, monitor];
  }

  updateMonitor(id: string, data: Partial<IMonitorFormData>): void {
    this.monitors = this._monitors.map(m =>
      m.id === id ? { ...m, ...data } : m
    );
  }

  deleteMonitor(id: string): void {
    this.monitors = this._monitors.filter(m => m.id !== id);
  }

  addIncident(incident: IIncidentDetails): void {
    this.incidents = [...this._incidents, incident];
  }

  updateIncident(id: string, data: Partial<IIncidentFormData>): void {
    this.incidents = this._incidents.map(i =>
      i.id === id ? { ...i, ...data } : i
    );
  }

  deleteIncident(id: string): void {
    this.incidents = this._incidents.filter(i => i.id !== id);
  }
}

// Singleton instance
export const adminState = new AdminState();
