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

import type { CallNotificationActionIntent } from '../logic/call-notification.rules';
import { buildIncomingCallNotification, buildInCallNotification } from '../logic/call-notification.rules';
import { resolveMobileAdapter } from '../logic/mobile-capacitor-adapter.rules';
import type { MobileNotificationAdapter } from '../contracts/mobile.contracts';
import { WebMobileNotificationsAdapter } from '../adapters/web/web-mobile-notifications.adapter';
import { MobilePlatformService } from './mobile-platform.service';
import { MobilePushRegistrationService } from './mobile-push-registration.service';

/** Facade for push/local notifications with platform-specific adapters. */
@Injectable({ providedIn: 'root' })
export class MobileNotificationsService {
  private readonly mobilePlatform = inject(MobilePlatformService);
  private readonly pushRegistration = inject(MobilePushRegistrationService);
  private adapter: MobileNotificationAdapter = new WebMobileNotificationsAdapter();
  private adapterReady: Promise<MobileNotificationAdapter> | null = null;
  private callActionHandler: ((input: { callId: string; intent: CallNotificationActionIntent }) => void) | null = null;
  private initialized = false;

  async initialize(): Promise<void> {
    if (this.initialized) {
      return;
    }

    const adapter = await this.ensureAdapter();

    await adapter.initialize();
    this.pushRegistration.initialize();
    this.initialized = true;
  }

  async showIncomingCall(displayName: string, callId: string): Promise<void> {
    await this.initialize();
    const adapter = await this.ensureAdapter();

    await adapter.showCallNotification(buildIncomingCallNotification(displayName, callId));
  }

  async showActiveCall(input: { callId: string; displayName: string; isMuted: boolean }): Promise<void> {
    await this.initialize();
    const adapter = await this.ensureAdapter();

    await adapter.showCallNotification(buildInCallNotification(input));
  }

  async dismissIncomingCall(callId: string): Promise<void> {
    const adapter = await this.ensureAdapter();

    await adapter.dismissCallNotification(callId, 'incoming');
  }

  async dismissActiveCall(callId: string): Promise<void> {
    const adapter = await this.ensureAdapter();

    await adapter.dismissCallNotification(callId, 'active');
  }

  onCallAction(handler: (input: { callId: string; intent: CallNotificationActionIntent }) => void): void {
    this.callActionHandler = handler;
    this.adapter.onActionSelected(handler);
  }

  private ensureAdapter(): Promise<MobileNotificationAdapter> {
    if (!this.adapterReady) {
      this.adapterReady = resolveMobileAdapter(
        this.mobilePlatform.runtime(),
        this.adapter,
        async () => {
          const { CapacitorMobileNotificationsAdapter } = await import('../adapters/capacitor/capacitor-mobile-notifications.adapter');

          return new CapacitorMobileNotificationsAdapter();
        }
      ).then((adapter) => {
        this.adapter = adapter;

        if (this.callActionHandler) {
          this.adapter.onActionSelected(this.callActionHandler);
        }

        return adapter;
      });
    }

    return this.adapterReady;
  }
}
