import { act, renderHook, waitFor } from '@testing-library/react';
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
import { beforeEach, expect, it, vi } from 'vitest';
import type { AuthUser } from '@alqove/types';
import { useAuthStore } from '@/stores/auth';
import { useMessages, usePostMessage, useDeleteMessage } from '../use-messages';
import { useMyThreads } from '../use-my-threads';
import { useSellerReviews, useStoreRatingSummary } from '../use-reviews';
import { useReturn, useSellerReturns, useApproveReturn, useRejectReturn, useMarkReturnReceived, useRetryReturnLabel, useProactiveRefund, useSellerCloseWithoutRefund } from '../use-returns';
const mocks = vi.hoisted(() => {
  const methods = { listSeller: vi.fn(), get: vi.fn(), approve: vi.fn(), reject: vi.fn(), markReceived: vi.fn(), retryLabel: vi.fn(), proactive: vi.fn(), sellerCloseWithoutRefund: vi.fn() };
  const messages = { threads: vi.fn(), list: vi.fn(), post: vi.fn(), delete: vi.fn() };
  return { messages, messageScope: vi.fn<(storeId: string) => typeof messages>(() => messages), reviews: { sellerReviews: vi.fn(), sellerRatingSummary: vi.fn(), storeRatingSummary: vi.fn() }, methods, forStore: vi.fn<(storeId: string) => typeof methods>(() => methods) };
});
vi.mock('@/lib/api', () => ({ api: { me: { threads: mocks.messages.threads }, messages: { ...mocks.messages, forStore: mocks.messageScope }, reviews: mocks.reviews, returns: { forStore: mocks.forStore, ...mocks.methods } } }));
const wrapper = ({ children }: { children: React.ReactNode }) => <QueryClientProvider client={new QueryClient({ defaultOptions: { queries: { retry: false }, mutations: { retry: false } } })}>{children}</QueryClientProvider>;
beforeEach(() => {
  vi.clearAllMocks();
  Object.values(mocks.methods).forEach((mock) => mock.mockResolvedValue({ data: { id: 'return', order_id: 'order' } }));
  mocks.methods.listSeller.mockResolvedValue({ data: [] });
  useAuthStore.setState({ user: { id: 'u', store_id: 'legacy' } as AuthUser, token: 'token', isLoading: false,
    selectedStoreId: 'chosen', memberships: [{ id: 'm', store_id: 'chosen', role: 'owner', capabilities: ['store.admin'], is_exempt: false }] });
});
it('seller messaging carries store scope through inbox, list, post and delete', async () => {
  mocks.messages.threads.mockResolvedValue({ data: [] });
  mocks.messages.list.mockResolvedValue({ data: [], meta: { total: 0, has_more: false } });
  const { result } = renderHook(() => ({ inbox: useMyThreads('chosen'), list: useMessages('order', { storeId: 'chosen' }), post: usePostMessage('order', 'chosen'), remove: useDeleteMessage('order', 'chosen') }), { wrapper });
  await waitFor(() => expect(result.current.inbox.isSuccess && result.current.list.isSuccess).toBe(true));
  await act(async () => { await result.current.post.mutateAsync({ body: 'hello' }); await result.current.remove.mutateAsync('message'); });
  expect(mocks.messageScope).toHaveBeenCalledWith('chosen');
  expect(mocks.messageScope.mock.calls.length).toBeGreaterThanOrEqual(4);
});
it('seller review lists and rating summaries send the selected store', async () => {
  Object.values(mocks.reviews).forEach((mock) => mock.mockResolvedValue({ data: [] }));
  const { result } = renderHook(() => ({ reviews: useSellerReviews({ page: 2 }), summary: useStoreRatingSummary('chosen', true) }), { wrapper });
  await waitFor(() => expect(result.current.reviews.isSuccess && result.current.summary.isSuccess).toBe(true));
  expect(mocks.reviews.sellerReviews).toHaveBeenCalledWith('chosen', { page: 2 });
  expect(mocks.reviews.sellerRatingSummary).toHaveBeenCalledWith('chosen');
  expect(mocks.reviews.storeRatingSummary).not.toHaveBeenCalled();
});
it('loads return detail in explicit seller scope without touching the buyer cache', async () => {
  const { result } = renderHook(() => useReturn('return', 'chosen'), { wrapper });
  await waitFor(() => expect(result.current.isSuccess).toBe(true));
  expect(mocks.forStore).toHaveBeenCalledWith('chosen');
});
it('does not submit a return action from a revoked or switched store context', async () => {
  const { result } = renderHook(() => useApproveReturn(), { wrapper });
  const oldAction = result.current.mutateAsync;
  act(() => useAuthStore.setState({ memberships: null }));
  await expect(oldAction({ returnId: 'return' })).rejects.toThrow();
  expect(mocks.methods.approve).not.toHaveBeenCalled();
});
it('seller return queries and mutations use the selected store endpoint family', async () => {
  const { result } = renderHook(() => ({ list: useSellerReturns(), approve: useApproveReturn(), reject: useRejectReturn(),
    receive: useMarkReturnReceived(), retry: useRetryReturnLabel(), proactive: useProactiveRefund('order'), close: useSellerCloseWithoutRefund() }), { wrapper });
  await waitFor(() => expect(result.current.list.isSuccess).toBe(true));
  await act(async () => {
    await result.current.approve.mutateAsync({ returnId: 'return', restockingFeeCents: 100 });
    await result.current.reject.mutateAsync({ returnId: 'return', reasonText: 'reason' });
    await result.current.receive.mutateAsync('return');
    await result.current.retry.mutateAsync('return');
    await result.current.proactive.mutateAsync({ mode: 'keep-it', item_ids: ['item'] });
    await result.current.close.mutateAsync({ returnId: 'return', reason: 'reason' });
  });
  expect(mocks.forStore).toHaveBeenCalledWith('chosen');
  expect(mocks.forStore.mock.calls.every(([id]) => id === 'chosen')).toBe(true);
  expect(mocks.forStore.mock.calls.length).toBeGreaterThanOrEqual(7);
});
