import { CommandBus } from '@application/handlers/CommandBus';
import { QueryBus } from '@application/handlers/QueryBus';
import { EventBus } from '@domain/events/EventBus';
import { LocalStorageRepository } from '@infrastructure/persistence/LocalStorageRepository';
import { ElectronNotification } from '@infrastructure/notifications/ElectronNotification';
import { WebAudioAlarm } from '@infrastructure/alarm/WebAudioAlarm';
import { UIState } from '@presentation/state/UIState';
import { App } from '@presentation/components/App';
import type { AppState } from '@domain/ports/StateRepository';

// Command handler factories
import { createStartTimerHandler } from '@application/commands/StartTimer';
import { createStopTimerHandler } from '@application/commands/StopTimer';
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 { createToggleGaugeHandler, createUpdateGaugeLevelHandler } from '@application/commands/UpdateGauge';
import { createRegisterAccouplementHandler } from '@application/commands/RegisterAccouplement';
import { createUpdateSettingsHandler } from '@application/commands/UpdateSettings';
import { createResetStatsHandler } from '@application/commands/ResetStats';
import { createReorderEnclosHandler } from '@application/commands/ReorderEnclos';
import { createUpdateWorkflowHandler } from '@application/commands/UpdateWorkflow';
import { createDeleteWorkflowHandler } from '@application/commands/DeleteWorkflow';
import { createSaveWorkflowHandler } from '@application/commands/SaveWorkflow';
import { createImportWorkflowsHandler } from '@application/commands/ImportWorkflows';
import { createClearEnclosHandler, createRenameEnclosHandler, createResetTimerHandler, createNouvelleFourneeHandler } from '@application/commands/EnclosActions';
import { createRechargeGaugeHandler } from '@application/commands/RechargeGauge';
import { createCompleteTimerHandler } from '@application/commands/CompleteTimer';
import { createRenameDragodindeHandler, createUpdateDdStatHandler, createUpdateDdSerenTargetHandler, createUpdateDdLevelTargetHandler, createReorderDragodindeHandler } from '@application/commands/DragodindeActions';

// Query handler factories
import { createGetDashboardHandler } from '@application/queries/GetDashboard';
import { createGetEnclosDetailHandler } from '@application/queries/GetEnclosDetail';
import { createGetTimerStateHandler } from '@application/queries/GetTimerState';
import { createGetBreedingOptionsHandler } from '@application/queries/GetBreedingOptions';
import { createGetReapproTreeHandler } from '@application/queries/GetReapproTree';
import { createGetInventaireHandler } from '@application/queries/GetInventaire';
import { createGetSettingsHandler } from '@application/queries/GetSettings';
import { createGetWorkflowsHandler } from '@application/queries/GetWorkflows';
import { createGetStatisticsHandler } from '@application/queries/GetStatistics';

async function bootstrap(): Promise<void> {
  // Infrastructure
  const repo = new LocalStorageRepository();
  const notifications = new ElectronNotification();
  const alarm = new WebAudioAlarm();
  const events = new EventBus();

  // Load state
  const defaultState: AppState = {
    enclos: [], activeId: 'dashboard', nextEnclosId: 1,
    alarmSound: 'arpege', notifsEnabled: true, ntfyTopic: '',
    archivedStats: [], inventaire: {}, workflows: [], accouplements: [],
  };
  const state: AppState = (await repo.load()) ?? defaultState;

  // Command Bus
  const commandBus = new CommandBus();
  commandBus.register('start-timer', createStartTimerHandler(state, repo));
  commandBus.register('stop-timer', createStopTimerHandler(state, repo));
  commandBus.register('create-enclos', createCreateEnclosHandler(state, repo));
  commandBus.register('delete-enclos', createDeleteEnclosHandler(state, repo, events));
  commandBus.register('add-dragodinde', createAddDragodindeHandler(state, repo));
  commandBus.register('remove-dragodinde', createRemoveDragodindeHandler(state, repo));
  commandBus.register('toggle-gauge', createToggleGaugeHandler(state, repo));
  commandBus.register('update-gauge-level', createUpdateGaugeLevelHandler(state, repo));
  commandBus.register('register-accouplement', createRegisterAccouplementHandler(state, repo, events));
  commandBus.register('update-settings', createUpdateSettingsHandler(state, repo));
  commandBus.register('reset-stats', createResetStatsHandler(state, repo));
  commandBus.register('reorder-enclos', createReorderEnclosHandler(state, repo));
  commandBus.register('update-workflow', createUpdateWorkflowHandler(state, repo));
  commandBus.register('delete-workflow', createDeleteWorkflowHandler(state, repo));
  commandBus.register('save-workflow', createSaveWorkflowHandler(state, repo));
  commandBus.register('import-workflows', createImportWorkflowsHandler(state, repo));
  commandBus.register('complete-timer', createCompleteTimerHandler(state, repo, events));
  commandBus.register('recharge-gauge', createRechargeGaugeHandler(state, repo));
  commandBus.register('clear-enclos', createClearEnclosHandler(state, repo));
  commandBus.register('rename-enclos', createRenameEnclosHandler(state, repo));
  commandBus.register('reset-timer', createResetTimerHandler(state, repo));
  commandBus.register('nouvelle-fournee', createNouvelleFourneeHandler(state, repo));
  commandBus.register('rename-dragodinde', createRenameDragodindeHandler(state, repo));
  commandBus.register('update-dd-stat', createUpdateDdStatHandler(state, repo));
  commandBus.register('update-dd-seren-target', createUpdateDdSerenTargetHandler(state, repo));
  commandBus.register('update-dd-level-target', createUpdateDdLevelTargetHandler(state, repo));
  commandBus.register('reorder-dragodinde', createReorderDragodindeHandler(state, repo));

  // Query Bus
  const queryBus = new QueryBus();
  queryBus.register('get-dashboard', createGetDashboardHandler(state));
  queryBus.register('get-enclos-detail', createGetEnclosDetailHandler(state));
  queryBus.register('get-timer-state', createGetTimerStateHandler(state));
  queryBus.register('get-breeding-options', createGetBreedingOptionsHandler());
  queryBus.register('get-reappro-tree', createGetReapproTreeHandler());
  queryBus.register('get-inventaire', createGetInventaireHandler(state));
  queryBus.register('get-settings', createGetSettingsHandler(state));
  queryBus.register('get-workflows', createGetWorkflowsHandler(state));
  queryBus.register('get-statistics', createGetStatisticsHandler(state));

  // Event handlers
  events.on('timer-completed', (event) => {
    const enclosName = (event as any).enclosName ?? 'Enclos';
    if (state.notifsEnabled) {
      notifications.showNotification('Dragodindes prêtes !', `${enclosName} — Toutes les cibles atteintes !`);
    }
    alarm.play(state.alarmSound);
    if (state.ntfyTopic) {
      const url = `https://ntfy.mickael-pol.fr/${state.ntfyTopic}`;
      notifications.sendMobileNotification(url, 'Dragodindes prêtes !', `${enclosName} — Toutes les cibles atteintes !`);
    }
  });

  // Presentation
  const uiState = new UIState();
  uiState.activeView = state.activeId ?? 'dashboard';

  const rootEl = document.getElementById('app');
  if (!rootEl) throw new Error('Root element #app not found');

  const app = new App(commandBus, queryBus, uiState, rootEl, (name: string) => alarm.play(name));
  app.render();
}

bootstrap().catch(console.error);
