import { Injectable, signal, computed } from '@angular/core';
import { BackgroundConfig, BackgroundOptions, BackgroundState } from '../types/background.types';
import { BackgroundGenerator } from '../utils/background-generator';

@Injectable({
  providedIn: 'root'
})
export class BackgroundService {
  private _activeBackgrounds = signal<Map<string, BackgroundState>>(new Map());
  
  // Public computed signals
  readonly activeBackgrounds = computed(() => Array.from(this._activeBackgrounds().values()));
  readonly hasActiveBackgrounds = computed(() => this._activeBackgrounds().size > 0);

  /**
   * Apply a background to an element
   */
  applyBackground(element: HTMLElement, config: BackgroundConfig, id?: string): string {
    const backgroundId = id || this.generateId();
    const styles = BackgroundGenerator.generateCss(config);
    
    // Apply styles to element
    Object.entries(styles).forEach(([property, value]) => {
      element.style.setProperty(property, value);
    });

    // Add to active backgrounds
    this._activeBackgrounds.update(backgrounds => {
      const newMap = new Map(backgrounds);
      newMap.set(backgroundId, {
        active: true,
        config,
        element
      });
      return newMap;
    });

    return backgroundId;
  }

  /**
   * Apply a full-screen background
   */
  applyFullScreenBackground(config: BackgroundConfig, options?: Partial<BackgroundOptions>): string {
    const backgroundId = this.generateId();
    const element = this.createFullScreenElement(options);
    
    const styles = BackgroundGenerator.generateCss(config);
    Object.entries(styles).forEach(([property, value]) => {
      element.style.setProperty(property, value);
    });

    document.body.appendChild(element);

    this._activeBackgrounds.update(backgrounds => {
      const newMap = new Map(backgrounds);
      newMap.set(backgroundId, {
        active: true,
        config,
        element
      });
      return newMap;
    });

    return backgroundId;
  }

  /**
   * Update an existing background
   */
  updateBackground(id: string, config: BackgroundConfig): boolean {
    const backgroundState = this._activeBackgrounds().get(id);
    if (!backgroundState || !backgroundState.element) {
      return false;
    }

    const styles = BackgroundGenerator.generateCss(config);
    Object.entries(styles).forEach(([property, value]) => {
      backgroundState.element!.style.setProperty(property, value);
    });

    this._activeBackgrounds.update(backgrounds => {
      const newMap = new Map(backgrounds);
      const existing = newMap.get(id);
      if (existing) {
        existing.config = config;
        newMap.set(id, existing);
      }
      return newMap;
    });

    return true;
  }

  /**
   * Remove a background
   */
  removeBackground(id: string): boolean {
    const backgroundState = this._activeBackgrounds().get(id);
    if (!backgroundState) {
      return false;
    }

    // Remove full-screen element if it was created by this service
    if (backgroundState.element?.classList.contains('ui-background-fullscreen')) {
      backgroundState.element.remove();
    } else if (backgroundState.element) {
      // Clear inline styles for regular elements
      this.clearElementStyles(backgroundState.element);
    }

    this._activeBackgrounds.update(backgrounds => {
      const newMap = new Map(backgrounds);
      newMap.delete(id);
      return newMap;
    });

    return true;
  }

  /**
   * Remove all backgrounds
   */
  removeAllBackgrounds(): void {
    this._activeBackgrounds().forEach((state, id) => {
      this.removeBackground(id);
    });
  }

  /**
   * Get background state
   */
  getBackground(id: string): BackgroundState | undefined {
    return this._activeBackgrounds().get(id);
  }

  /**
   * Generate CSS for a configuration without applying it
   */
  generateCss(config: BackgroundConfig): { [key: string]: string } {
    return BackgroundGenerator.generateCss(config);
  }

  /**
   * Generate a background ID
   */
  private generateId(): string {
    return `bg-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
  }

  /**
   * Create a full-screen background element
   */
  private createFullScreenElement(options?: Partial<BackgroundOptions>): HTMLElement {
    const element = document.createElement('div');
    element.className = `ui-background-fullscreen ${options?.className || ''}`.trim();
    
    // Base full-screen styles
    element.style.position = 'fixed';
    element.style.top = '0';
    element.style.left = '0';
    element.style.width = '100%';
    element.style.height = '100%';
    element.style.pointerEvents = 'none';
    element.style.zIndex = (options?.zIndex || -1).toString();

    return element;
  }

  /**
   * Clear background-related styles from an element
   */
  private clearElementStyles(element: HTMLElement): void {
    const propertiesToClear = [
      'background',
      'background-image',
      'background-color',
      'background-size',
      'background-position',
      'background-repeat',
      'background-attachment',
      'backdrop-filter',
      'opacity',
      'animation'
    ];

    propertiesToClear.forEach(property => {
      element.style.removeProperty(property);
    });
  }
}