/**
 * Angular Integration fuer @breakpilot/consent-sdk
 *
 * @example
 * ```typescript
 * // app.module.ts
 * import { ConsentModule } from '@breakpilot/consent-sdk/angular';
 *
 * @NgModule({
 *   imports: [
 *     ConsentModule.forRoot({
 *       apiEndpoint: 'https://consent.example.com/api/v1',
 *       siteId: 'site_abc123',
 *     }),
 *   ],
 * })
 * export class AppModule {}
 * ```
 */

// =============================================================================
// NOTE: Angular SDK Structure
// =============================================================================
//
// Angular hat ein komplexeres Build-System (ngc, ng-packagr).
// Diese Datei definiert die Schnittstelle - fuer Production muss ein
// separates Angular Library Package erstellt werden:
//
//   ng generate library @breakpilot/consent-sdk-angular
//
// Die folgende Implementation ist fuer direkten Import vorgesehen.
// =============================================================================

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

// =============================================================================
// Angular Service Interface
// =============================================================================

/**
 * ConsentService Interface fuer Angular DI
 *
 * @example
 * ```typescript
 * @Component({...})
 * export class MyComponent {
 *   constructor(private consent: ConsentService) {
 *     if (this.consent.hasConsent('analytics')) {
 *       // Analytics laden
 *     }
 *   }
 * }
 * ```
 */
export interface IConsentService {
  /** Initialisiert? */
  readonly isInitialized: boolean;

  /** Laedt noch? */
  readonly isLoading: boolean;

  /** Banner sichtbar? */
  readonly isBannerVisible: boolean;

  /** Aktueller Consent-Zustand */
  readonly consent: ConsentState | null;

  /** Muss Consent eingeholt werden? */
  readonly needsConsent: boolean;

  /** Prueft Consent fuer Kategorie */
  hasConsent(category: ConsentCategory): boolean;

  /** Alle akzeptieren */
  acceptAll(): Promise<void>;

  /** Alle ablehnen */
  rejectAll(): Promise<void>;

  /** Auswahl speichern */
  saveSelection(categories: Partial<ConsentCategories>): Promise<void>;

  /** Banner anzeigen */
  showBanner(): void;

  /** Banner ausblenden */
  hideBanner(): void;

  /** Einstellungen oeffnen */
  showSettings(): void;
}

// =============================================================================
// ConsentService Implementation
// =============================================================================

/**
 * 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;
    }
  }
}

// =============================================================================
// Angular Module Configuration
// =============================================================================

/**
 * Konfiguration fuer ConsentModule.forRoot()
 */
export interface ConsentModuleConfig extends ConsentConfig {}

/**
 * Token fuer Dependency Injection
 * Verwendung mit Angular @Inject():
 *
 * @example
 * ```typescript
 * constructor(@Inject(CONSENT_CONFIG) private config: ConsentConfig) {}
 * ```
 */
export const CONSENT_CONFIG = 'CONSENT_CONFIG';
export const CONSENT_SERVICE = 'CONSENT_SERVICE';

// =============================================================================
// Factory Functions fuer Angular DI
// =============================================================================

/**
 * Factory fuer ConsentService
 *
 * @example
 * ```typescript
 * // app.module.ts
 * providers: [
 *   { provide: CONSENT_CONFIG, useValue: { apiEndpoint: '...', siteId: '...' } },
 *   { provide: CONSENT_SERVICE, useFactory: consentServiceFactory, deps: [CONSENT_CONFIG] },
 * ]
 * ```
 */
export function consentServiceFactory(config: ConsentConfig): ConsentServiceBase {
  return new ConsentServiceBase(config);
}

// =============================================================================
// Angular Module Definition (Template)
// =============================================================================

/**
 * ConsentModule - Angular Module
 *
 * Dies ist eine Template-Definition. Fuer echte Angular-Nutzung
 * muss ein separates Angular Library Package erstellt werden.
 *
 * @example
 * ```typescript
 * // In einem Angular Library Package:
 * @NgModule({
 *   declarations: [ConsentBannerComponent, ConsentGateDirective],
 *   exports: [ConsentBannerComponent, ConsentGateDirective],
 * })
 * export class ConsentModule {
 *   static forRoot(config: ConsentModuleConfig): ModuleWithProviders<ConsentModule> {
 *     return {
 *       ngModule: ConsentModule,
 *       providers: [
 *         { provide: CONSENT_CONFIG, useValue: config },
 *         { provide: CONSENT_SERVICE, useFactory: consentServiceFactory, deps: [CONSENT_CONFIG] },
 *       ],
 *     };
 *   }
 * }
 * ```
 */
