import { DOCUMENT } from '@angular/common';
import { Injector, runInInjectionContext } from '@angular/core';
import { ElectronBridgeService } from '../../../core/platform/electron/electron-bridge.service';
import { ViewportService } from '../../../core/platform/viewport.service';
import { CustomEmojiService } from '../../../domains/custom-emoji';
import { NativeContextMenuComponent } from './native-context-menu.component';

function createDomTarget(action: 'add' | 'remove', emojiId: string): Element {
  const host = {
    getAttribute: vi.fn((name: string) => name === 'data-custom-emoji-id' ? emojiId : null)
  } as unknown as Element;

  return {
    closest: vi.fn((selector: string) => {
      if (action === 'remove' && selector.includes('data-custom-emoji-library')) {
        return host;
      }

      if (action === 'add' && selector.includes('data-custom-emoji') && !selector.includes('library')) {
        return host;
      }

      return null;
    })
  } as unknown as Element;
}

describe('NativeContextMenuComponent', () => {
  function createComponent(options?: {
    findEmoji?: unknown;
    isEmojiInLibrary?: boolean;
  }): NativeContextMenuComponent {
    const injector = Injector.create({
      providers: [
        NativeContextMenuComponent,
        {
          provide: DOCUMENT,
          useValue: {
            getSelection: () => null,
            createRange: () => ({
              selectNodeContents: vi.fn(),
              collapse: vi.fn(),
              cloneRange: () => ({})
            }),
            body: null
          }
        },
        {
          provide: ViewportService,
          useValue: {
            isMobile: () => false
          }
        },
        {
          provide: ElectronBridgeService,
          useValue: {
            isAvailable: false,
            getApi: () => null
          }
        },
        {
          provide: CustomEmojiService,
          useValue: {
            findEmoji: vi.fn(() => options?.findEmoji ?? { id: 'party-id' }),
            isEmojiInLibrary: vi.fn(() => options?.isEmojiInLibrary ?? false),
            saveEmojiToLibrary: vi.fn(async () => undefined),
            removeEmojiFromLibrary: vi.fn(async () => undefined)
          }
        }
      ]
    });

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

  it('opens the add-to-library menu for marked chat emoji targets', () => {
    const component = createComponent();
    const target = createDomTarget('add', 'party-id');

    component.onDocumentContextMenu({
      target,
      preventDefault: vi.fn(),
      stopPropagation: vi.fn(),
      clientX: 12,
      clientY: 34
    } as unknown as MouseEvent);

    expect(component.customEmojiMenu()).toEqual({
      action: 'add',
      emojiId: 'party-id',
      posX: 12,
      posY: 34
    });

    expect(component.params()).toBeNull();
  });

  it('opens the remove-from-library menu for marked picker emoji targets', () => {
    const component = createComponent({ isEmojiInLibrary: true });
    const target = createDomTarget('remove', 'wave-id');

    component.onDocumentContextMenu({
      target,
      preventDefault: vi.fn(),
      stopPropagation: vi.fn(),
      clientX: 8,
      clientY: 16
    } as unknown as MouseEvent);

    expect(component.customEmojiMenu()).toEqual({
      action: 'remove',
      emojiId: 'wave-id',
      posX: 8,
      posY: 16
    });
  });

  it('does not open a custom emoji menu when the emoji is already in the library', () => {
    const component = createComponent({ isEmojiInLibrary: true });
    const target = createDomTarget('add', 'party-id');

    component.onDocumentContextMenu({
      target,
      preventDefault: vi.fn(),
      stopPropagation: vi.fn(),
      clientX: 8,
      clientY: 16
    } as unknown as MouseEvent);

    expect(component.customEmojiMenu()).toBeNull();
  });
});
