import { render, screen, fireEvent, waitFor } from '@testing-library/react';
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
import { vi, it, expect } from 'vitest';
import { ClockClient } from '../clock-client';
vi.mock('@/stores/auth', () => ({ useAuthStore: { getState: () => ({ commandGeneration: 1, user: { id: 'u1' }, token: 'token', selectedStoreId: 's1', memberships: [{ store_id: 's1' }], isLoading: false }) } }));
const status = vi.fn(); const act = vi.fn();
vi.mock('@/lib/api', () => ({ api: { scheduling: { settings: async () => ({ data: { timezone: 'America/Los_Angeles' } }) }, timekeeping: { clock: { status: (...a: unknown[]) => status(...a), act: (...a: unknown[]) => act(...a) } } } }));
it('ends breaks by intent and displays store timezone, never browser-local time', async () => {
  status.mockReset(); act.mockReset();
  status.mockResolvedValue({ data: { status: 'on_break', state_revision: 'v3', allowed_actions: ['break'], punches: [], server_time: '2026-09-06T12:00:00Z' } });
  act.mockResolvedValue({ data: {} });
  const qc = new QueryClient({ defaultOptions: { queries: { retry: false } } });
  render(<QueryClientProvider client={qc}><ClockClient /></QueryClientProvider>);
  expect(await screen.findByText(/America\/Los_Angeles/)).toBeInTheDocument();
  expect(screen.getByRole('button', { name: 'Clock out' })).toBeDisabled();
  fireEvent.click(screen.getByRole('button', { name: 'End break' }));
  await waitFor(() => expect(act).toHaveBeenCalledWith('s1', { action: 'break', state_revision: 'v3' }, expect.any(String)));
});
vi.mock('@/lib/stores/store-context', async (importOriginal) => ({ ...(await importOriginal<typeof import('@/lib/stores/store-context')>()), useSelectedMembership: () => ({ store_id: 's1', capabilities: [] }), useSelectedStoreId: () => 's1' }));
it('uses the refreshed revision and a new key after a definite stale-state rejection', async () => {
  status.mockReset(); act.mockReset();
  status.mockResolvedValueOnce({ data: { status: 'clocked_out', state_revision: 'v1', allowed_actions: ['clock'], punches: [], server_time: '2026-09-06T12:00:00Z' } }).mockResolvedValue({ data: { status: 'clocked_in', state_revision: 'v2', allowed_actions: ['clock', 'break'], punches: [], server_time: '2026-09-06T12:00:01Z' } });
  act.mockRejectedValueOnce({ message: 'Stale clock state; refresh before acting.' }).mockResolvedValueOnce({ data: {} });
  const qc = new QueryClient({ defaultOptions: { queries: { retry: false } } });
  render(<QueryClientProvider client={qc}><ClockClient /></QueryClientProvider>);
  fireEvent.click(await screen.findByRole('button', { name: 'Clock in' }));
  const clockOut = await screen.findByRole('button', { name: 'Clock out' });
  await waitFor(() => expect(clockOut).toBeEnabled());
  fireEvent.click(clockOut);
  await waitFor(() => expect(act).toHaveBeenCalledTimes(2));
  expect(act.mock.calls[1][1]).toEqual({ action: 'clock', state_revision: 'v2' });
  expect(act.mock.calls[1][2]).not.toBe(act.mock.calls[0][2]);
});
it('uses authoritative state and retries an uncertain command with the same key', async () => {
  status.mockReset(); act.mockReset();
  status.mockResolvedValue({ data: { status: 'clocked_out', state_revision: 'clock-v1', allowed_actions: ['clock'], punches: [], server_time: '2026-09-06T12:00:00Z', timezone: 'America/Los_Angeles' } });
  act.mockRejectedValueOnce(new TypeError('Network unavailable')).mockResolvedValueOnce({ data: {} });
  const qc = new QueryClient({ defaultOptions: { queries: { retry: false } } });
  render(<QueryClientProvider client={qc}><ClockClient /></QueryClientProvider>);
  fireEvent.click(await screen.findByRole('button', { name: 'Clock in' }));
  expect(await screen.findByRole('alert')).toHaveTextContent('Network unavailable');
  await waitFor(() => expect(status.mock.calls.length).toBeGreaterThan(1));
  fireEvent.click(screen.getByRole('button', { name: 'Retry same action' }));
  await waitFor(() => expect(act).toHaveBeenCalledTimes(2));
  expect(act.mock.calls[0]).toEqual(act.mock.calls[1]);
  expect(act.mock.calls[0][1]).toEqual({ action: 'clock', state_revision: 'clock-v1' });
});