export const ConsentModuleDefinition = {
  /**
   * Providers fuer Root-Module
   */
  forRoot: (config: ConsentModuleConfig) => ({
    provide: CONSENT_CONFIG,
    useValue: config,
  }),
};

// =============================================================================
// Component Templates (fuer Angular Library)
// =============================================================================

/**
 * ConsentBannerComponent Template
 *
 * Fuer Angular Library Implementation:
 *
 * @example
 * ```typescript
 * @Component({
 *   selector: 'bp-consent-banner',
 *   template: CONSENT_BANNER_TEMPLATE,
 *   styles: [CONSENT_BANNER_STYLES],
 * })
 * export class ConsentBannerComponent {
 *   constructor(public consent: ConsentService) {}
 * }
 * ```
 */
export const CONSENT_BANNER_TEMPLATE = `
<div
  *ngIf="consent.isBannerVisible"
  class="bp-consent-banner"
  role="dialog"
  aria-modal="true"
  aria-label="Cookie-Einstellungen"
>
  <div class="bp-consent-banner-content">
    <h2>Datenschutzeinstellungen</h2>
    <p>
      Wir nutzen Cookies und ähnliche Technologien, um Ihnen ein optimales
      Nutzererlebnis zu bieten.
    </p>
    <div class="bp-consent-banner-actions">
      <button
        type="button"
        class="bp-consent-btn bp-consent-btn-reject"
        (click)="consent.rejectAll()"
      >
        Alle ablehnen
      </button>
      <button
        type="button"
        class="bp-consent-btn bp-consent-btn-settings"
        (click)="consent.showSettings()"
      >
        Einstellungen
      </button>
      <button
        type="button"
        class="bp-consent-btn bp-consent-btn-accept"
        (click)="consent.acceptAll()"
      >
        Alle akzeptieren
      </button>
    </div>
  </div>
</div>
`;

/**
 * ConsentGateDirective Template
 *
 * @example
 * ```typescript
 * @Directive({
 *   selector: '[bpConsentGate]',
 * })
 * export class ConsentGateDirective implements OnInit, OnDestroy {
 *   @Input('bpConsentGate') category!: ConsentCategory;
 *
 *   private unsubscribe?: () => void;
 *
 *   constructor(
 *     private templateRef: TemplateRef<any>,
 *     private viewContainer: ViewContainerRef,
 *     private consent: ConsentService
 *   ) {}
 *
 *   ngOnInit() {
 *     this.updateView();
 *     this.unsubscribe = this.consent.onConsentChange(() => this.updateView());
 *   }
 *
 *   ngOnDestroy() {
 *     this.unsubscribe?.();
 *   }
 *
 *   private updateView() {
 *     if (this.consent.hasConsent(this.category)) {
 *       this.viewContainer.createEmbeddedView(this.templateRef);
 *     } else {
 *       this.viewContainer.clear();
 *     }
 *   }
 * }
 * ```
 */
export const CONSENT_GATE_USAGE = `
<!-- Verwendung in Templates -->
<div *bpConsentGate="'analytics'">
  <analytics-component></analytics-component>
</div>

<!-- Mit else Template -->
<ng-container *bpConsentGate="'marketing'; else placeholder">
  <marketing-component></marketing-component>
</ng-container>
<ng-template #placeholder>
  <p>Bitte akzeptieren Sie Marketing-Cookies.</p>
</ng-template>
`;

// =============================================================================
// RxJS Observable Wrapper (Optional)
// =============================================================================

/**
 * RxJS Observable Wrapper fuer ConsentService
 *
 * Fuer Projekte die RxJS bevorzugen:
 *
 * @example
 * ```typescript
 * import { BehaviorSubject, Observable } from 'rxjs';
 *
 * export class ConsentServiceRx extends ConsentServiceBase {
 *   private consentSubject = new BehaviorSubject<ConsentState | null>(null);
 *   private bannerVisibleSubject = new BehaviorSubject<boolean>(false);
 *
 *   consent$ = this.consentSubject.asObservable();
 *   isBannerVisible$ = this.bannerVisibleSubject.asObservable();
 *
 *   constructor(config: ConsentConfig) {
 *     super(config);
 *     this.onConsentChange((c) => this.consentSubject.next(c));
 *     this.onBannerShow(() => this.bannerVisibleSubject.next(true));
 *     this.onBannerHide(() => this.bannerVisibleSubject.next(false));
 *   }
 * }
 * ```
 */

// =============================================================================
// Exports
// =============================================================================

export type { ConsentConfig, ConsentState, ConsentCategory, ConsentCategories };
