/**
 * EventPersistenceManager - Persists event changes to IndexedDB
 *
 * Listens to drag/resize events and updates IndexedDB via EventService.
 * This bridges the gap between UI interactions and data persistence.
 */

import { ICalendarEvent, IEventBus, IEventUpdatedPayload } from '../types/CalendarTypes';
import { EventService } from '../storage/events/EventService';
import { DateService } from '../core/DateService';
import { CoreEvents } from '../constants/CoreEvents';
import { IDragEndPayload } from '../types/DragTypes';
import { IResizeEndPayload } from '../types/ResizeTypes';

export class EventPersistenceManager {
  constructor(
    private eventService: EventService,
    private eventBus: IEventBus,
    private dateService: DateService
  ) {
    this.setupListeners();
  }

  private setupListeners(): void {
    this.eventBus.on(CoreEvents.EVENT_DRAG_END, this.handleDragEnd);
    this.eventBus.on(CoreEvents.EVENT_RESIZE_END, this.handleResizeEnd);
  }

  /**
   * Handle drag end - update event position in IndexedDB
   */
  private handleDragEnd = async (e: Event): Promise<void> => {
    const payload = (e as CustomEvent<IDragEndPayload>).detail;
    const { swpEvent } = payload;

    // Get existing event to merge with
    const event = await this.eventService.get(swpEvent.eventId);
    if (!event) {
      console.warn(`EventPersistenceManager: Event ${swpEvent.eventId} not found`);
      return;
    }

    // Parse resourceId from columnKey if present
    const { resource } = this.dateService.parseColumnKey(swpEvent.columnKey);

    // Update and save - start/end already calculated in SwpEvent
    // Set allDay based on drop target:
    // - header: allDay = true
    // - grid: allDay = false (converts allDay event to timed)
    const updatedEvent: ICalendarEvent = {
      ...event,
      start: swpEvent.start,
      end: swpEvent.end,
      resourceId: resource ?? event.resourceId,
      allDay: payload.target === 'header',
      syncStatus: 'pending'
    };

    await this.eventService.save(updatedEvent);

    // Emit EVENT_UPDATED for EventRenderer to re-render affected columns
    const updatePayload: IEventUpdatedPayload = {
      eventId: updatedEvent.id,
      sourceColumnKey: payload.sourceColumnKey,
      targetColumnKey: swpEvent.columnKey
    };
    this.eventBus.emit(CoreEvents.EVENT_UPDATED, updatePayload);
  };

  /**
   * Handle resize end - update event duration in IndexedDB
   */
  private handleResizeEnd = async (e: Event): Promise<void> => {
    const payload = (e as CustomEvent<IResizeEndPayload>).detail;
    const { swpEvent } = payload;

    // Get existing event to merge with
    const event = await this.eventService.get(swpEvent.eventId);
    if (!event) {
      console.warn(`EventPersistenceManager: Event ${swpEvent.eventId} not found`);
      return;
    }

    // Update and save - end already calculated in SwpEvent
    const updatedEvent: ICalendarEvent = {
      ...event,
      end: swpEvent.end,
      syncStatus: 'pending'
    };

    await this.eventService.save(updatedEvent);

    // Emit EVENT_UPDATED for EventRenderer to re-render the column
    // Resize stays in same column, so source and target are the same
    const updatePayload: IEventUpdatedPayload = {
      eventId: updatedEvent.id,
      sourceColumnKey: swpEvent.columnKey,
      targetColumnKey: swpEvent.columnKey
    };
    this.eventBus.emit(CoreEvents.EVENT_UPDATED, updatePayload);
  };
}
