'use strict'
const cfg = require('./config')
const { log, json, parseBody } = require('./helpers')

let routrPool = null, identityPool = null

function getPool (connStr, label) {
  const { Pool } = require('pg')
  const pool = new Pool({ connectionString: connStr, max: 3 })
  pool.on('error', e => log(`${label} DB pool error:`, e.message))
  return pool
}

function getRoutrPool () { return routrPool || (routrPool = getPool(cfg.ROUTR_DB_URL, 'Routr')) }
function getIdentityPool () { return identityPool || (identityPool = getPool(cfg.FNIDENTITY_DB_URL, 'Identity')) }

const ROUTR_TABLES = { trunks: 'trunks', agents: 'agents', credentials: 'credentials', numbers: 'numbers', domains: 'domains', acls: 'access_control_lists', peers: 'peers' }
const IDENTITY_TABLES = { workspaces: 'workspaces', users: 'users' }

async function handle (req, res, method, path, url) {
  try {
    const parts = path.replace('/telephony/', '').split('/').filter(Boolean)
    const resource = parts[0], ref = parts[1] || null

    if (resource === 'overview' && method === 'GET') {
      const rPool = getRoutrPool(), iPool = getIdentityPool()
      const [trunks, agents, creds, numbers, domains, peers, workspaces] = await Promise.all([
        rPool.query('SELECT COUNT(*) FROM trunks'),
        rPool.query('SELECT COUNT(*) FROM agents'),
        rPool.query('SELECT COUNT(*) FROM credentials'),
        rPool.query('SELECT COUNT(*) FROM numbers'),
        rPool.query('SELECT COUNT(*) FROM domains'),
        rPool.query('SELECT COUNT(*) FROM peers'),
        iPool.query('SELECT COUNT(*) FROM workspaces'),
      ])
      return json(res, 200, {
        trunks: +trunks.rows[0].count, agents: +agents.rows[0].count,
        credentials: +creds.rows[0].count, numbers: +numbers.rows[0].count,
        domains: +domains.rows[0].count, peers: +peers.rows[0].count,
        workspaces: +workspaces.rows[0].count,
      })
    }

    const isIdentity = !!IDENTITY_TABLES[resource]
    const tableName = IDENTITY_TABLES[resource] || ROUTR_TABLES[resource]
    if (!tableName) {
      return json(res, 404, { error: `Unknown resource: ${resource}. Available: overview, ${[...Object.keys(ROUTR_TABLES), ...Object.keys(IDENTITY_TABLES)].join(', ')}` })
    }
    const pool = isIdentity ? getIdentityPool() : getRoutrPool()

    if (method === 'GET' && !ref) {
      const limit = parseInt(url.searchParams.get('limit') || '100', 10)
      const offset = parseInt(url.searchParams.get('offset') || '0', 10)
      const result = await pool.query(`SELECT * FROM ${tableName} ORDER BY created_at DESC LIMIT $1 OFFSET $2`, [limit, offset])
      const count = await pool.query(`SELECT COUNT(*) FROM ${tableName}`)
      return json(res, 200, { items: result.rows, total: +count.rows[0].count })
    }

    if (method === 'GET' && ref) {
      const result = await pool.query(`SELECT * FROM ${tableName} WHERE ref = $1`, [ref])
      return result.rows.length ? json(res, 200, result.rows[0]) : json(res, 404, { error: 'Not found' })
    }

    if (method === 'POST' && !ref) {
      const body = await parseBody(req)
      if (!body.ref) body.ref = require('crypto').randomUUID()
      if (!body.api_version) body.api_version = 'v2'
      if (!body.created_at) body.created_at = new Date()
      if (!body.updated_at) body.updated_at = new Date()
      const keys = Object.keys(body), vals = Object.values(body)
      if (keys.some(k => !/^[a-z_][a-z0-9_]*$/i.test(k))) return json(res, 400, { error: 'Invalid field name' }) // anti-SQLi : clés=colonnes, on rejette tout identifiant non standard
      const result = await pool.query(`INSERT INTO ${tableName} (${keys.join(', ')}) VALUES (${keys.map((_, i) => `$${i + 1}`).join(', ')}) RETURNING *`, vals)
      log(`Telephony: created ${resource}/${result.rows[0].ref}`)
      return json(res, 201, result.rows[0])
    }

    if (method === 'PUT' && ref) {
      const body = await parseBody(req)
      body.updated_at = new Date(); delete body.ref; delete body.created_at
      const keys = Object.keys(body), vals = Object.values(body)
      if (keys.some(k => !/^[a-z_][a-z0-9_]*$/i.test(k))) return json(res, 400, { error: 'Invalid field name' }) // anti-SQLi : clés=colonnes
      vals.push(ref)
      const result = await pool.query(`UPDATE ${tableName} SET ${keys.map((k, i) => `${k} = $${i + 1}`).join(', ')} WHERE ref = $${vals.length} RETURNING *`, vals)
      if (!result.rows.length) return json(res, 404, { error: 'Not found' })
      log(`Telephony: updated ${resource}/${ref}`)
      return json(res, 200, result.rows[0])
    }

    if (method === 'DELETE' && ref) {
      const result = await pool.query(`DELETE FROM ${tableName} WHERE ref = $1 RETURNING ref`, [ref])
      if (!result.rows.length) return json(res, 404, { error: 'Not found' })
      log(`Telephony: deleted ${resource}/${ref}`)
      return json(res, 200, { ok: true, deleted: ref })
    }

    return json(res, 405, { error: 'Method not allowed' })
  } catch (e) {
    log('Telephony error:', e.message)
    return json(res, 500, { error: e.message })
  }
}

module.exports = { handle }
