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

export type AriaLivePoliteness = 'off' | 'polite' | 'assertive';

export interface LiveAnnouncementConfig {
  politeness?: AriaLivePoliteness;
  duration?: number;
  clearPrevious?: boolean;
}

@Injectable({
  providedIn: 'root'
})
export class LiveAnnouncerService implements OnDestroy {
  private liveElement?: HTMLElement;
  private timeouts: Map<AriaLivePoliteness, any> = new Map();

  constructor() {
    this.createLiveElement();
  }

  ngOnDestroy(): void {
    this.timeouts.forEach(timeout => clearTimeout(timeout));
    this.removeLiveElement();
  }

  /**
   * Announces a message to screen readers
   */
  announce(
    message: string,
    politeness: AriaLivePoliteness = 'polite',
    duration?: number
  ): void {
    this.announceWithConfig(message, {
      politeness,
      duration,
      clearPrevious: true
    });
  }

  /**
   * Announces a message with full configuration options
   */
  announceWithConfig(message: string, config: LiveAnnouncementConfig = {}): void {
    const {
      politeness = 'polite',
      duration = 4000,
      clearPrevious = true
    } = config;

    if (!this.liveElement) {
      this.createLiveElement();
    }

    if (!this.liveElement) return;

    // Clear any existing timeout for this politeness level
    if (this.timeouts.has(politeness)) {
      clearTimeout(this.timeouts.get(politeness));
    }

    // Clear previous message if requested
    if (clearPrevious) {
      this.liveElement.textContent = '';
    }

    // Set the politeness level
    this.liveElement.setAttribute('aria-live', politeness);

    // Announce the message
    setTimeout(() => {
      if (this.liveElement) {
        this.liveElement.textContent = message;
      }
    }, 100);

    // Clear the message after the specified duration
    if (duration > 0) {
      const timeoutId = setTimeout(() => {
        if (this.liveElement) {
          this.liveElement.textContent = '';
        }
        this.timeouts.delete(politeness);
      }, duration);

      this.timeouts.set(politeness, timeoutId);
    }
  }

  /**
   * Clears all current announcements
   */
  clear(): void {
    if (this.liveElement) {
      this.liveElement.textContent = '';
    }
    this.timeouts.forEach(timeout => clearTimeout(timeout));
    this.timeouts.clear();
  }

  /**
   * Announces multiple messages with delays between them
   */
  announceSequence(
    messages: string[],
    politeness: AriaLivePoliteness = 'polite',
    delayBetween = 1000
  ): void {
    messages.forEach((message, index) => {
      setTimeout(() => {
        this.announce(message, politeness);
      }, index * delayBetween);
    });
  }

  /**
   * Creates the live region element
   */
  private createLiveElement(): void {
    if (typeof document === 'undefined') return;

    // Remove existing element if it exists
    this.removeLiveElement();

    // Create new live region
    this.liveElement = document.createElement('div');
    this.liveElement.setAttribute('aria-live', 'polite');
    this.liveElement.setAttribute('aria-atomic', 'true');
    this.liveElement.setAttribute('id', 'a11y-live-announcer');
    
    // Make it invisible but still accessible to screen readers
    this.liveElement.style.position = 'absolute';
    this.liveElement.style.left = '-10000px';
    this.liveElement.style.width = '1px';
    this.liveElement.style.height = '1px';
    this.liveElement.style.overflow = 'hidden';

    document.body.appendChild(this.liveElement);
  }

  /**
   * Removes the live region element
   */
  private removeLiveElement(): void {
    const existing = document.getElementById('a11y-live-announcer');
    if (existing) {
      existing.remove();
    }
    this.liveElement = undefined;
  }
}