/**
 * 投票功能测试
 */
import { describe, it, expect, beforeAll, afterAll, beforeEach } from 'vitest';
import { VotingEngine, loadVotingScripts } from '../services/voting.engine';
import { redis } from '../config/redis';
import { TICKET_TYPES } from '@gala/shared/constants';

describe('投票功能测试', () => {
  let votingEngine: VotingEngine;
  const testUserId = 'test_user_001';
  const testProgramId = 'test_program_001';

  beforeAll(async () => {
    await loadVotingScripts();
    votingEngine = new VotingEngine();
  });

  beforeEach(async () => {
    // 清理测试数据
    const keys = await redis.keys('vote:*test*');
    if (keys.length > 0) await redis.del(...keys);
  });

  afterAll(async () => {
    await redis.quit();
  });

  describe('投票提交', () => {
    it('应该成功投票', async () => {
      const result = await votingEngine.castVote(
        testUserId,
        testProgramId,
        'creative'
      );
      expect(result.success).toBe(true);
      expect(result.program_id).toBe(testProgramId);
    });

    it('应该拒绝无效的票种', async () => {
      const result = await votingEngine.castVote(
        testUserId,
        testProgramId,
        'invalid_ticket' as any
      );
      expect(result.success).toBe(false);
      expect(result.error).toBe('INVALID_TICKET_TYPE');
    });
  });

  describe('重复投票拦截', () => {
    it('同一票种重复投同一节目应该被拦截', async () => {
      // 第一次投票
      await votingEngine.castVote(testUserId, testProgramId, 'creative');
      // 第二次投票（同一票种同一节目）
      const result = await votingEngine.castVote(testUserId, testProgramId, 'creative');
      expect(result.is_duplicate).toBe(true);
    });

    it('同一票种投不同节目应该撤销旧票', async () => {
      const program1 = 'test_program_001';
      const program2 = 'test_program_002';
      // 第一次投票
      await votingEngine.castVote(testUserId, program1, 'creative');
      // 第二次投票（同一票种不同节目）
      const result = await votingEngine.castVote(testUserId, program2, 'creative');
      expect(result.success).toBe(true);
      expect(result.revoked).toBe(true);
      expect(result.revoked_program).toBe(program1);
    });

    it('不同票种投同一节目应该被拦截', async () => {
      // 第一次投票
      await votingEngine.castVote(testUserId, testProgramId, 'creative');
      // 第二次投票（不同票种同一节目）
      const result = await votingEngine.castVote(testUserId, testProgramId, 'visual');
      expect(result.success).toBe(false);
      expect(result.error).toBe('ALREADY_VOTED_PROGRAM');
    });
  });

  describe('票数统计', () => {
    it('投票后票数应该增加', async () => {
      const result = await votingEngine.castVote(testUserId, testProgramId, 'creative');
      expect(result.success).toBe(true);
      expect(result.new_count).toBe(1);
    });

    it('多人投票票数应该累加', async () => {
      await votingEngine.castVote('test_user_1', testProgramId, 'creative');
      await votingEngine.castVote('test_user_2', testProgramId, 'visual');
      const result = await votingEngine.castVote('test_user_3', testProgramId, 'atmosphere');
      expect(result.success).toBe(true);
      expect(result.new_count).toBe(1); // 每个票种独立计数
    });
  });
});
