import { Container, Builder } from '@novadi/core';

// Core
import { EventBus } from './core/EventBus';
import { DateService } from './core/DateService';
import { CalendarOrchestrator } from './core/CalendarOrchestrator';
import { CalendarApp } from './core/CalendarApp';
import { TimeAxisRenderer } from './features/timeaxis/TimeAxisRenderer';
import { ScrollManager } from './core/ScrollManager';
import { HeaderDrawerManager } from './core/HeaderDrawerManager';
import { ITimeFormatConfig } from './core/ITimeFormatConfig';
import { IGridConfig } from './core/IGridConfig';

// Types
import { IEventBus, ICalendarEvent, ISync, IResource } from './types/CalendarTypes';
import { TenantSetting } from './types/SettingsTypes';
import { ViewConfig } from './core/ViewConfig';

// Renderers
import { IRenderer } from './core/IGroupingRenderer';
import { DateRenderer } from './features/date/DateRenderer';
import { ResourceRenderer } from './features/resource/ResourceRenderer';
import { EventRenderer } from './features/event/EventRenderer';
import { ScheduleRenderer } from './features/schedule/ScheduleRenderer';
import { HeaderDrawerRenderer } from './features/headerdrawer/HeaderDrawerRenderer';

// Storage
import { IndexedDBContext, IDBConfig, defaultDBConfig } from './storage/IndexedDBContext';
import { IStore } from './storage/IStore';
import { IEntityService } from './storage/IEntityService';
import { EventStore } from './storage/events/EventStore';
import { EventService } from './storage/events/EventService';
import { ResourceStore } from './storage/resources/ResourceStore';
import { ResourceService } from './storage/resources/ResourceService';
import { SettingsStore } from './storage/settings/SettingsStore';
import { SettingsService } from './storage/settings/SettingsService';
import { ViewConfigStore } from './storage/viewconfigs/ViewConfigStore';
import { ViewConfigService } from './storage/viewconfigs/ViewConfigService';

// Managers
import { DragDropManager } from './managers/DragDropManager';
import { EdgeScrollManager } from './managers/EdgeScrollManager';
import { ResizeManager } from './managers/ResizeManager';
import { EventPersistenceManager } from './managers/EventPersistenceManager';

/**
 * Default configuration values
 */
export const defaultTimeFormatConfig: ITimeFormatConfig = {
  timezone: Intl.DateTimeFormat().resolvedOptions().timeZone,
  use24HourFormat: true,
  locale: 'da-DK',
  dateFormat: 'locale',
  showSeconds: false
};

export const defaultGridConfig: IGridConfig = {
  hourHeight: 64,
  dayStartHour: 6,
  dayEndHour: 18,
  snapInterval: 15,
  gridStartThresholdMinutes: 30
};

/**
 * Calendar configuration options
 */
export interface ICalendarOptions {
  timeConfig?: ITimeFormatConfig;
  gridConfig?: IGridConfig;
  dbConfig?: IDBConfig;
}

/**
 * Creates a configured DI container with all core calendar services registered.
 * Call this to get a ready-to-use container for the calendar.
 *
 * @param options - Optional calendar configuration options
 * @returns Configured Container instance
 */
export function createCalendarContainer(options?: ICalendarOptions): Container {
  const container = new Container();
  const builder = container.builder();

  registerCoreServices(builder, options);

  return builder.build();
}

/**
 * Registers all core calendar services with the DI container builder.
 * Use this when you need to customize the container or add extensions.
 *
 * @param builder - ContainerBuilder to register services with
 * @param options - Optional calendar configuration options
 */
export function registerCoreServices(
  builder: Builder,
  options?: ICalendarOptions
): void {
  const timeConfig = options?.timeConfig ?? defaultTimeFormatConfig;
  const gridConfig = options?.gridConfig ?? defaultGridConfig;
  const dbConfig = options?.dbConfig ?? defaultDBConfig;
  // Configuration instances
  builder.registerInstance(timeConfig).as<ITimeFormatConfig>();
  builder.registerInstance(gridConfig).as<IGridConfig>();
  builder.registerInstance(dbConfig).as<IDBConfig>();

  // Core - EventBus (singleton pattern via dual registration)
  builder.registerType(EventBus).as<EventBus>();
  builder.registerType(EventBus).as<IEventBus>();

  // Core Services
  builder.registerType(DateService).as<DateService>();

  // Storage infrastructure
  builder.registerType(IndexedDBContext).as<IndexedDBContext>();

  // Core Stores (for IndexedDB schema creation via IStore[] array injection)
  builder.registerType(EventStore).as<IStore>();
  builder.registerType(ResourceStore).as<IStore>();
  builder.registerType(SettingsStore).as<IStore>();
  builder.registerType(ViewConfigStore).as<IStore>();

  // Core Entity Services (polymorphic via IEntityService<T>)
  builder.registerType(EventService).as<IEntityService<ICalendarEvent>>();
  builder.registerType(EventService).as<IEntityService<ISync>>();
  builder.registerType(EventService).as<EventService>();

  builder.registerType(ResourceService).as<IEntityService<IResource>>();
  builder.registerType(ResourceService).as<IEntityService<ISync>>();
  builder.registerType(ResourceService).as<ResourceService>();

  builder.registerType(SettingsService).as<IEntityService<TenantSetting>>();
  builder.registerType(SettingsService).as<IEntityService<ISync>>();
  builder.registerType(SettingsService).as<SettingsService>();

  builder.registerType(ViewConfigService).as<IEntityService<ViewConfig>>();
  builder.registerType(ViewConfigService).as<IEntityService<ISync>>();
  builder.registerType(ViewConfigService).as<ViewConfigService>();

  // Core Renderers
  builder.registerType(EventRenderer).as<EventRenderer>();
  builder.registerType(ScheduleRenderer).as<ScheduleRenderer>();
  builder.registerType(HeaderDrawerRenderer).as<HeaderDrawerRenderer>();
  builder.registerType(TimeAxisRenderer).as<TimeAxisRenderer>();

  // Grouping Renderers (registered as IRenderer[] for CalendarOrchestrator)
  builder.registerType(DateRenderer).as<IRenderer>();
  builder.registerType(ResourceRenderer).as<IRenderer>();

  // Core Managers
  builder.registerType(ScrollManager).as<ScrollManager>();
  builder.registerType(HeaderDrawerManager).as<HeaderDrawerManager>();
  builder.registerType(DragDropManager).as<DragDropManager>();
  builder.registerType(EdgeScrollManager).as<EdgeScrollManager>();
  builder.registerType(ResizeManager).as<ResizeManager>();
  builder.registerType(EventPersistenceManager).as<EventPersistenceManager>();

  // Orchestrator and App
  builder.registerType(CalendarOrchestrator).as<CalendarOrchestrator>();
  builder.registerType(CalendarApp).as<CalendarApp>();
}
