import { IScheduleOverride } from '../../types/ScheduleTypes';
import { IndexedDBContext } from '../IndexedDBContext';
import { ScheduleOverrideStore } from './ScheduleOverrideStore';

/**
 * ScheduleOverrideService - CRUD for schedule overrides
 *
 * Provides access to date-specific schedule overrides for resources.
 */
export class ScheduleOverrideService {
  private context: IndexedDBContext;

  constructor(context: IndexedDBContext) {
    this.context = context;
  }

  private get db(): IDBDatabase {
    return this.context.getDatabase();
  }

  /**
   * Get override for a specific resource and date
   */
  async getOverride(resourceId: string, date: string): Promise<IScheduleOverride | null> {
    return new Promise((resolve, reject) => {
      const transaction = this.db.transaction([ScheduleOverrideStore.STORE_NAME], 'readonly');
      const store = transaction.objectStore(ScheduleOverrideStore.STORE_NAME);
      const index = store.index('resourceId_date');
      const request = index.get([resourceId, date]);

      request.onsuccess = () => {
        resolve(request.result || null);
      };

      request.onerror = () => {
        reject(new Error(`Failed to get override for ${resourceId} on ${date}: ${request.error}`));
      };
    });
  }

  /**
   * Get all overrides for a resource
   */
  async getByResource(resourceId: string): Promise<IScheduleOverride[]> {
    return new Promise((resolve, reject) => {
      const transaction = this.db.transaction([ScheduleOverrideStore.STORE_NAME], 'readonly');
      const store = transaction.objectStore(ScheduleOverrideStore.STORE_NAME);
      const index = store.index('resourceId');
      const request = index.getAll(resourceId);

      request.onsuccess = () => {
        resolve(request.result || []);
      };

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

  /**
   * Get overrides for a date range
   */
  async getByDateRange(resourceId: string, startDate: string, endDate: string): Promise<IScheduleOverride[]> {
    const all = await this.getByResource(resourceId);
    return all.filter(o => o.date >= startDate && o.date <= endDate);
  }

  /**
   * Save an override
   */
  async save(override: IScheduleOverride): Promise<void> {
    return new Promise((resolve, reject) => {
      const transaction = this.db.transaction([ScheduleOverrideStore.STORE_NAME], 'readwrite');
      const store = transaction.objectStore(ScheduleOverrideStore.STORE_NAME);
      const request = store.put(override);

      request.onsuccess = () => resolve();
      request.onerror = () => {
        reject(new Error(`Failed to save override ${override.id}: ${request.error}`));
      };
    });
  }

  /**
   * Delete an override
   */
  async delete(id: string): Promise<void> {
    return new Promise((resolve, reject) => {
      const transaction = this.db.transaction([ScheduleOverrideStore.STORE_NAME], 'readwrite');
      const store = transaction.objectStore(ScheduleOverrideStore.STORE_NAME);
      const request = store.delete(id);

      request.onsuccess = () => resolve();
      request.onerror = () => {
        reject(new Error(`Failed to delete override ${id}: ${request.error}`));
      };
    });
  }
}
