import * as bcrypt from 'bcryptjs';
import { AuthService } from './auth.service';
import { expectAppError } from '../../testing/prisma-mock';

describe('AuthService player login', () => {
  const prisma = {
    user: {
      findUnique: jest.fn(),
    },
    userAuth: {
      update: jest.fn(),
    },
  };
  const jwt = { sign: jest.fn().mockReturnValue('token') };
  const config = { get: jest.fn().mockReturnValue('1h') };
  const systemConfig = {};
  const invites = {};
  const sms = {};
  const audit = { log: jest.fn() };

  let service: AuthService;

  beforeEach(() => {
    jest.clearAllMocks();
    service = new AuthService(
      prisma as never,
      jwt as never,
      config as never,
      systemConfig as never,
      invites as never,
      sms as never,
      audit as never,
    );
  });

  it('blocks player login when parent agent is suspended with blockDirectPlayerLogin', async () => {
    const passwordHash = await bcrypt.hash('Player@123', 4);
    prisma.user.findUnique
      .mockResolvedValueOnce({
        id: 10n,
        username: 'player1',
        userType: 'PLAYER',
        status: 'ACTIVE',
        parentId: 20n,
        auth: { passwordHash, loginFailCount: 0, lockedUntil: null },
        adminRole: null,
      })
      .mockResolvedValueOnce({
        userType: 'AGENT',
        status: 'SUSPENDED',
        agentProfile: { blockDirectPlayerLogin: true },
      });

    await expect(service.login('player1', 'Player@123', 'player')).rejects.toMatchObject(
      expectAppError('PARENT_AGENT_SUSPENDED'),
    );
    expect(jwt.sign).not.toHaveBeenCalled();
  });

  it('allows player login when parent agent suspended without blockDirectPlayerLogin', async () => {
    const passwordHash = await bcrypt.hash('Player@123', 4);
    prisma.user.findUnique
      .mockResolvedValueOnce({
        id: 10n,
        username: 'player1',
        userType: 'PLAYER',
        status: 'ACTIVE',
        parentId: 20n,
        locale: 'zh-CN',
        auth: { passwordHash, loginFailCount: 0, lockedUntil: null },
        adminRole: null,
      })
      .mockResolvedValueOnce({
        userType: 'AGENT',
        status: 'SUSPENDED',
        agentProfile: { blockDirectPlayerLogin: false },
      });
    prisma.userAuth.update.mockResolvedValue({});

    const result = await service.login('player1', 'Player@123', 'player');
    expect(result.token).toBe('token');
  });
});
