import { Injectable } from '@angular/core';

import { createCapacitorSqliteStore, type MobileSqliteStore } from '../adapters/capacitor/capacitor-sqlite.store';
import { resolveMobileSqliteDatabaseName } from '../logic/mobile-sqlite-database-name.rules';
import { getStoredCurrentUserId } from '../../../core/storage/current-user-storage';

/** Shared native SQLite connection used by mobile persistence and DatabaseService. */
@Injectable({ providedIn: 'root' })
export class MobileSqliteConnectionService {
  private store: MobileSqliteStore | null = null;
  private activeDatabaseName: string | null = null;
  private initializationPromise: Promise<MobileSqliteStore | null> | null = null;
  private initializationFailed = false;

  get isAvailable(): boolean {
    return this.store?.isAvailable === true;
  }

  async initialize(): Promise<MobileSqliteStore | null> {
    if (this.initializationFailed) {
      return null;
    }

    if (this.initializationPromise) {
      return this.initializationPromise;
    }

    this.initializationPromise = this.openStore()
      .catch((error) => {
        this.initializationFailed = true;
        console.error('[mobile] SQLite initialization failed', error);
        return null;
      })
      .finally(() => {
        this.initializationPromise = null;
      });

    return this.initializationPromise;
  }

  async getStore(): Promise<MobileSqliteStore> {
    const store = await this.initialize();

    if (!store?.isAvailable) {
      throw new Error('Native SQLite store is unavailable on this shell.');
    }

    return store;
  }

  private async openStore(): Promise<MobileSqliteStore | null> {
    const databaseName = resolveMobileSqliteDatabaseName(getStoredCurrentUserId());

    if (this.store && this.activeDatabaseName === databaseName && this.store.isAvailable) {
      return this.store;
    }

    this.store = await createCapacitorSqliteStore(databaseName);

    if (!this.store) {
      return null;
    }

    await this.store.initialize();
    this.activeDatabaseName = databaseName;

    return this.store;
  }
}
