import 'reflect-metadata'

import { app } from 'electron'
import { join } from 'path'
import { DataSource } from 'typeorm'

import { ClassEntitySchema } from '../entities/ClassEntity'
import { StudentProfileEntitySchema } from '../entities/StudentProfileEntity'
import { TemplateEntitySchema } from '../entities/TemplateEntity'
import { ReportEntitySchema } from '../entities/ReportEntity'
import { getLogger } from './loggerService'

const DATABASE_FILENAME = 'growth-report.sqlite'
const logger = getLogger('database')

let dataSource: DataSource | null = null
let dataSourcePromise: Promise<DataSource> | null = null

function getDatabasePath(): string {
  return join(app.getPath('userData'), DATABASE_FILENAME)
}

export async function getAppDataSource(): Promise<DataSource> {
  if (dataSource?.isInitialized) {
    return dataSource
  }

  if (dataSourcePromise) {
    return dataSourcePromise
  }

  const nextDataSource = new DataSource({
    type: 'better-sqlite3',
    database: getDatabasePath(),
    entities: [
      ClassEntitySchema,
      StudentProfileEntitySchema,
      TemplateEntitySchema,
      ReportEntitySchema
    ],
    synchronize: true,
    logging: false,
    prepareDatabase(database): void {
      database.pragma('journal_mode = WAL')
      database.pragma('foreign_keys = ON')
      database.exec('DROP INDEX IF EXISTS idx_child_profiles_class_id')
    }
  })

  dataSourcePromise = nextDataSource
    .initialize()
    .then((initializedDataSource) => {
      dataSource = initializedDataSource
      logger.info('数据库初始化完成', {
        databasePath: getDatabasePath(),
        entities: initializedDataSource.entityMetadatas.map((metadata) => metadata.name)
      })
      return initializedDataSource
    })
    .catch((error) => {
      dataSourcePromise = null
      throw error
    })

  return dataSourcePromise
}
