import { render, screen, waitFor, fireEvent } from '@testing-library/react';
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
import { vi, describe, it, expect, beforeEach } from 'vitest';
import { OrderDetailClient } from '../order-detail-client';

const showMock = vi.fn();
const refundMock = vi.fn();
const forceCancelMock = vi.fn();
const reverseMock = vi.fn();
vi.mock('@/lib/api', () => ({
  api: {
    admin: {
      showOrder: (...a: unknown[]) => showMock(...a),
      refundOrder: (...a: unknown[]) => refundMock(...a),
      forceCancelOrder: (...a: unknown[]) => forceCancelMock(...a),
      reverseOrderTransfer: (...a: unknown[]) => reverseMock(...a),
    },
  },
}));

function wrap(node: React.ReactNode) {
  const qc = new QueryClient({ defaultOptions: { queries: { retry: false } } });
  return <QueryClientProvider client={qc}>{node}</QueryClientProvider>;
}

const detail = {
  id: 'abc12345',
  purchase_id: 'p1',
  status: 'pending',
  subtotal: 5000,
  shipping_cost: 500,
  tax_amount: 0,
  total: 5500,
  tracking_number: null,
  tracking_url: null,
  carrier: null,
  ship_by: null,
  shipped_at: null,
  delivered_at: null,
  cancelled_at: null,
  cancellation_reason: null,
  stripe_transfer_id: 'tr_x',
  transferred_at: '2026-05-01T00:00:00Z',
  stripe_transfer_reversal_id: null,
  transfer_reversed_at: null,
  store: { id: 's1', name: 'Revive' },
  buyer: { first_name: 'Jane', last_name: 'Doe' },
  items: [
    { id: 'oi1', item_id: 'item-1', title_snapshot: 'Tee', price_snapshot: 2500, image_url_snapshot: null },
    { id: 'oi2', item_id: 'item-2', title_snapshot: 'Jacket', price_snapshot: 2500, image_url_snapshot: null },
  ],
  purchase: { id: 'p1', stripe_payment_intent_id: 'pi_1', shipping_address: {} },
  created_at: '2026-05-04T00:00:00Z',
};

describe('OrderDetailClient (admin)', () => {
  beforeEach(() => {
    showMock.mockReset();
    refundMock.mockReset();
    forceCancelMock.mockReset();
    reverseMock.mockReset();
  });

  it('refund flow: amount input + justification → calls refundOrder', async () => {
    showMock.mockResolvedValue({ data: detail });
    refundMock.mockResolvedValue({ data: detail });
    render(wrap(<OrderDetailClient orderId="abc12345" />));
    await waitFor(() => expect(screen.getByText('Tee')).toBeInTheDocument());

    fireEvent.click(screen.getByRole('button', { name: /Issue refund/ }));
    fireEvent.change(screen.getByLabelText('Refund amount (cents)'), { target: { value: '3000' } });
    fireEvent.change(screen.getByLabelText('Justification'), {
      target: { value: 'Customer reported damaged packaging — partial refund.' },
    });
    fireEvent.click(screen.getByRole('button', { name: 'Confirm' }));

    await waitFor(() => expect(refundMock).toHaveBeenCalled());
    const [orderId, amount, just] = refundMock.mock.calls[0];
    expect(orderId).toBe('abc12345');
    expect(amount).toBe(3000);
    expect(just).toMatch(/damaged packaging/);
  });

  it('force-cancel flow', async () => {
    showMock.mockResolvedValue({ data: detail });
    forceCancelMock.mockResolvedValue({ data: detail });
    render(wrap(<OrderDetailClient orderId="abc12345" />));
    await waitFor(() => expect(screen.getByText('Tee')).toBeInTheDocument());

    fireEvent.click(screen.getByRole('button', { name: /Force cancel/ }));
    fireEvent.change(screen.getByLabelText('Justification'), {
      target: { value: 'Seller unresponsive past auto-cancel window.' },
    });
    // After dialog opens, two buttons match "Force cancel" (the action strip
    // button + the dialog confirm). Click the dialog's (second one).
    const buttons = screen.getAllByRole('button', { name: 'Force cancel' });
    fireEvent.click(buttons[buttons.length - 1]);

    await waitFor(() => expect(forceCancelMock).toHaveBeenCalled());
  });

  it('reverse-transfer disabled when transfer_reversed_at is set', async () => {
    showMock.mockResolvedValue({
      data: {
        ...detail,
        transfer_reversed_at: '2026-05-02T00:00:00Z',
        stripe_transfer_reversal_id: 'trr_done',
      },
    });
    render(wrap(<OrderDetailClient orderId="abc12345" />));
    await waitFor(() => expect(screen.getByText('Tee')).toBeInTheDocument());
    expect(screen.getByRole('button', { name: /Reverse transfer/ })).toBeDisabled();
  });
});
