import { AsyncLocalStorage } from 'node:async_hooks'
import pg from 'pg'

const { Pool } = pg

export interface TenantContext {
  tenantId: string
  pool: pg.Pool
  scope?: { role: string; storeCode?: string; region?: string } | null
}

export const tenantContextStorage = new AsyncLocalStorage<TenantContext>()

const poolCache = new Map<string, { pool: pg.Pool; lastUsed: number }>()
const IDLE_TIMEOUT = 10 * 60 * 1000

export function getTenantPool(config: {
  tenantId: string
  dbHost: string
  dbPort: number
  dbName: string
  dbUser: string
  dbPassword?: string
}): pg.Pool {
  const key = config.tenantId
  const cached = poolCache.get(key)
  if (cached) {
    cached.lastUsed = Date.now()
    return cached.pool
  }
  const poolConfig: any = {
    host: config.dbHost,
    port: config.dbPort,
    database: config.dbName,
    user: config.dbUser,
    max: 5,
    idleTimeoutMillis: 30000,
  }
  if (config.dbPassword) {
    poolConfig.password = config.dbPassword
  }
  const pool = new Pool(poolConfig)
  pool.on('error', (err) => {
    console.error(`Tenant pool [${key}] error:`, err)
    closeTenantPool(key)
  })
  poolCache.set(key, { pool, lastUsed: Date.now() })
  return pool
}

export function closeTenantPool(tenantId: string) {
  const cached = poolCache.get(tenantId)
  if (cached) {
    cached.pool.end()
    poolCache.delete(tenantId)
  }
}

export function closeAllTenantPools() {
  for (const [, cached] of poolCache) {
    cached.pool.end()
  }
  poolCache.clear()
}

setInterval(() => {
  const now = Date.now()
  for (const [id, cached] of poolCache) {
    if (now - cached.lastUsed > IDLE_TIMEOUT) {
      console.log(`Closing idle tenant pool [${id}]`)
      closeTenantPool(id)
    }
  }
}, 5 * 60 * 1000)
