import { render, screen, fireEvent, waitFor } from '@testing-library/react';
import { vi, describe, it, expect, beforeEach } from 'vitest';
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
import type { OrderItemData } from '@alqove/api-client';
import { ReturnRequestModal } from '../return-request-modal';

const requestMock = vi.fn();
vi.mock('@/lib/api', () => ({
  api: {
    returns: { request: (...args: unknown[]) => requestMock(...args) },
    messages: { uploadAttachment: vi.fn() },
  },
}));

const items: OrderItemData[] = [
  { id: 'i1', item_id: 'item-1', title_snapshot: 'Red shirt', price_snapshot: 5000, image_url_snapshot: null },
  { id: 'i2', item_id: 'item-2', title_snapshot: 'Blue jeans', price_snapshot: 7500, image_url_snapshot: null },
];

function renderModal(props?: Partial<React.ComponentProps<typeof ReturnRequestModal>>) {
  const qc = new QueryClient({ defaultOptions: { queries: { retry: false }, mutations: { retry: false } } });
  return render(
    <QueryClientProvider client={qc}>
      <ReturnRequestModal
        orderId="o1"
        items={items}
        open={true}
        onClose={() => {}}
        {...props}
      />
    </QueryClientProvider>,
  );
}

describe('ReturnRequestModal', () => {
  beforeEach(() => requestMock.mockReset());

  it('renders all reasons and per-line items', () => {
    renderModal();
    expect(screen.getByText(/Item arrived damaged/i)).toBeTruthy();
    expect(screen.getByText(/Wrong item received/i)).toBeTruthy();
    expect(screen.getByText(/Not as described/i)).toBeTruthy();
    expect(screen.getByText(/Doesn't fit/i)).toBeTruthy();
    expect(screen.getByText(/Changed my mind/i)).toBeTruthy();
    expect(screen.getByText(/Other/i)).toBeTruthy();
    expect(screen.getByText('Red shirt')).toBeTruthy();
    expect(screen.getByText('Blue jeans')).toBeTruthy();
  });

  it('disables submit until a reason is picked and at least one item is checked', () => {
    renderModal();
    const submit = screen.getByRole('button', { name: /File return/i });
    expect(submit).toBeDisabled();

    fireEvent.click(screen.getByLabelText(/Item arrived damaged/i));
    expect(submit).not.toBeDisabled();
  });

  it('requires reason_text when reason is "other"', () => {
    renderModal();
    fireEvent.click(screen.getByLabelText(/^Other/i));
    const submit = screen.getByRole('button', { name: /File return/i });
    expect(submit).toBeDisabled();

    fireEvent.change(screen.getByLabelText(/Tell us more/i), {
      target: { value: 'My reason here' },
    });
    expect(submit).not.toBeDisabled();
  });

  it('successful submit calls mutation with correct payload', async () => {
    requestMock.mockResolvedValueOnce({
      data: {
        id: 'r1',
        order_id: 'o1',
        state: 'requested',
        items: [],
        approved_at: null,
        rejected_at: null,
        label_issued_at: null,
        in_transit_at: null,
        received_at: null,
        refunded_at: null,
        closed_at: null,
        cancelled_at: null,
        created_at: '2026-05-07T10:00:00Z',
        updated_at: '2026-05-07T10:00:00Z',
      },
    });

    renderModal();
    fireEvent.click(screen.getByLabelText(/Item arrived damaged/i));
    fireEvent.click(screen.getByRole('button', { name: /File return/i }));

    await waitFor(() => {
      expect(requestMock).toHaveBeenCalledWith('o1', {
        reason: 'damaged',
        item_ids: ['i1', 'i2'],
      });
    });
  });
});
