import * as SQLite from 'expo-sqlite';
import { Platform } from 'react-native';
import { getDbName } from './DatabaseConfig';
import { runMigrations } from '../schema/MigrationManager';

type SQLiteDatabase = SQLite.SQLiteDatabase;

class DatabaseManager {
  private static instance: DatabaseManager;
  private db: SQLiteDatabase | null = null;
  private currentUserId: string | null = null;
  private initPromise: Promise<void> | null = null;

  static getInstance(): DatabaseManager {
    if (!DatabaseManager.instance) {
      DatabaseManager.instance = new DatabaseManager();
    }
    return DatabaseManager.instance;
  }

  async initialize(userId?: string | null): Promise<void> {
    const targetUserId = userId || null;

    if (this.db && this.currentUserId === targetUserId) {
      return;
    }

    if (this.initPromise) {
      await this.initPromise;
      if (this.db && this.currentUserId === targetUserId) {
        return;
      }
    }

    this.initPromise = this.doInitialize(targetUserId);

    try {
      await this.initPromise;
    } finally {
      this.initPromise = null;
    }
  }

  private async doInitialize(targetUserId: string | null): Promise<void> {
    if (this.db) {
      this.forceClose(this.db);
      this.db = null;
      this.currentUserId = null;
    }

    const dbName = getDbName(targetUserId);
    const isWeb = Platform.OS === 'web';

    if (isWeb) {
      try {
        const db = await this.tryOpenDatabase(dbName);
        await runMigrations(db);
        this.db = db;
        this.currentUserId = targetUserId;
      } catch (error) {
        console.warn('[DatabaseManager] Web数据库打开失败，使用内存数据库:', error);
        const db = await SQLite.openDatabaseAsync(':memory:');
        await runMigrations(db);
        this.db = db;
        this.currentUserId = targetUserId;
      }
      return;
    }

    const db = await this.tryOpenDatabase(dbName);
    await runMigrations(db);
    this.db = db;
    this.currentUserId = targetUserId;
  }

  private async tryOpenDatabase(dbName: string): Promise<SQLiteDatabase> {
    try {
      return await SQLite.openDatabaseAsync(dbName, {
        useNewConnection: true,
      });
    } catch (error) {
      const msg = String(error);
      if (msg.includes('cannot create file') || msg.includes('SQLITE_CANTOPEN') || msg.includes('database is locked')) {
        return await SQLite.openDatabaseAsync(':memory:');
      }
      throw error;
    }
  }

  private forceClose(db: SQLiteDatabase): void {
    try {
      db.closeSync();
    } catch {
      try {
        db.closeAsync().catch(() => {});
      } catch {}
    }
  }

  async close(): Promise<void> {
    if (this.initPromise) {
      await this.initPromise.catch(() => {});
    }

    if (this.db) {
      this.forceClose(this.db);
      this.db = null;
      this.currentUserId = null;
    }
  }

  async getDb(): Promise<SQLiteDatabase> {
    if (this.db) return this.db;

    if (this.initPromise) {
      await this.initPromise;
      if (this.db) return this.db;
    }

    throw new Error('数据库未初始化');
  }

  getDbSync(): SQLiteDatabase | null {
    return this.db;
  }

  getCurrentUserId(): string | null {
    return this.currentUserId;
  }

  isReady(): boolean {
    return this.db !== null;
  }
}

export const databaseManager = DatabaseManager.getInstance();
export { DatabaseManager };