import { IBooking, EntityType, IEventBus, BookingStatus } from '../../types/CalendarTypes';
import { BookingStore } from './BookingStore';
import { BaseEntityService } from '../BaseEntityService';
import { IndexedDBContext } from '../IndexedDBContext';

/**
 * BookingService - CRUD operations for bookings in IndexedDB
 */
export class BookingService extends BaseEntityService<IBooking> {
  readonly storeName = BookingStore.STORE_NAME;
  readonly entityType: EntityType = 'Booking';

  constructor(context: IndexedDBContext, eventBus: IEventBus) {
    super(context, eventBus);
  }

  protected serialize(booking: IBooking): unknown {
    return {
      ...booking,
      createdAt: booking.createdAt.toISOString()
    };
  }

  protected deserialize(data: unknown): IBooking {
    const raw = data as Record<string, unknown>;
    return {
      ...raw,
      createdAt: new Date(raw.createdAt as string)
    } as IBooking;
  }

  /**
   * Get bookings for a customer
   */
  async getByCustomer(customerId: string): Promise<IBooking[]> {
    return new Promise((resolve, reject) => {
      const transaction = this.db.transaction([this.storeName], 'readonly');
      const store = transaction.objectStore(this.storeName);
      const index = store.index('customerId');
      const request = index.getAll(customerId);

      request.onsuccess = () => {
        const data = request.result as unknown[];
        const bookings = data.map(item => this.deserialize(item));
        resolve(bookings);
      };

      request.onerror = () => {
        reject(new Error(`Failed to get bookings for customer ${customerId}: ${request.error}`));
      };
    });
  }

  /**
   * Get bookings by status
   */
  async getByStatus(status: BookingStatus): Promise<IBooking[]> {
    return new Promise((resolve, reject) => {
      const transaction = this.db.transaction([this.storeName], 'readonly');
      const store = transaction.objectStore(this.storeName);
      const index = store.index('status');
      const request = index.getAll(status);

      request.onsuccess = () => {
        const data = request.result as unknown[];
        const bookings = data.map(item => this.deserialize(item));
        resolve(bookings);
      };

      request.onerror = () => {
        reject(new Error(`Failed to get bookings with status ${status}: ${request.error}`));
      };
    });
  }
}
