/**
 * Repository tests for votes module — in-memory datastore.
 */

import { describe, it, expect, beforeEach, afterAll } from 'vitest';
import { MemoryDatastoreProvider } from '@bytelyst/datastore';
import { setProvider, _resetDatastoreProvider } from '../../lib/datastore.js';
import { getByItemAndUser, countByItem, listByItem, create, remove } from './repository.js';
import type { VoteDoc } from './types.js';

const baseVote: VoteDoc = {
  id: 'vote_1',
  productId: 'lysnrai',
  itemId: 'item_1',
  userId: 'user_1',
  createdAt: '2026-02-16T00:00:00Z',
};

describe('votes repository', () => {
  beforeEach(() => {
    setProvider(new MemoryDatastoreProvider());
  });

  afterAll(() => {
    _resetDatastoreProvider();
  });

  describe('getByItemAndUser', () => {
    it('returns vote when found', async () => {
      await create(baseVote);
      const result = await getByItemAndUser('item_1', 'user_1');
      expect(result).toEqual(baseVote);
    });

    it('returns null when not found', async () => {
      const result = await getByItemAndUser('item_1', 'user_1');
      expect(result).toBeNull();
    });
  });

  describe('countByItem', () => {
    it('returns count', async () => {
      await create(baseVote);
      await create({ ...baseVote, id: 'vote_2', userId: 'user_2' });
      const result = await countByItem('item_1');
      expect(result).toBe(2);
    });

    it('returns 0 when no votes', async () => {
      const result = await countByItem('item_1');
      expect(result).toBe(0);
    });
  });

  describe('listByItem', () => {
    it('returns votes for item', async () => {
      await create(baseVote);
      const result = await listByItem('item_1');
      expect(result).toHaveLength(1);
      expect(result[0]!.id).toBe('vote_1');
    });

    it('returns empty array when no votes', async () => {
      const result = await listByItem('item_1');
      expect(result).toEqual([]);
    });
  });

  describe('create', () => {
    it('creates and returns vote', async () => {
      const result = await create(baseVote);
      expect(result).toEqual(baseVote);
    });
  });

  describe('remove', () => {
    it('deletes and returns true', async () => {
      await create(baseVote);
      const result = await remove('vote_1');
      expect(result).toBe(true);
    });

    it('returns true even for nonexistent (idempotent delete)', async () => {
      const result = await remove('nonexistent');
      expect(result).toBe(true);
    });
  });
});
