import { renderHook, act, waitFor } from '@testing-library/react';
import { vi, it, expect, beforeEach } from 'vitest';
import { useClockCommand, useTimekeepingGuard } from '../use-timekeeping';
const auth = vi.hoisted(() => ({ commandGeneration: 1, user: { id: 'u1' } as { id: string } | null, token: 'token', selectedStoreId: 's1', isLoading: false, memberships: [{ store_id: 's1', capabilities: ['timesheets.approve'] }] }));
const clock = vi.fn();
vi.mock('@/stores/auth', () => ({ useAuthStore: { getState: () => auth } }));
vi.mock('@/lib/api', () => ({ api: { timekeeping: { clock: { act: (...a: unknown[]) => clock(...a) } } } }));
beforeEach(() => { auth.user = { id: 'u1' }; auth.selectedStoreId = 's1'; clock.mockReset(); });
it('rejects A to B to A generations even when identity and tenant match again', () => {
  const { result } = renderHook(() => useTimekeepingGuard('s1', 'timesheets.approve'));
  auth.commandGeneration += 2;
  expect(result.current.current()).toBe(false);
});
it('rejects stale tenant and session commands at dispatch', () => {
  const { result } = renderHook(() => useTimekeepingGuard('s1', 'timesheets.approve'));
  expect(() => result.current.assert()).not.toThrow();
  auth.selectedStoreId = 's2';
  expect(() => result.current.assert()).toThrow(/access changed/i);
  auth.selectedStoreId = 's1'; auth.user = { id: 'u2' };
  expect(result.current.current()).toBe(false);
});
it('does not refetch or show completion after logout during a clock command', async () => {
  let resolve!: (value: unknown) => void;
  clock.mockReturnValue(new Promise(r => { resolve = r; }));
  const refresh = vi.fn().mockResolvedValue({});
  const { result } = renderHook(() => useClockCommand('s1', refresh));
  let pending!: Promise<void>;
  act(() => { pending = result.current.run({ action: 'clock', state_revision: 'empty' }); });
  await waitFor(() => expect(clock).toHaveBeenCalledOnce());
  auth.user = null;
  await act(async () => { resolve({ data: {} }); await pending; });
  expect(refresh).not.toHaveBeenCalled();
  expect(result.current.error).toBeNull();
});
