/**
 * ConsentServiceBase — Angular Service Wrapper.
 *
 * Phase 4: extracted from angular/index.ts.
 */

import { ConsentManager } from '../core/ConsentManager';
import type {
  ConsentCategories,
  ConsentCategory,
  ConsentConfig,
  ConsentState,
} from '../types';
import type { IConsentService } from './interface';

/**
 * ConsentService - Angular Service Wrapper
 *
 * Diese Klasse kann als Angular Service registriert werden:
 *
 * @example
 * ```typescript
 * // consent.service.ts
 * import { Injectable } from '@angular/core';
 * import { ConsentServiceBase } from '@breakpilot/consent-sdk/angular';
 *
 * @Injectable({ providedIn: 'root' })
 * export class ConsentService extends ConsentServiceBase {
 *   constructor() {
 *     super({
 *       apiEndpoint: environment.consentApiEndpoint,
 *       siteId: environment.siteId,
 *     });
 *   }
 * }
 * ```
 */
export class ConsentServiceBase implements IConsentService {
  private manager: ConsentManager;
  private _consent: ConsentState | null = null;
  private _isInitialized = false;
  private _isLoading = true;
  private _isBannerVisible = false;

  // Callbacks fuer Angular Change Detection
  private changeCallbacks: Array<(consent: ConsentState) => void> = [];
  private bannerShowCallbacks: Array<() => void> = [];
  private bannerHideCallbacks: Array<() => void> = [];

  constructor(config: ConsentConfig) {
    this.manager = new ConsentManager(config);
    this.setupEventListeners();
    this.initialize();
  }

  // ---------------------------------------------------------------------------
  // Getters
  // ---------------------------------------------------------------------------

  get isInitialized(): boolean {
    return this._isInitialized;
  }

  get isLoading(): boolean {
    return this._isLoading;
  }

  get isBannerVisible(): boolean {
    return this._isBannerVisible;
  }

  get consent(): ConsentState | null {
    return this._consent;
  }

  get needsConsent(): boolean {
    return this.manager.needsConsent();
  }

  // ---------------------------------------------------------------------------
  // Methods
  // ---------------------------------------------------------------------------

  hasConsent(category: ConsentCategory): boolean {
    return this.manager.hasConsent(category);
  }

  async acceptAll(): Promise<void> {
    await this.manager.acceptAll();
  }

  async rejectAll(): Promise<void> {
    await this.manager.rejectAll();
  }

  async saveSelection(categories: Partial<ConsentCategories>): Promise<void> {
    await this.manager.setConsent(categories);
    this.manager.hideBanner();
  }

  showBanner(): void {
    this.manager.showBanner();
  }

  hideBanner(): void {
    this.manager.hideBanner();
  }

  showSettings(): void {
    this.manager.showSettings();
  }

  // ---------------------------------------------------------------------------
  // Change Detection Support
  // ---------------------------------------------------------------------------

  /**
   * Registriert Callback fuer Consent-Aenderungen
   * (fuer Angular Change Detection)
   */
  onConsentChange(callback: (consent: ConsentState) => void): () => void {
    this.changeCallbacks.push(callback);
    return () => {
      const index = this.changeCallbacks.indexOf(callback);
      if (index > -1) {
        this.changeCallbacks.splice(index, 1);
      }
    };
  }

  /**
   * Registriert Callback wenn Banner angezeigt wird
   */
  onBannerShow(callback: () => void): () => void {
    this.bannerShowCallbacks.push(callback);
    return () => {
      const index = this.bannerShowCallbacks.indexOf(callback);
      if (index > -1) {
        this.bannerShowCallbacks.splice(index, 1);
      }
    };
  }

  /**
   * Registriert Callback wenn Banner ausgeblendet wird
   */
  onBannerHide(callback: () => void): () => void {
    this.bannerHideCallbacks.push(callback);
    return () => {
      const index = this.bannerHideCallbacks.indexOf(callback);
      if (index > -1) {
        this.bannerHideCallbacks.splice(index, 1);
      }
    };
  }

  // ---------------------------------------------------------------------------
  // Internal
  // ---------------------------------------------------------------------------

  private setupEventListeners(): void {
    this.manager.on('change', (consent) => {
      this._consent = consent;
      this.changeCallbacks.forEach((cb) => cb(consent));
    });

    this.manager.on('banner_show', () => {
      this._isBannerVisible = true;
      this.bannerShowCallbacks.forEach((cb) => cb());
    });

    this.manager.on('banner_hide', () => {
      this._isBannerVisible = false;
      this.bannerHideCallbacks.forEach((cb) => cb());
    });
  }

  private async initialize(): Promise<void> {
    try {
      await this.manager.init();
      this._consent = this.manager.getConsent();
      this._isInitialized = true;
      this._isBannerVisible = this.manager.isBannerVisible();
    } catch (error) {
      console.error('Failed to initialize ConsentManager:', error);
    } finally {
      this._isLoading = false;
    }
  }
}
