import { renderHook, act } from '@testing-library/react';
import { vi, describe, it, expect, beforeEach } from 'vitest';

const { mockIn, mockEq } = vi.hoisted(() => ({
  mockIn: vi.fn(),
  mockEq: vi.fn(),
}));

vi.mock('../../../lib/supabase', () => ({
  supabase: {
    from: vi.fn(() => ({
      select: vi.fn(() => ({ in: mockIn })),
      update: vi.fn(() => ({ eq: mockEq })),
    })),
  },
}));

import { useSettings } from '../useSettings';

describe('useSettings', () => {
  beforeEach(() => vi.clearAllMocks());

  it('loads prices on mount', async () => {
    mockIn.mockResolvedValue({
      data: [{ key: 'price_200', value: '2000' }, { key: 'price_300', value: '3000' }],
      error: null,
    });
    const { result } = renderHook(() => useSettings());
    await act(async () => {});
    expect(result.current.loading).toBe(false);
    expect(result.current.prices).toEqual({ 200: 2000, 300: 3000 });
  });

  it('sets error when fetch fails', async () => {
    mockIn.mockResolvedValue({ data: null, error: { message: 'DB error' } });
    const { result } = renderHook(() => useSettings());
    await act(async () => {});
    expect(result.current.error).toBe('DB error');
  });

  it('updatePrice calls update().eq() and updates local state', async () => {
    mockIn.mockResolvedValue({
      data: [{ key: 'price_200', value: '2000' }, { key: 'price_300', value: '3000' }],
      error: null,
    });
    mockEq.mockResolvedValue({ error: null });
    const { result } = renderHook(() => useSettings());
    await act(async () => {});
    await act(async () => {
      await result.current.updatePrice('price_200', 1800);
    });
    expect(mockEq).toHaveBeenCalledWith('key', 'price_200');
    expect(result.current.prices[200]).toBe(1800);
  });

  it('updatePrice returns error without mutating state when DB fails', async () => {
    mockIn.mockResolvedValue({
      data: [{ key: 'price_200', value: '2000' }, { key: 'price_300', value: '3000' }],
      error: null,
    });
    mockEq.mockResolvedValue({ error: { message: 'update failed' } });
    const { result } = renderHook(() => useSettings());
    await act(async () => {});
    let updateResult;
    await act(async () => {
      updateResult = await result.current.updatePrice('price_200', 9999);
    });
    expect(updateResult.error.message).toBe('update failed');
    expect(result.current.prices[200]).toBe(2000);
  });
});
