import translationsEn from '../../../../../../public/i18n/en.json';
import type { CallNotificationActionIntent, CallNotificationPayload } from '../../logic/call-notification.rules';
import { resolveCallNotificationAction } from '../../logic/call-notification.rules';
import type { MobileNotificationAdapter } from '../../contracts/mobile.contracts';
import { loadCapacitorLocalNotificationsPlugin, loadCapacitorPushNotificationsPlugin } from './capacitor-plugin-loader';

const INCOMING_CALL_CHANNEL_ID = 'toju-incoming-call';
const ACTIVE_CALL_CHANNEL_ID = 'toju-active-call';

function mobileLabel(key: string): string {
  const value = key.split('.').reduce<unknown>((current, part) => {
    if (current && typeof current === 'object') {
      return (current as Record<string, unknown>)[part];
    }

    return undefined;
  }, translationsEn);

  return typeof value === 'string' ? value : key;
}

/** Capacitor local + push notification bridge with action buttons for in-call controls. */
export class CapacitorMobileNotificationsAdapter implements MobileNotificationAdapter {
  private actionHandler: ((input: { callId: string; intent: CallNotificationActionIntent }) => void) | null = null;
  private listenersRegistered = false;

  async initialize(): Promise<void> {
    const LocalNotifications = await loadCapacitorLocalNotificationsPlugin();
    const PushNotifications = await loadCapacitorPushNotificationsPlugin();

    if (!LocalNotifications) {
      return;
    }

    await LocalNotifications.createChannel({
      id: INCOMING_CALL_CHANNEL_ID,
      name: mobileLabel('mobile.notifications.incomingCallsChannel'),
      importance: 5,
      visibility: 1,
      sound: 'call.wav'
    });

    await LocalNotifications.createChannel({
      id: ACTIVE_CALL_CHANNEL_ID,
      name: mobileLabel('mobile.notifications.activeCallsChannel'),
      importance: 4,
      visibility: 1
    });

    await LocalNotifications.registerActionTypes({
      types: [
        {
          id: 'INCOMING_CALL_ACTIONS',
          actions: [{ id: 'answer', title: mobileLabel('mobile.notifications.answer') }, { id: 'hangup', title: mobileLabel('mobile.notifications.decline') }]
        },
        {
          id: 'ACTIVE_CALL_ACTIONS',
          actions: [{ id: 'mute', title: mobileLabel('mobile.notifications.mute') }, { id: 'hangup', title: mobileLabel('mobile.notifications.hangUp') }]
        }
      ]
    });

    if (!this.listenersRegistered) {
      await LocalNotifications.addListener('localNotificationActionPerformed', (event) => {
        const callId = event.notification.extra?.callId as string | undefined;
        const intent = resolveCallNotificationAction(event.actionId);

        if (!callId || !intent || !this.actionHandler) {
          return;
        }

        this.actionHandler({ callId, intent });
      });

      this.listenersRegistered = true;
    }

    if (PushNotifications) {
      const permission = await PushNotifications.checkPermissions();

      if (permission.receive === 'prompt') {
        await PushNotifications.requestPermissions();
      }
    }
  }

  async requestPermission(): Promise<boolean> {
    const LocalNotifications = await loadCapacitorLocalNotificationsPlugin();

    if (!LocalNotifications) {
      return false;
    }

    const permission = await LocalNotifications.checkPermissions();

    if (permission.display === 'granted') {
      return true;
    }

    const requested = await LocalNotifications.requestPermissions();

    return requested.display === 'granted';
  }

  async showCallNotification(payload: CallNotificationPayload): Promise<void> {
    const LocalNotifications = await loadCapacitorLocalNotificationsPlugin();

    if (!LocalNotifications) {
      return;
    }

    const granted = await this.requestPermission();

    if (!granted) {
      return;
    }

    await LocalNotifications.schedule({
      notifications: [
        {
          id: payload.id,
          title: payload.title,
          body: payload.body,
          channelId: payload.kind === 'incoming' ? INCOMING_CALL_CHANNEL_ID : ACTIVE_CALL_CHANNEL_ID,
          ongoing: payload.kind === 'active',
          autoCancel: payload.kind === 'incoming',
          extra: {
            callId: payload.callId,
            kind: payload.kind
          },
          actionTypeId: payload.kind === 'active' ? 'ACTIVE_CALL_ACTIONS' : 'INCOMING_CALL_ACTIONS'
        }
      ]
    });
  }

  async dismissCallNotification(callId: string, kind: CallNotificationPayload['kind']): Promise<void> {
    const LocalNotifications = await loadCapacitorLocalNotificationsPlugin();

    if (!LocalNotifications) {
      return;
    }

    const notifications = await LocalNotifications.getDeliveredNotifications();
    const matching = notifications.notifications.filter((notification) => {
      const extraCallId = notification.extra?.callId as string | undefined;
      const extraKind = notification.extra?.kind as CallNotificationPayload['kind'] | undefined;

      return extraCallId === callId && extraKind === kind;
    });

    if (matching.length === 0) {
      return;
    }

    await LocalNotifications.removeDeliveredNotifications({
      notifications: matching
    });
  }

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