import { beforeEach, describe, expect, it, vi } from 'vitest';

const {
  mockExecute,
  mockRelease,
  mockGetConnection,
  mockQueryOne,
  mockAwardDiamonds,
} = vi.hoisted(() => {
  const execute = vi.fn();
  const release = vi.fn();
  const getConnection = vi.fn(async () => ({
    execute,
    release,
  }));
  const queryOne = vi.fn();
  const awardDiamonds = vi.fn(() => true);
  return {
    mockExecute: execute,
    mockRelease: release,
    mockGetConnection: getConnection,
    mockQueryOne: queryOne,
    mockAwardDiamonds: awardDiamonds,
  };
});

vi.mock('../../../src/database/index.js', () => ({
  query: vi.fn(),
  queryOne: mockQueryOne,
  execute: vi.fn(),
  getConnection: mockGetConnection,
}));

vi.mock('../../../src/monetization/diamondEconomy.js', () => ({
  awardDiamonds: mockAwardDiamonds,
}));

import { claimDailyReward } from '../../../src/services/retention/dailyRewards.js';
import { awardDiamonds } from '../../../src/monetization/diamondEconomy.js';

describe('dailyRewards security behavior', () => {
  beforeEach(() => {
    vi.clearAllMocks();

    mockExecute.mockImplementation(async (sql: string) => {
      if (sql.includes('SELECT * FROM player_login_streak')) {
        return [[{
          player_id: 'player-1',
          current_streak: 1,
          last_login_date: new Date(),
          total_logins: 1,
          next_reward_day: 1,
          claimed_today: 0,
        }]];
      }
      return [[]];
    });

    mockQueryOne.mockImplementation(async (_sql: string, params?: unknown[]) => {
      const day = Number(params?.[0] ?? 0);
      return {
        day_number: day,
        reward_type: 'diamonds',
        reward_amount: day === 1 ? 5 : 50,
        reward_item_id: null,
        display_name: `Day ${day}`,
      };
    });
  });

  it('uses day 1 reward (not day 7) when next_reward_day starts at 1', async () => {
    const result = await claimDailyReward('player-1');

    expect(result.success).toBe(true);
    expect(result.reward?.day).toBe(1);
    expect((awardDiamonds as unknown as { mock: { calls: unknown[][] } }).mock.calls[0]?.slice(0, 3))
      .toEqual(['player-1', 'daily_reward_day1', 5]);
  });
});
