const { gql } = require('graphql-tag')
const stringifyCanon = require('canonical-json')
const { createHash } = require('crypto')
const Ots = require('opentimestamps')

const ITEM_OTS_FIELDS = gql`
  fragment ItemOTSFields on Item {
    parentId
    parentOtsHash
    title
    text
    url
  }`

function timestampItem ({ apollo, models }) {
  return async function ({ data: { id } }) {
    console.log('timestamping item', id)

    const { data: { item: { parentId, parentOtsHash, title, text, url } } } = await apollo.query({
      query: gql`
        ${ITEM_OTS_FIELDS}
        query Item {
          item(id: ${id}) {
            ...ItemOTSFields
          }
        }`
    })

    if (parentId && !parentOtsHash) {
      console.log('no parent hash available ... skipping')
      return
    }

    // SHA256 hash item using a canonical serialization format { parentHash, title, text, url }
    const itemString = stringifyCanon({ parentHash: parentOtsHash, title, text, url })
    const otsHash = createHash('sha256').update(itemString).digest()
    const detached = Ots.DetachedTimestampFile.fromHash(new Ots.Ops.OpSHA256(), otsHash)

    // timestamp it
    await Ots.stamp(detached)

    // get proof
    const otsFile = Buffer.from(detached.serializeToBytes())

    // store in item
    await models.item.update({ where: { id }, data: { otsHash: otsHash.toString('hex'), otsFile } })

    console.log('done timestamping item', id)
  }
}

module.exports = { timestampItem }