/**
 * Frontend hook tests for trading reports.
 *
 * Tests useReports and useReport hooks with MSW mocks.
 * Requirements validated: 5.4, 5.5
 */
import { renderHook, waitFor } from '@testing-library/react';
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
import { http, HttpResponse } from 'msw';
import { type ReactNode, createElement } from 'react';
import { describe, expect, it } from 'vitest';
import { useReports, useReport } from '../api/hooks';
import { server } from './mocks/server';

const mockReportList = [
  {
    id: 'rpt-1',
    report_type: 'daily',
    period_start: '2025-01-15',
    period_end: '2025-01-15',
    validation_status: 'passed',
    generated_at: '2025-01-15T21:30:00Z',
  },
  {
    id: 'rpt-2',
    report_type: 'weekly',
    period_start: '2025-01-13',
    period_end: '2025-01-17',
    validation_status: 'warnings',
    generated_at: '2025-01-18T10:00:00Z',
  },
];

const mockReportDetail = {
  id: 'rpt-1',
  report_type: 'daily',
  period_start: '2025-01-15',
  period_end: '2025-01-15',
  validation_status: 'passed',
  generated_at: '2025-01-15T21:30:00Z',
  created_at: '2025-01-15T21:30:05Z',
  report_data: {
    pnl: { realized_pnl: 125.5, unrealized_pnl: -30.2 },
    executive_summary: 'Test executive summary',
  },
};

function createWrapper() {
  const queryClient = new QueryClient({
    defaultOptions: {
      queries: { retry: false, gcTime: 0 },
    },
  });
  return function Wrapper({ children }: { children: ReactNode }) {
    return createElement(QueryClientProvider, { client: queryClient }, children);
  };
}

describe('useReports', () => {
  it('fetches report list with default params', async () => {
    server.use(
      http.get('/api/reports', () => HttpResponse.json(mockReportList)),
    );

    const { result } = renderHook(() => useReports(), {
      wrapper: createWrapper(),
    });

    await waitFor(() => expect(result.current.isSuccess).toBe(true));

    expect(result.current.data).toHaveLength(2);
    expect(result.current.data![0].id).toBe('rpt-1');
    expect(result.current.data![0].report_type).toBe('daily');
    expect(result.current.data![1].report_type).toBe('weekly');
  });

  it('passes query params for filtering', async () => {
    let capturedUrl = '';
    server.use(
      http.get('/api/reports', ({ request }) => {
        capturedUrl = request.url;
        return HttpResponse.json([mockReportList[0]]);
      }),
    );

    const { result } = renderHook(
      () => useReports({ report_type: 'daily', limit: 10 }),
      { wrapper: createWrapper() },
    );

    await waitFor(() => expect(result.current.isSuccess).toBe(true));

    expect(capturedUrl).toContain('report_type=daily');
    expect(capturedUrl).toContain('limit=10');
    expect(result.current.data).toHaveLength(1);
  });

  it('handles error state', async () => {
    server.use(
      http.get('/api/reports', () =>
        new HttpResponse(null, { status: 500 }),
      ),
    );

    const { result } = renderHook(() => useReports(), {
      wrapper: createWrapper(),
    });

    await waitFor(() => expect(result.current.isError).toBe(true));
  });
});

describe('useReport', () => {
  it('fetches single report by id', async () => {
    server.use(
      http.get('/api/reports/rpt-1', () =>
        HttpResponse.json(mockReportDetail),
      ),
    );

    const { result } = renderHook(() => useReport('rpt-1'), {
      wrapper: createWrapper(),
    });

    await waitFor(() => expect(result.current.isSuccess).toBe(true));

    expect(result.current.data!.id).toBe('rpt-1');
    expect(result.current.data!.report_data).toBeDefined();
    expect(result.current.data!.report_data.pnl).toBeDefined();
    expect(result.current.data!.created_at).toBe('2025-01-15T21:30:05Z');
  });

  it('does not fetch when id is undefined', async () => {
    const { result } = renderHook(() => useReport(undefined), {
      wrapper: createWrapper(),
    });

    // Should stay in idle/loading state without fetching
    expect(result.current.isFetching).toBe(false);
  });

  it('handles 404 error', async () => {
    server.use(
      http.get('/api/reports/nonexistent', () =>
        new HttpResponse(null, { status: 404 }),
      ),
    );

    const { result } = renderHook(() => useReport('nonexistent'), {
      wrapper: createWrapper(),
    });

    await waitFor(() => expect(result.current.isError).toBe(true));
  });
});
