import BetModel, { type BetModelConfig } from './BetModel';
import {
    beforeEach,
    describe,
    expect,
    it,
} from '@jest/globals';

describe('BetModel', () =>
{
    let bets: number[];
    let model: BetModel;

    beforeEach(() =>
    {
        bets = [10, 20, 50, 100];
        model = new BetModel(bets, 0, 0);
    });

    it('should initialize with default values', () =>
    {
        expect(model.bet).toBe(10);
        expect(model.currentBetIndex).toBe(0);
        expect(model.defaultBetIndex).toBe(0);
    });

    it('should increase bet when possible', () =>
    {
        model.increaseBet();
        expect(model.bet).toBe(20);

        model.increaseBet();
        expect(model.bet).toBe(50);
    });

    it('should not increase bet beyond maximum', () =>
    {
        model.setToMaxBet();
        expect(model.bet).toBe(100);

        model.increaseBet();
        expect(model.bet).toBe(100);
    });

    it('should decrease bet when possible', () =>
    {
        model.setToMaxBet();
        model.decreaseBet();
        expect(model.bet).toBe(50);

        model.decreaseBet();
        expect(model.bet).toBe(20);
    });

    it('should not decrease bet below minimum', () =>
    {
        expect(model.bet).toBe(10);

        model.decreaseBet();
        expect(model.bet).toBe(10);
    });

    it('should set bet by value', () =>
    {
        model.setBetByValue(50);
        expect(model.bet).toBe(50);
        expect(model.currentBetIndex).toBe(2);
    });

    it('should throw error for invalid bet value', () =>
    {
        expect(() => model.setBetByValue(200)).toThrow('Bet value 200 is not valid.');
    });

    it('should lock and unlock bets', () =>
    {
        model.lock();
        expect(model.isLocked()).toBe(true);

        model.increaseBet();
        expect(model.bet).toBe(10);

        model.unlock();
        expect(model.isLocked()).toBe(false);

        model.increaseBet();
        expect(model.bet).toBe(20);
    });

    it('should reset to default bet', () =>
    {
        model.setBetByValue(50);
        expect(model.bet).toBe(50);

        model.resetToDefault();
        expect(model.bet).toBe(10);
    });

    it('should validate canIncreaseBet and canDecreaseBet', () =>
    {
        expect(model.canDecreaseBet()).toBe(false);
        expect(model.canIncreaseBet()).toBe(true);

        model.setToMaxBet();
        expect(model.canIncreaseBet()).toBe(false);
        expect(model.canDecreaseBet()).toBe(true);

        model.lock();
        expect(model.canIncreaseBet()).toBe(false);
        expect(model.canDecreaseBet()).toBe(false);
    });

    it('should accept config objects with locks', () =>
    {
        const config: BetModelConfig = {
            bets,
            currentBetIndex: 2,
            defaultBetIndex: 1,
            locked: true,
        };

        const configuredModel = new BetModel(config);

        expect(configuredModel.bet).toBe(50);
        expect(configuredModel.isLocked()).toBe(true);

        expect(() => configuredModel.setBetByValue(100)).toThrow(
            'Cannot set bet value: bets are locked.',
        );

        configuredModel.unlock();
        configuredModel.setToMaxBet();
        expect(configuredModel.bet).toBe(100);
    });
});
