import '@angular/compiler';
import {
  afterEach,
  beforeEach,
  describe,
  expect,
  it,
  vi
} from 'vitest';
import { Injector, runInInjectionContext } from '@angular/core';

const pushState = vi.hoisted(() => ({
  register: vi.fn(() => Promise.resolve()),
  checkPermissions: vi.fn(() => Promise.resolve({ receive: 'granted' })),
  requestPermissions: vi.fn(() => Promise.resolve({ receive: 'granted' })),
  addListener: vi.fn(() => Promise.resolve({ remove: vi.fn() }))
}));
const deviceState = vi.hoisted(() => ({
  getInfo: vi.fn(() => Promise.resolve({ platform: 'android' }))
}));
const mobilePlatformState = vi.hoisted(() => ({
  isCapacitor: true
}));
const remotePushState = vi.hoisted(() => ({
  configured: true
}));

vi.mock('../adapters/capacitor/capacitor-plugin-loader', () => ({
  loadCapacitorPushNotificationsPlugin: vi.fn(() => Promise.resolve(pushState)),
  loadCapacitorDevicePlugin: vi.fn(() => Promise.resolve(deviceState))
}));

vi.mock('../adapters/capacitor/metoyou-mobile.plugin', () => ({
  loadMetoyouMobilePlugin: vi.fn(() => Promise.resolve({
    isRemotePushConfigured: vi.fn(() => Promise.resolve({ configured: remotePushState.configured }))
  }))
}));

import { loadMetoyouMobilePlugin } from '../adapters/capacitor/metoyou-mobile.plugin';
import { MobilePlatformService } from './mobile-platform.service';
import { MobilePushRegistrationService } from './mobile-push-registration.service';

function createService(): MobilePushRegistrationService {
  const injector = Injector.create({
    providers: [
      MobilePushRegistrationService,
      {
        provide: MobilePlatformService,
        useValue: {
          isCapacitor: () => mobilePlatformState.isCapacitor
        }
      }
    ]
  });

  return runInInjectionContext(injector, () => injector.get(MobilePushRegistrationService));
}

describe('MobilePushRegistrationService', () => {
  beforeEach(() => {
    vi.spyOn(console, 'warn').mockImplementation(() => {});
    mobilePlatformState.isCapacitor = true;
    remotePushState.configured = true;
    pushState.register.mockClear();
    pushState.addListener.mockClear();
    vi.mocked(loadMetoyouMobilePlugin).mockClear();
  });

  afterEach(() => {
    vi.restoreAllMocks();
  });

  it('skips PushNotifications.register when remote push is unavailable', async () => {
    remotePushState.configured = false;

    const service = createService();

    service.initialize();

    await vi.waitFor(() => {
      expect(console.warn).toHaveBeenCalledWith(
        expect.stringContaining('google-services.json')
      );
    });

    expect(pushState.register).not.toHaveBeenCalled();
  });

  it('registers for remote push when Firebase/APNs is configured', async () => {
    const service = createService();

    service.initialize();

    await vi.waitFor(() => {
      expect(pushState.register).toHaveBeenCalledTimes(1);
    });

    expect(loadMetoyouMobilePlugin).toHaveBeenCalled();
  });

  it('does not wire listeners on non-capacitor shells', () => {
    mobilePlatformState.isCapacitor = false;

    const service = createService();

    service.initialize();

    expect(pushState.register).not.toHaveBeenCalled();
    expect(loadMetoyouMobilePlugin).not.toHaveBeenCalled();
  });
});
