import { renderHook } from '@testing-library/react';

import { ThemeProvider } from './ThemeProvider';
import { DEFAULT_BASE_THEME, DEFAULT_SCREEN_MODE } from './const';
import { useTheme } from './useTheme';

describe('useTheme', () => {
  it('returns default light theme', () => {
    jest.spyOn(console, 'warn').mockImplementation();

    const {
      result: { current },
    } = renderHook(() => useTheme());

    expect(current).toStrictEqual({
      theme: DEFAULT_BASE_THEME,
      screenMode: DEFAULT_SCREEN_MODE,
      isModern: false,
      isForestGreenTheme: false,
      isScreenModeDark: false,
      className: 'np-theme-light',
    });

    jest.clearAllMocks();
  });

  it('returns personal theme', () => {
    const {
      result: { current },
    } = renderHook(() => useTheme(), {
      wrapper: (props) => <ThemeProvider theme="personal" {...props} />,
    });

    expect(current).toStrictEqual({
      theme: 'personal',
      screenMode: DEFAULT_SCREEN_MODE,
      isModern: true,
      isForestGreenTheme: false,
      isScreenModeDark: false,
      className: 'np-theme-personal',
    });
  });

  it('returns forest-green theme', () => {
    const {
      result: { current },
    } = renderHook(() => useTheme(), {
      wrapper: (props) => <ThemeProvider theme="forest-green" {...props} />,
    });

    expect(current).toStrictEqual({
      theme: 'forest-green',
      screenMode: DEFAULT_SCREEN_MODE,
      isModern: true,
      isForestGreenTheme: true,
      isScreenModeDark: false,
      className: 'np-theme-personal np-theme-personal--forest-green',
    });
  });

  it('returns bright-green theme', () => {
    const {
      result: { current },
    } = renderHook(() => useTheme(), {
      wrapper: (props) => <ThemeProvider theme="bright-green" {...props} />,
    });

    expect(current).toStrictEqual({
      theme: 'bright-green',
      screenMode: DEFAULT_SCREEN_MODE,
      isModern: true,
      isForestGreenTheme: false,
      isScreenModeDark: false,
      className: 'np-theme-personal np-theme-personal--bright-green',
    });
  });

  it('returns default screen mode if used default light theme', () => {
    const {
      result: { current },
    } = renderHook(() => useTheme(), {
      wrapper: (props) => <ThemeProvider theme={DEFAULT_BASE_THEME} screenMode="dark" {...props} />,
    });

    expect(current).toStrictEqual({
      theme: DEFAULT_BASE_THEME,
      screenMode: DEFAULT_SCREEN_MODE,
      isModern: false,
      isForestGreenTheme: false,
      isScreenModeDark: false,
      className: 'np-theme-light',
    });
  });

  it('returns dark screen mode', () => {
    const {
      result: { current },
    } = renderHook(() => useTheme(), {
      wrapper: (props) => <ThemeProvider theme="personal" screenMode="dark" {...props} />,
    });

    expect(current).toStrictEqual({
      theme: 'personal',
      screenMode: 'dark',
      isModern: true,
      isForestGreenTheme: false,
      isScreenModeDark: true,
      className: 'np-theme-personal np-theme-personal--dark',
    });
  });

  it('warns when used outside a theme provider on staging or localhost', () => {
    jest.spyOn(console, 'warn').mockImplementation();

    Object.defineProperty(window, 'location', {
      value: {
        hostname: 'wise.com',
      },
      writable: true,
    });

    const {
      result: { current: productionValue },
    } = renderHook(() => useTheme());

    expect(productionValue).toStrictEqual({
      theme: DEFAULT_BASE_THEME,
      screenMode: DEFAULT_SCREEN_MODE,
      isModern: false,
      isForestGreenTheme: false,
      isScreenModeDark: false,
      className: 'np-theme-light',
    });

    // eslint-disable-next-line no-console
    expect(console.warn).not.toHaveBeenCalled();

    Object.defineProperty(window, 'location', {
      value: {
        hostname: 'dev-wi.se',
      },
      writable: true,
    });

    const {
      result: { current: stagingValue },
    } = renderHook(() => useTheme());

    expect(stagingValue).toStrictEqual({
      theme: DEFAULT_BASE_THEME,
      screenMode: DEFAULT_SCREEN_MODE,
      isModern: false,
      isForestGreenTheme: false,
      isScreenModeDark: false,
      className: 'np-theme-light',
    });

    // eslint-disable-next-line no-console
    expect(console.warn).toHaveBeenCalledTimes(1);

    Object.defineProperty(window, 'location', {
      value: {
        hostname: 'localhost',
      },
      writable: true,
    });

    const {
      result: { current: localhostValue },
    } = renderHook(() => useTheme());

    expect(localhostValue).toStrictEqual({
      theme: DEFAULT_BASE_THEME,
      screenMode: DEFAULT_SCREEN_MODE,
      isModern: false,
      isForestGreenTheme: false,
      isScreenModeDark: false,
      className: 'np-theme-light',
    });

    // eslint-disable-next-line no-console
    expect(console.warn).toHaveBeenCalledTimes(2);

    Object.defineProperty(window, 'location', {
      value: undefined,
      writable: true,
    });

    const {
      result: { current: noHostnameValue },
    } = renderHook(() => useTheme());

    expect(noHostnameValue).toStrictEqual({
      theme: DEFAULT_BASE_THEME,
      screenMode: DEFAULT_SCREEN_MODE,
      isModern: false,
      isForestGreenTheme: false,
      isScreenModeDark: false,
      className: 'np-theme-light',
    });

    // eslint-disable-next-line no-console
    expect(console.warn).toHaveBeenCalledTimes(2);

    jest.clearAllMocks();
  });
});
