import { useAuthStore } from '@/stores/auth';
import type { AuthUser } from '@alqove/types';
import { render, screen, waitFor, fireEvent } from '@testing-library/react';
import { vi, describe, it, expect, beforeEach } from 'vitest';
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
import { ProactiveRefundModal } from '../proactive-refund-modal';
import type { OrderItemData } from '@alqove/api-client';

const proactiveMock = vi.fn();
vi.mock('@/lib/api', () => ({
  api: {
    returns: { forStore: (storeId: string) => {
      expect(storeId).toBe('store-1');
      return {
      proactive: (...a: unknown[]) => proactiveMock(...a),
      };
    } },
  },
}));

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

const items: OrderItemData[] = [
  {
    id: 'oi1',
    item_id: 'item1',
    title_snapshot: 'Vintage Tee',
    price_snapshot: 2500,
    image_url_snapshot: null,
  },
  {
    id: 'oi2',
    item_id: 'item2',
    title_snapshot: 'Wool Hat',
    price_snapshot: 1500,
    image_url_snapshot: null,
  },
];

const baseProps = {
  orderId: 'ord-1',
  shippingCost: 500,
  items,
  open: true,
  onClose: () => {},
};

describe('ProactiveRefundModal', () => {
  beforeEach(() => {
    proactiveMock.mockReset();
  });

  it('renders default state with keep-it preselected', () => {
    render(wrap(<ProactiveRefundModal {...baseProps} />));
    const keepIt = screen.getByLabelText(/keep the item/i) as HTMLInputElement;
    expect(keepIt.checked).toBe(true);
  });

  it('switching to ship-back updates submit button copy', () => {
    render(wrap(<ProactiveRefundModal {...baseProps} />));
    expect(
      screen.getByRole('button', { name: /^Issue refund$/i }),
    ).toBeInTheDocument();
    fireEvent.click(screen.getByLabelText(/issue a return label/i));
    expect(
      screen.getByRole('button', { name: /Issue refund \+ label/i }),
    ).toBeInTheDocument();
  });

  it('item checkboxes default to checked', () => {
    render(wrap(<ProactiveRefundModal {...baseProps} />));
    const cb1 = screen.getByLabelText(/Vintage Tee/i) as HTMLInputElement;
    const cb2 = screen.getByLabelText(/Wool Hat/i) as HTMLInputElement;
    expect(cb1.checked).toBe(true);
    expect(cb2.checked).toBe(true);
  });

  it('refund amount input updates when items toggle', () => {
    render(wrap(<ProactiveRefundModal {...baseProps} />));
    const amountInput = screen.getByLabelText(/Refund amount/i) as HTMLInputElement;
    expect(amountInput.value).toBe('40.00');
    fireEvent.click(screen.getByLabelText(/Wool Hat/i));
    expect(amountInput.value).toBe('25.00');
  });

  it('refund amount must be > 0', async () => {
    render(wrap(<ProactiveRefundModal {...baseProps} />));
    const amountInput = screen.getByLabelText(/Refund amount/i);
    fireEvent.change(amountInput, { target: { value: '0' } });
    fireEvent.click(screen.getByRole('button', { name: /^Issue refund$/i }));
    await waitFor(() =>
      expect(screen.getByText(/must be greater than 0/i)).toBeInTheDocument(),
    );
    expect(proactiveMock).not.toHaveBeenCalled();
  });

  it('refund amount must be ≤ subtotal + shipping when shipping checkbox is on', async () => {
    render(wrap(<ProactiveRefundModal {...baseProps} />));
    fireEvent.click(screen.getByLabelText(/Refund original shipping/i));
    const amountInput = screen.getByLabelText(/Refund amount/i);
    // subtotal 4000 + shipping 500 = 4500 cap
    fireEvent.change(amountInput, { target: { value: '50.00' } });
    fireEvent.click(screen.getByRole('button', { name: /^Issue refund$/i }));
    await waitFor(() =>
      expect(screen.getByText(/cannot exceed/i)).toBeInTheDocument(),
    );
    expect(proactiveMock).not.toHaveBeenCalled();
  });

  it('Refund original shipping checkbox is visible and toggleable', () => {
    render(wrap(<ProactiveRefundModal {...baseProps} />));
    const ship = screen.getByLabelText(/Refund original shipping/i) as HTMLInputElement;
    expect(ship.checked).toBe(false);
    fireEvent.click(ship);
    expect(ship.checked).toBe(true);
  });

  it('submit calls useProactiveRefund with the right payload shape', async () => {
    proactiveMock.mockResolvedValueOnce({ data: { id: 'r1', order_id: 'ord-1' } });
    render(wrap(<ProactiveRefundModal {...baseProps} />));
    fireEvent.click(screen.getByLabelText(/Wool Hat/i));
    fireEvent.click(screen.getByRole('button', { name: /^Issue refund$/i }));
    await waitFor(() => expect(proactiveMock).toHaveBeenCalledTimes(1));
    expect(proactiveMock).toHaveBeenCalledWith('ord-1', {
      mode: 'keep-it',
      item_ids: ['oi1'],
      amount_cents: 2500,
      refund_original_shipping: false,
      reason_text: null,
    });
  });

  it('409 response shows inline error + link', async () => {
    proactiveMock.mockRejectedValueOnce(
      Object.assign(new Error('open return exists'), { status: 409 }),
    );
    render(wrap(<ProactiveRefundModal {...baseProps} />));
    fireEvent.click(screen.getByRole('button', { name: /^Issue refund$/i }));
    await waitFor(() =>
      expect(screen.getByText(/already an open return/i)).toBeInTheDocument(),
    );
    expect(screen.getByRole('link', { name: /view it/i })).toBeInTheDocument();
  });

  it('success closes modal', async () => {
    const onClose = vi.fn();
    proactiveMock.mockResolvedValueOnce({ data: { id: 'r1', order_id: 'ord-1' } });
    render(wrap(<ProactiveRefundModal {...baseProps} onClose={onClose} />));
    fireEvent.click(screen.getByRole('button', { name: /^Issue refund$/i }));
    await waitFor(() => expect(onClose).toHaveBeenCalled());
  });

  it('disables submit while mutation pending', async () => {
    let resolveFn: ((v: unknown) => void) | undefined;
    proactiveMock.mockImplementation(
      () => new Promise((res) => { resolveFn = res; }),
    );
    render(wrap(<ProactiveRefundModal {...baseProps} />));
    fireEvent.click(screen.getByRole('button', { name: /^Issue refund$/i }));
    await waitFor(() => {
      const btn = screen.getByRole('button', { name: /Issuing/i }) as HTMLButtonElement;
      expect(btn.disabled).toBe(true);
    });
    resolveFn?.({ data: { id: 'r1', order_id: 'ord-1' } });
  });
});

beforeEach(() => {
  useAuthStore.setState({ user: { id: 'seller', store_id: 'legacy' } as AuthUser, token: 'token', isLoading: false,
    selectedStoreId: 'store-1', memberships: [{ id: 'm', store_id: 'store-1', role: 'owner', capabilities: ['store.admin'], is_exempt: false }] });
});
