import { describe, it, expect, vi } from 'vitest';
import { render, screen, waitFor, fireEvent } from '@testing-library/react';
import TaskTab from './TaskTab.jsx';

const mockGetAgentTasks = vi.fn();
vi.mock('../../../api', () => ({
  getAgentTasks: (...args) => mockGetAgentTasks(...args),
}));

describe('TaskTab response shape handling', () => {
  it('백엔드가 {tasks: [...]} 객체로 wrapping해서 응답해도 .map 깨지지 않음', async () => {
    mockGetAgentTasks.mockResolvedValueOnce({
      tasks: [
        { id: 't1', task_type: 'compose', status: 'succeeded', created_at: '2026-05-18T08:00:00Z' },
        { id: 't2', task_type: 'fetch_news', status: 'failed', created_at: '2026-05-18T08:05:00Z' },
      ],
    });
    render(<TaskTab agentId="music" refreshTrigger={0} />);
    await waitFor(() => expect(screen.getByText('compose')).toBeInTheDocument());
    expect(screen.getByText('fetch_news')).toBeInTheDocument();
  });

  it('백엔드가 bare array를 반환해도 동작 (backward compat)', async () => {
    mockGetAgentTasks.mockResolvedValueOnce([
      { id: 't9', task_type: 'compose', status: 'succeeded', created_at: '2026-05-18T08:00:00Z' },
    ]);
    render(<TaskTab agentId="music" refreshTrigger={0} />);
    await waitFor(() => expect(screen.getByText('compose')).toBeInTheDocument());
  });

  it('응답이 falsy/empty이면 No tasks yet 표시', async () => {
    mockGetAgentTasks.mockResolvedValueOnce({ tasks: [] });
    render(<TaskTab agentId="music" refreshTrigger={0} />);
    await waitFor(() => expect(screen.getByText('No tasks yet')).toBeInTheDocument());
  });

  it('task 클릭 → result_data가 객체일 때도 stringify되어 안전하게 렌더', async () => {
    mockGetAgentTasks.mockResolvedValueOnce({
      tasks: [{
        id: 't_compose',
        task_type: 'compose',
        status: 'succeeded',
        created_at: '2026-05-18T08:00:00Z',
        result_data: { music_task_id: 'abc-123', tracks: [] },
      }],
    });
    render(<TaskTab agentId="music" refreshTrigger={0} />);
    const row = await screen.findByText('compose');
    fireEvent.click(row.closest('.ao-task-item'));
    const pre = await screen.findByText(/music_task_id/);
    expect(pre.textContent).toContain('"music_task_id": "abc-123"');
    expect(pre.textContent).toContain('"tracks": []');
  });

  it('task 클릭 → result_data가 JSON 문자열일 때 parse 후 pretty 렌더', async () => {
    mockGetAgentTasks.mockResolvedValueOnce({
      tasks: [{
        id: 't_str',
        task_type: 'compose',
        status: 'succeeded',
        created_at: '2026-05-18T08:00:00Z',
        result_data: '{"foo":"bar"}',
      }],
    });
    render(<TaskTab agentId="music" refreshTrigger={0} />);
    const row = await screen.findByText('compose');
    fireEvent.click(row.closest('.ao-task-item'));
    const pre = await screen.findByText(/foo/);
    expect(pre.textContent).toContain('"foo": "bar"');
  });

  it('task 클릭 → result_data가 plain string이면 그대로 표시 (parse 실패 fallback)', async () => {
    mockGetAgentTasks.mockResolvedValueOnce({
      tasks: [{
        id: 't_plain',
        task_type: 'fetch_news',
        status: 'succeeded',
        created_at: '2026-05-18T08:00:00Z',
        result_data: 'Just a log line',
      }],
    });
    render(<TaskTab agentId="music" refreshTrigger={0} />);
    const row = await screen.findByText('fetch_news');
    fireEvent.click(row.closest('.ao-task-item'));
    expect(await screen.findByText('Just a log line')).toBeInTheDocument();
  });
});
