import { IStore } from './IStore';

/**
 * IndexedDBContext - Database connection manager
 *
 * RESPONSIBILITY:
 * - Opens and manages IDBDatabase connection lifecycle
 * - Creates object stores via injected IStore implementations
 * - Provides shared IDBDatabase instance to all services
 */
export class IndexedDBContext {
  private static readonly DB_NAME = 'CalendarDB';
  private static readonly DB_VERSION = 4;

  private db: IDBDatabase | null = null;
  private initialized: boolean = false;
  private stores: IStore[];

  constructor(stores: IStore[]) {
    this.stores = stores;
  }

  /**
   * Initialize and open the database
   */
  async initialize(): Promise<void> {
    return new Promise((resolve, reject) => {
      const request = indexedDB.open(IndexedDBContext.DB_NAME, IndexedDBContext.DB_VERSION);

      request.onerror = () => {
        reject(new Error(`Failed to open IndexedDB: ${request.error}`));
      };

      request.onsuccess = () => {
        this.db = request.result;
        this.initialized = true;
        resolve();
      };

      request.onupgradeneeded = (event) => {
        const db = (event.target as IDBOpenDBRequest).result;

        // Create all entity stores via injected IStore implementations
        this.stores.forEach(store => {
          if (!db.objectStoreNames.contains(store.storeName)) {
            store.create(db);
          }
        });
      };
    });
  }

  /**
   * Check if database is initialized
   */
  public isInitialized(): boolean {
    return this.initialized;
  }

  /**
   * Get IDBDatabase instance
   */
  public getDatabase(): IDBDatabase {
    if (!this.db) {
      throw new Error('IndexedDB not initialized. Call initialize() first.');
    }
    return this.db;
  }

  /**
   * Close database connection
   */
  close(): void {
    if (this.db) {
      this.db.close();
      this.db = null;
      this.initialized = false;
    }
  }

  /**
   * Delete entire database (for testing/reset)
   */
  static async deleteDatabase(): Promise<void> {
    return new Promise((resolve, reject) => {
      const request = indexedDB.deleteDatabase(IndexedDBContext.DB_NAME);

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