import { cleanup, fireEvent, render, screen, waitFor } from '@testing-library/react';
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
import { BlockPlayoutTroubleshootingScreen } from './BlockPlayoutTroubleshootingScreen';

function jsonResponse(body: unknown, status = 200): Response {
  return new Response(JSON.stringify(body), { headers: { 'Content-Type': 'application/json' }, status });
}

const playoutsPage = {
  totalCount: 2,
  page: [
    { id: 5, channelNumber: '1', channelName: 'Cartoons', scheduleKind: 'Block', scheduleName: '', dailyRebuildTime: null, buildStatus: null },
    { id: 6, channelNumber: '2', channelName: 'Movies', scheduleKind: 'Classic', scheduleName: '', dailyRebuildTime: null, buildStatus: null }
  ]
};

const blocks = [
  { id: 10, groupId: 1, groupName: 'Morning', name: 'Toons', minutes: 60, stopScheduling: 'AfterDurationEnd' },
  { id: -1, groupId: 1, groupName: 'Morning', name: '(none)', minutes: 0, stopScheduling: 'AfterDurationEnd' }
];

const historyPage = {
  totalCount: 1,
  page: [{ id: 99, when: '2026-07-07T00:00:00Z', finish: '2026-07-07T01:00:00Z', key: '{"BlockId":10}', details: '{"MediaItemId":3}' }]
};

const details = {
  playbackOrder: 'Shuffle',
  collectionType: 'Collection',
  name: 'Cartoons Collection',
  mediaItemType: 'Episode',
  mediaItemTitle: 'S1E1 - Pilot'
};

function mockApi() {
  return vi.spyOn(window, 'fetch').mockImplementation((input: RequestInfo | URL, init?: RequestInit) => {
    const url = input.toString();
    const method = (init?.method ?? 'GET').toUpperCase();

    if (url === '/api/v1/playouts' && method === 'GET') {
      return Promise.resolve(jsonResponse(playoutsPage));
    }
    if (url === '/api/v1/playouts/5/blocks' && method === 'GET') {
      return Promise.resolve(jsonResponse(blocks));
    }
    if (url.startsWith('/api/v1/playouts/5/blocks/10/history') && method === 'GET') {
      return Promise.resolve(jsonResponse(historyPage));
    }
    if (url === '/api/v1/playouts/history/99' && method === 'GET') {
      return Promise.resolve(jsonResponse(details));
    }

    return Promise.resolve(new Response(null, { status: 204 }));
  });
}

describe('BlockPlayoutTroubleshootingScreen', () => {
  beforeEach(() => {
    window.localStorage.clear();
    vi.restoreAllMocks();
  });

  afterEach(() => {
    cleanup();
  });

  it('only lists Block playouts in the selector', async () => {
    mockApi();
    render(<BlockPlayoutTroubleshootingScreen />);

    await waitFor(() => expect(screen.getByRole('option', { name: '1 - Cartoons' })).toBeTruthy());
    expect(screen.queryByRole('option', { name: '2 - Movies' })).toBeNull();
  });

  it('drills from playout to block to history to decoded details', async () => {
    mockApi();
    render(<BlockPlayoutTroubleshootingScreen />);

    await screen.findByRole('option', { name: '1 - Cartoons' });
    fireEvent.change(screen.getByRole('combobox'), { target: { value: '5' } });

    expect(await screen.findByText('Toons')).toBeTruthy();
    fireEvent.click(screen.getByRole('button', { name: 'History' }));

    expect(await screen.findByText('{"BlockId":10}')).toBeTruthy();
    fireEvent.click(screen.getByText('{"BlockId":10}'));

    expect(await screen.findByText('Cartoons Collection')).toBeTruthy();
    expect(screen.getByText('S1E1 - Pilot')).toBeTruthy();
  });

  it('hides the History action for a block with a negative (unpersisted) id', async () => {
    mockApi();
    render(<BlockPlayoutTroubleshootingScreen />);

    await screen.findByRole('option', { name: '1 - Cartoons' });
    fireEvent.change(screen.getByRole('combobox'), { target: { value: '5' } });

    await screen.findByText('Toons');
    expect(await screen.findByText('(none)')).toBeTruthy();

    // Only the persisted block (id 10) gets a History button.
    expect(screen.getAllByRole('button', { name: 'History' })).toHaveLength(1);
  });

  it('restores the page size from localStorage on mount and persists a change', async () => {
    window.localStorage.setItem('ctv-block-history-page-size', '50');
    mockApi();
    render(<BlockPlayoutTroubleshootingScreen />);

    await screen.findByRole('option', { name: '1 - Cartoons' });
    fireEvent.change(screen.getByRole('combobox'), { target: { value: '5' } });
    await screen.findByText('Toons');
    fireEvent.click(screen.getByRole('button', { name: 'History' }));

    await screen.findByText('{"BlockId":10}');
    const pageSizeSelect = screen.getAllByRole('combobox')[1] as HTMLSelectElement;
    expect(pageSizeSelect.value).toBe('50');

    fireEvent.change(pageSizeSelect, { target: { value: '25' } });
    expect(window.localStorage.getItem('ctv-block-history-page-size')).toBe('25');
  });
});
