import { describe, it, expect, vi } from 'vitest';
import { CommandBus } from '@application/handlers/CommandBus';
import { QueryBus } from '@application/handlers/QueryBus';
import { EventBus } from '@domain/events/EventBus';
import type { AppState, StateRepository } from '@domain/ports/StateRepository';
import { createRegisterAccouplementHandler } from '@application/commands/RegisterAccouplement';
import { createGetDashboardHandler } from '@application/queries/GetDashboard';
import { createGetBreedingOptionsHandler } from '@application/queries/GetBreedingOptions';
import { BreedingService } from '@domain/services/BreedingService';

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();
  const qBus = new QueryBus();

  cmdBus.register('register-accouplement', createRegisterAccouplementHandler(state, repo, events));
  qBus.register('get-dashboard', createGetDashboardHandler(state));
  qBus.register('get-breeding-options', createGetBreedingOptionsHandler());

  return { state, cmdBus, qBus };
}

describe('Breeding Workflow', () => {
  it('select parents → deduce baby → register → dashboard reflects', () => {
    const { cmdBus, qBus } = setup();
    const svc = new BreedingService();

    // 1. Get compatible partners for Rousse
    const options = qBus.execute<any>({ type: 'get-breeding-options', race: 'Rousse' });
    expect(options.partners.some((p: any) => p.partner === 'Dorée')).toBe(true);

    // 2. Deduce baby
    const baby = svc.deduceBaby('Rousse', 'Dorée');
    expect(baby).toBe('Dorée et Rousse');

    // 3. Register accouplement
    cmdBus.execute({
      type: 'register-accouplement',
      parentA: 'Rousse', parentB: 'Dorée', baby: 'Dorée et Rousse',
      couples: 10, babiesObtained: 7,
    });

    // 4. Dashboard shows updated stats
    const dash = qBus.execute<any>({ type: 'get-dashboard' });
    expect(dash.totalCouples).toBe(10);
    expect(dash.totalBabies).toBe(7);
    expect(dash.successRate).toBe(70);
    expect(dash.raceBreakdown['Dorée et Rousse']).toBe(7);
  });

  it('multiple accouplements accumulate', () => {
    const { cmdBus, qBus } = setup();

    cmdBus.execute({
      type: 'register-accouplement',
      parentA: 'Rousse', parentB: 'Dorée', baby: 'Dorée et Rousse',
      couples: 5, babiesObtained: 3,
    });
    cmdBus.execute({
      type: 'register-accouplement',
      parentA: 'Amande', parentB: 'Dorée', baby: 'Amande et Dorée',
      couples: 8, babiesObtained: 5,
    });

    const dash = qBus.execute<any>({ type: 'get-dashboard' });
    expect(dash.totalCouples).toBe(13);
    expect(dash.totalBabies).toBe(8);
  });
});
