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

import { ChatVideoPlayerComponent } from './chat-video-player.component';

function createComponent(): ChatVideoPlayerComponent {
  const injector = Injector.create({ providers: [ChatVideoPlayerComponent] });

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

function createVideoStub(initialPaused: boolean): HTMLVideoElement {
  const video = {
    paused: initialPaused,
    ended: false,
    play: vi.fn().mockImplementation(function play(this: { paused: boolean }) {
      this.paused = false;
      return Promise.resolve();
    }),
    pause: vi.fn().mockImplementation(function pause(this: { paused: boolean }) {
      this.paused = true;
    })
  };

  return video as unknown as HTMLVideoElement;
}

function attachVideo(component: ChatVideoPlayerComponent, video: HTMLVideoElement): void {
  component.videoRef = { nativeElement: video } as ElementRef<HTMLVideoElement>;
}

describe('ChatVideoPlayerComponent playback clicks', () => {
  beforeEach(() => {
    vi.useFakeTimers();
  });

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

  it('schedules stage playback toggle after a short delay', () => {
    const component = createComponent();
    const video = createVideoStub(true);

    attachVideo(component, video);

    component.onVideoClick();

    expect(video.play).not.toHaveBeenCalled();

    vi.advanceTimersByTime(300);
    expect(video.play).toHaveBeenCalledTimes(1);
  });

  it('control playback click stops propagation so stage toggle is not scheduled', () => {
    const component = createComponent();
    const video = createVideoStub(false);
    const stopPropagation = vi.fn();

    attachVideo(component, video);

    component.onControlPlaybackClick({ stopPropagation } as unknown as MouseEvent);

    expect(stopPropagation).toHaveBeenCalled();
    expect(video.pause).toHaveBeenCalledTimes(1);
  });

  it('pauses once when control playback is used without a bubbling stage click', () => {
    const component = createComponent();
    const video = createVideoStub(false);

    attachVideo(component, video);

    component.togglePlayback();

    vi.advanceTimersByTime(300);

    expect(video.pause).toHaveBeenCalledTimes(1);
    expect(video.play).not.toHaveBeenCalled();
  });

  it('double-toggles when control playback bubbles into the stage click handler', () => {
    const component = createComponent();
    const video = createVideoStub(false);

    attachVideo(component, video);

    component.togglePlayback();
    component.onVideoClick();

    vi.advanceTimersByTime(300);

    expect(video.pause).toHaveBeenCalledTimes(1);
    expect(video.play).toHaveBeenCalledTimes(1);
  });
});
