import { cleanup, render, screen, waitFor } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import { afterEach, describe, expect, it, vi } from 'vitest';
import { JobPanel } from '../../../src/components/JobPanel';
import type { ExportResult } from '../../../src/export';

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

describe('JobPanel result selection', () => {
  it('downloads only the selected generated results as ZIP', async () => {
    const user = userEvent.setup();
    const onSaveZip = vi.fn();
    const first = result('one', 'one.png');
    const second = result('two', 'two.png');

    render(
      <JobPanel
        engineState={{
          status: 'ready',
          mode: 'single-thread',
          capabilities: {
            versionText: 'test',
            buildConfiguration: [],
            demuxers: new Set(),
            muxers: new Set(),
            decoders: new Set(),
            encoders: new Set(),
            filters: new Set(),
          },
        }}
        jobs={[]}
        results={[first, second]}
        verifications={{}}
        logs={[]}
        onCancel={vi.fn()}
        onCancelJob={vi.fn()}
        onRetryJob={vi.fn()}
        onClearJobHistory={vi.fn()}
        onSave={vi.fn()}
        onSaveZip={onSaveZip}
        onSaveReport={vi.fn()}
        onPreview={vi.fn()}
        onRemove={vi.fn()}
        onClearResults={vi.fn()}
      />
    );

    await waitFor(() =>
      expect(
        screen.getByRole('button', {
          name: 'Download selected as ZIP (2)',
        })
      ).toBeEnabled()
    );
    await user.click(
      screen.getByRole('checkbox', { name: 'Select two.png for ZIP' })
    );
    await user.click(
      screen.getByRole('button', { name: 'Download selected as ZIP (1)' })
    );
    expect(onSaveZip).toHaveBeenCalledWith([first]);
  });

  it('marks browser-rejected media as download-only and does not offer Preview', () => {
    vi.spyOn(HTMLMediaElement.prototype, 'canPlayType').mockReturnValue('');
    const output = mediaResult('audio', 'archive.flac', 'audio/flac');

    render(
      <JobPanel
        engineState={{
          status: 'ready',
          mode: 'single-thread',
          capabilities: {
            versionText: 'test',
            buildConfiguration: [],
            demuxers: new Set(),
            muxers: new Set(),
            decoders: new Set(),
            encoders: new Set(),
            filters: new Set(),
          },
        }}
        jobs={[]}
        results={[output]}
        verifications={{}}
        logs={[]}
        onCancel={vi.fn()}
        onCancelJob={vi.fn()}
        onRetryJob={vi.fn()}
        onClearJobHistory={vi.fn()}
        onSave={vi.fn()}
        onSaveZip={vi.fn()}
        onSaveReport={vi.fn()}
        onPreview={vi.fn()}
        onRemove={vi.fn()}
        onClearResults={vi.fn()}
      />
    );

    expect(screen.queryByRole('button', { name: 'Preview' })).toBeNull();
    expect(
      screen.getByText(/Download only: The browser reports no native/iu)
    ).toBeVisible();
    expect(screen.getByRole('button', { name: 'Save result' })).toBeEnabled();
  });

  it('shows the exact split interval and per-result verification state', () => {
    const output = {
      ...mediaResult('segment', 'clip-001.mp4', 'video/mp4'),
      timeRange: { startSeconds: 1.25, endSeconds: 3.5 },
    };

    render(
      <JobPanel
        engineState={{
          status: 'ready',
          mode: 'single-thread',
          capabilities: {
            versionText: 'test',
            buildConfiguration: [],
            demuxers: new Set(),
            muxers: new Set(),
            decoders: new Set(),
            encoders: new Set(),
            filters: new Set(),
          },
        }}
        jobs={[]}
        results={[output]}
        verifications={{
          segment: {
            warning: 'Output was created, but its verification probe failed.',
          },
        }}
        logs={[]}
        onCancel={vi.fn()}
        onCancelJob={vi.fn()}
        onRetryJob={vi.fn()}
        onClearJobHistory={vi.fn()}
        onSave={vi.fn()}
        onSaveZip={vi.fn()}
        onSaveReport={vi.fn()}
        onPreview={vi.fn()}
        onRemove={vi.fn()}
        onClearResults={vi.fn()}
      />
    );

    expect(
      screen.getByText(
        'Segment range 00:00:01.250–00:00:03.500 · 00:00:02.250 duration'
      )
    ).toBeVisible();
    expect(screen.getByText(/created · verification warning/iu)).toBeVisible();
    expect(
      screen.getByText('Output was created, but its verification probe failed.')
    ).toBeVisible();
  });
});

function result(id: string, fileName: string): ExportResult {
  const blob = new Blob([id], { type: 'image/png' });
  return {
    id,
    planId: `plan-${id}`,
    outputId: `output-${id}`,
    fileName,
    blob,
    mimeType: blob.type,
    role: 'thumbnail',
    size: blob.size,
    createdAt: '2026-01-01T00:00:00.000Z',
  };
}

function mediaResult(
  id: string,
  fileName: string,
  mimeType: string
): ExportResult {
  const blob = new Blob([id], { type: mimeType });
  return {
    id,
    planId: `plan-${id}`,
    outputId: `output-${id}`,
    fileName,
    blob,
    mimeType,
    role: 'media',
    size: blob.size,
    createdAt: '2026-01-01T00:00:00.000Z',
  };
}
