import { Injectable, InjectionToken } from '@angular/core';

export interface A11yConfiguration {
  // Live announcer settings
  announcer?: {
    defaultPoliteness?: 'polite' | 'assertive';
    defaultDuration?: number;
    enabled?: boolean;
  };

  // Focus management settings
  focusManagement?: {
    trapFocus?: boolean;
    restoreFocus?: boolean;
    focusVisibleEnabled?: boolean;
    focusOriginDetection?: boolean;
  };

  // Keyboard navigation settings
  keyboard?: {
    enableShortcuts?: boolean;
    enableArrowNavigation?: boolean;
    enableRovingTabindex?: boolean;
    customShortcuts?: Array<{
      key: string;
      ctrlKey?: boolean;
      shiftKey?: boolean;
      altKey?: boolean;
      description?: string;
    }>;
  };

  // Skip links settings
  skipLinks?: {
    enabled?: boolean;
    position?: 'top' | 'after-header';
    showOnFocus?: boolean;
    links?: Array<{
      href: string;
      text: string;
    }>;
  };

  // Auto-enhancement settings
  autoEnhancement?: {
    enabled?: boolean;
    enhanceComponents?: string[]; // Component selectors to enhance
    addAriaAttributes?: boolean;
    addKeyboardSupport?: boolean;
    addFocusManagement?: boolean;
  };

  // High contrast and reduced motion
  accessibility?: {
    respectReducedMotion?: boolean;
    respectHighContrast?: boolean;
    injectAccessibilityStyles?: boolean;
    addBodyClasses?: boolean;
  };

  // Development settings
  development?: {
    warnings?: boolean;
    logging?: boolean;
    accessibilityAuditing?: boolean;
  };
}

export const DEFAULT_A11Y_CONFIG: Required<A11yConfiguration> = {
  announcer: {
    defaultPoliteness: 'polite',
    defaultDuration: 4000,
    enabled: true
  },
  focusManagement: {
    trapFocus: true,
    restoreFocus: true,
    focusVisibleEnabled: true,
    focusOriginDetection: true
  },
  keyboard: {
    enableShortcuts: true,
    enableArrowNavigation: true,
    enableRovingTabindex: true,
    customShortcuts: []
  },
  skipLinks: {
    enabled: true,
    position: 'top',
    showOnFocus: true,
    links: [
      { href: '#main', text: 'Skip to main content' },
      { href: '#navigation', text: 'Skip to navigation' }
    ]
  },
  autoEnhancement: {
    enabled: false,
    enhanceComponents: [],
    addAriaAttributes: true,
    addKeyboardSupport: true,
    addFocusManagement: true
  },
  accessibility: {
    respectReducedMotion: true,
    respectHighContrast: true,
    injectAccessibilityStyles: true,
    addBodyClasses: true
  },
  development: {
    warnings: true,
    logging: false,
    accessibilityAuditing: false
  }
};

export const A11Y_CONFIG = new InjectionToken<A11yConfiguration>('A11Y_CONFIG');

@Injectable({
  providedIn: 'root'
})
export class A11yConfigService {
  private config: Required<A11yConfiguration>;

  constructor() {
    this.config = { ...DEFAULT_A11Y_CONFIG };
  }

  /**
   * Update the configuration
   */
  updateConfig(config: Partial<A11yConfiguration>): void {
    this.config = this.mergeConfig(this.config, config);
  }

  /**
   * Get the current configuration
   */
  getConfig(): Required<A11yConfiguration> {
    return { ...this.config };
  }

  /**
   * Get a specific configuration section
   */
  getSection<K extends keyof A11yConfiguration>(section: K): Required<A11yConfiguration>[K] {
    return this.config[section];
  }

  /**
   * Check if a feature is enabled
   */
  isEnabled(feature: string): boolean {
    const parts = feature.split('.');
    let current: any = this.config;
    
    for (const part of parts) {
      if (current && typeof current === 'object' && part in current) {
        current = current[part];
      } else {
        return false;
      }
    }
    
    return current === true;
  }

  /**
   * Log a message if logging is enabled
   */
  log(message: string, ...args: any[]): void {
    if (this.config.development.logging) {
      console.log(`[A11y]`, message, ...args);
    }
  }

  /**
   * Log a warning if warnings are enabled
   */
  warn(message: string, ...args: any[]): void {
    if (this.config.development.warnings) {
      console.warn(`[A11y Warning]`, message, ...args);
    }
  }

  /**
   * Log an error
   */
  error(message: string, ...args: any[]): void {
    console.error(`[A11y Error]`, message, ...args);
  }

  /**
   * Deep merge configuration objects
   */
  private mergeConfig(
    base: Required<A11yConfiguration>, 
    override: Partial<A11yConfiguration>
  ): Required<A11yConfiguration> {
    const result = { ...base };
    
    for (const key in override) {
      const value = override[key as keyof A11yConfiguration];
      if (value !== undefined) {
        if (typeof value === 'object' && !Array.isArray(value) && value !== null) {
          (result as any)[key] = this.mergeObjects(
            (result as any)[key] || {},
            value
          );
        } else {
          (result as any)[key] = value;
        }
      }
    }
    
    return result;
  }

  /**
   * Deep merge objects
   */
  private mergeObjects(base: any, override: any): any {
    const result = { ...base };
    
    for (const key in override) {
      const value = override[key];
      if (value !== undefined) {
        if (typeof value === 'object' && !Array.isArray(value) && value !== null) {
          result[key] = this.mergeObjects(result[key] || {}, value);
        } else {
          result[key] = value;
        }
      }
    }
    
    return result;
  }
}