const fs = require('fs').promises
const keystone = require('keystone')
const recast = require('recast')


const Types = keystone.Field.Types
const CoreEntity = new keystone.List('CoreEntity')

const generateModel = require('../lib/core/entity/api/generate/model').default

CoreEntity.add({
  name: { type: String, required: true, index: true, },

  rebuild: { type: Types.Boolean, },
})

CoreEntity.relationship({ path: 'fields', ref: 'CoreField', refPath: 'entity' })

const populateRelated = (model, fieldList) => new Promise((resolve) => {
  keystone.populateRelated(model, fieldList, () => {
    resolve(model)
  })
})

CoreEntity.schema.pre('save', async function (next) {
  const nameParse = this.name.match(/[A-Z][a-zA-Z0-9]+/gm)

  if (nameParse) {
    this.name = nameParse[0]
  } else {
    return next(new Error(`Name validation error (/[A-Z][a-z]+/gm)`))
  }

  if (this.rebuild) {
    const ast = generateModel(
      await populateRelated(this, ['fields'])
    )

    const code = recast.print(
      ast,
      { tabWidth: 2 }
    ).code

    try {
      await fs.writeFile(`./models/${ this.name }.js`, code, 'utf8')
    } catch (err) {
      console.error(err)

      return next(new Error(`Cannot write model file '${ this.name }'`))
    }

    this.rebuild = false
  }

  return next()
})

CoreEntity.defaultColumns = 'name'
CoreEntity.register()