import { describe, it, expect, vi } from 'vitest';
import { CommandBus } from '@application/handlers/CommandBus';
import { EventBus } from '@domain/events/EventBus';
import type { AppState, StateRepository } from '@domain/ports/StateRepository';
import { createCreateEnclosHandler } from '@application/commands/CreateEnclos';
import { createDeleteEnclosHandler } from '@application/commands/DeleteEnclos';
import { createAddDragodindeHandler } from '@application/commands/AddDragodinde';
import { createRemoveDragodindeHandler } from '@application/commands/RemoveDragodinde';
import { MAX_ENCLOS, MAX_DD } from '@domain/entities/Enclos';

function setup() {
  const repo: StateRepository = { load: vi.fn(async () => null), save: vi.fn() };
  const events = new EventBus();
  const state: AppState = {
    enclos: [], activeId: 'dashboard', nextEnclosId: 1,
    alarmSound: 'arpege', notifsEnabled: true, ntfyTopic: '',
    archivedStats: [], inventaire: {}, workflows: [], accouplements: [],
  };

  const cmdBus = new CommandBus();
  cmdBus.register('create-enclos', createCreateEnclosHandler(state, repo));
  cmdBus.register('delete-enclos', createDeleteEnclosHandler(state, repo, events));
  cmdBus.register('add-dragodinde', createAddDragodindeHandler(state, repo));
  cmdBus.register('remove-dragodinde', createRemoveDragodindeHandler(state, repo));

  return { state, cmdBus, events };
}

describe('Enclos Management', () => {
  it('create up to MAX_ENCLOS', () => {
    const { state, cmdBus } = setup();
    for (let i = 0; i < MAX_ENCLOS + 2; i++) {
      cmdBus.execute({ type: 'create-enclos' });
    }
    expect(state.enclos).toHaveLength(MAX_ENCLOS);
  });

  it('delete switches to dashboard when last enclos removed', () => {
    const { state, cmdBus } = setup();
    cmdBus.execute({ type: 'create-enclos' });
    const id = state.enclos[0]!.id;
    state.activeId = id;
    cmdBus.execute({ type: 'delete-enclos', enclosId: id });
    expect(state.enclos).toHaveLength(0);
    expect(state.activeId).toBe('dashboard');
  });

  it('add DDs up to MAX_DD per enclos', () => {
    const { state, cmdBus } = setup();
    cmdBus.execute({ type: 'create-enclos' });
    const encId = state.enclos[0]!.id;
    // Already has 1 DD from creation
    for (let i = 0; i < MAX_DD; i++) {
      cmdBus.execute({ type: 'add-dragodinde', enclosId: encId });
    }
    expect(state.enclos[0]!.dragodindes.length).toBeLessThanOrEqual(MAX_DD);
  });

  it('remove DD from enclos', () => {
    const { state, cmdBus } = setup();
    cmdBus.execute({ type: 'create-enclos' });
    const encId = state.enclos[0]!.id;
    const ddId = state.enclos[0]!.dragodindes[0]!.id;
    cmdBus.execute({ type: 'remove-dragodinde', enclosId: encId, ddId });
    expect(state.enclos[0]!.dragodindes).toHaveLength(0);
  });
});
