/**
 * Tests pour usePlaylistKeyboardShortcuts
 * T0507: Create Playlist Keyboard Shortcuts
 */

import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
import { renderHook } from '@testing-library/react';
import { usePlaylistKeyboardShortcuts } from './usePlaylistKeyboardShortcuts';

describe('usePlaylistKeyboardShortcuts', () => {
  const mockCallbacks = {
    onPlayPause: vi.fn(),
    onNext: vi.fn(),
    onPrevious: vi.fn(),
    onAddTrack: vi.fn(),
    onDelete: vi.fn(),
  };

  beforeEach(() => {
    vi.clearAllMocks();
  });

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

  it('should add keydown event listener when enabled', () => {
    const addEventListenerSpy = vi.spyOn(window, 'addEventListener');
    const removeEventListenerSpy = vi.spyOn(window, 'removeEventListener');

    const { unmount } = renderHook(() =>
      usePlaylistKeyboardShortcuts({
        ...mockCallbacks,
        enabled: true,
      }),
    );

    expect(addEventListenerSpy).toHaveBeenCalledWith(
      'keydown',
      expect.any(Function),
    );

    unmount();

    expect(removeEventListenerSpy).toHaveBeenCalledWith(
      'keydown',
      expect.any(Function),
    );
  });

  it('should not add event listener when disabled', () => {
    const addEventListenerSpy = vi.spyOn(window, 'addEventListener');

    renderHook(() =>
      usePlaylistKeyboardShortcuts({
        ...mockCallbacks,
        enabled: false,
      }),
    );

    expect(addEventListenerSpy).not.toHaveBeenCalled();
  });

  it('should call onPlayPause when Space key is pressed', () => {
    renderHook(() =>
      usePlaylistKeyboardShortcuts({
        ...mockCallbacks,
        enabled: true,
      }),
    );

    const event = new KeyboardEvent('keydown', {
      code: 'Space',
      bubbles: true,
    });
    window.dispatchEvent(event);

    expect(mockCallbacks.onPlayPause).toHaveBeenCalledTimes(1);
  });

  it('should call onNext when ArrowRight key is pressed', () => {
    renderHook(() =>
      usePlaylistKeyboardShortcuts({
        ...mockCallbacks,
        enabled: true,
      }),
    );

    const event = new KeyboardEvent('keydown', {
      code: 'ArrowRight',
      bubbles: true,
    });
    window.dispatchEvent(event);

    expect(mockCallbacks.onNext).toHaveBeenCalledTimes(1);
  });

  it('should call onPrevious when ArrowLeft key is pressed', () => {
    renderHook(() =>
      usePlaylistKeyboardShortcuts({
        ...mockCallbacks,
        enabled: true,
      }),
    );

    const event = new KeyboardEvent('keydown', {
      code: 'ArrowLeft',
      bubbles: true,
    });
    window.dispatchEvent(event);

    expect(mockCallbacks.onPrevious).toHaveBeenCalledTimes(1);
  });

  it('should call onAddTrack when KeyA is pressed', () => {
    renderHook(() =>
      usePlaylistKeyboardShortcuts({
        ...mockCallbacks,
        enabled: true,
      }),
    );

    const event = new KeyboardEvent('keydown', {
      code: 'KeyA',
      bubbles: true,
    });
    window.dispatchEvent(event);

    expect(mockCallbacks.onAddTrack).toHaveBeenCalledTimes(1);
  });

  it('should call onDelete when Delete key is pressed', () => {
    renderHook(() =>
      usePlaylistKeyboardShortcuts({
        ...mockCallbacks,
        enabled: true,
      }),
    );

    const event = new KeyboardEvent('keydown', {
      code: 'Delete',
      bubbles: true,
    });
    window.dispatchEvent(event);

    expect(mockCallbacks.onDelete).toHaveBeenCalledTimes(1);
  });

  it('should call onDelete when Backspace key is pressed', () => {
    renderHook(() =>
      usePlaylistKeyboardShortcuts({
        ...mockCallbacks,
        enabled: true,
      }),
    );

    const event = new KeyboardEvent('keydown', {
      code: 'Backspace',
      bubbles: true,
    });
    window.dispatchEvent(event);

    expect(mockCallbacks.onDelete).toHaveBeenCalledTimes(1);
  });

  it('should not trigger shortcuts when typing in an input field', () => {
    renderHook(() =>
      usePlaylistKeyboardShortcuts({
        ...mockCallbacks,
        enabled: true,
      }),
    );

    const input = document.createElement('input');
    document.body.appendChild(input);
    input.focus();

    const event = new KeyboardEvent('keydown', {
      code: 'Space',
      bubbles: true,
      target: input,
    });
    window.dispatchEvent(event);

    expect(mockCallbacks.onPlayPause).not.toHaveBeenCalled();

    document.body.removeChild(input);
  });

  it('should not trigger shortcuts when typing in a textarea', () => {
    renderHook(() =>
      usePlaylistKeyboardShortcuts({
        ...mockCallbacks,
        enabled: true,
      }),
    );

    const textarea = document.createElement('textarea');
    document.body.appendChild(textarea);
    textarea.focus();

    const event = new KeyboardEvent('keydown', {
      code: 'Space',
      bubbles: true,
      target: textarea,
    });
    window.dispatchEvent(event);

    expect(mockCallbacks.onPlayPause).not.toHaveBeenCalled();

    document.body.removeChild(textarea);
  });

  it('should not trigger delete when typing in an input field', () => {
    renderHook(() =>
      usePlaylistKeyboardShortcuts({
        ...mockCallbacks,
        enabled: true,
      }),
    );

    const input = document.createElement('input');
    document.body.appendChild(input);
    input.focus();

    const event = new KeyboardEvent('keydown', {
      code: 'Delete',
      bubbles: true,
      target: input,
    });
    window.dispatchEvent(event);

    expect(mockCallbacks.onDelete).not.toHaveBeenCalled();

    document.body.removeChild(input);
  });

  it('should prevent default behavior when preventDefault is true', () => {
    renderHook(() =>
      usePlaylistKeyboardShortcuts({
        ...mockCallbacks,
        enabled: true,
        preventDefault: true,
      }),
    );

    const event = new KeyboardEvent('keydown', {
      code: 'Space',
      bubbles: true,
      cancelable: true,
    });
    const preventDefaultSpy = vi.spyOn(event, 'preventDefault');
    window.dispatchEvent(event);

    expect(preventDefaultSpy).toHaveBeenCalled();
  });

  it('should not prevent default behavior when preventDefault is false', () => {
    renderHook(() =>
      usePlaylistKeyboardShortcuts({
        ...mockCallbacks,
        enabled: true,
        preventDefault: false,
      }),
    );

    const event = new KeyboardEvent('keydown', {
      code: 'Space',
      bubbles: true,
      cancelable: true,
    });
    const preventDefaultSpy = vi.spyOn(event, 'preventDefault');
    window.dispatchEvent(event);

    expect(preventDefaultSpy).not.toHaveBeenCalled();
  });

  it('should work with containerRef', () => {
    const container = document.createElement('div');
    document.body.appendChild(container);
    const containerRef = { current: container };

    renderHook(() =>
      usePlaylistKeyboardShortcuts({
        ...mockCallbacks,
        enabled: true,
        containerRef,
      }),
    );

    // Event from outside container should not trigger
    const outsideEvent = new KeyboardEvent('keydown', {
      code: 'Space',
      bubbles: true,
    });
    window.dispatchEvent(outsideEvent);
    expect(mockCallbacks.onPlayPause).not.toHaveBeenCalled();

    // Event from inside container should trigger
    const insideElement = document.createElement('div');
    container.appendChild(insideElement);
    const insideEvent = new KeyboardEvent('keydown', {
      code: 'Space',
      bubbles: true,
      target: insideElement,
    });
    container.dispatchEvent(insideEvent);
    expect(mockCallbacks.onPlayPause).toHaveBeenCalledTimes(1);

    document.body.removeChild(container);
  });

  it('should not call callbacks if they are not provided', () => {
    renderHook(() =>
      usePlaylistKeyboardShortcuts({
        enabled: true,
      }),
    );

    const event = new KeyboardEvent('keydown', {
      code: 'Space',
      bubbles: true,
    });
    window.dispatchEvent(event);

    // Should not throw error
    expect(true).toBe(true);
  });
});
