const cloud = require('wx-server-sdk')

cloud.init({ env: cloud.DYNAMIC_CURRENT_ENV })
const db = cloud.database()
const _ = db.command
const POST_LIKES_COLLECTION = 'postLikes'

function isCollectionMissing(error) {
  const text = String(error?.errMsg || error?.message || error || '')
  return (
    text.includes('collection not exist') ||
    text.includes('collection not exists') ||
    text.includes('collection is not exists') ||
    text.includes('DATABASE_COLLECTION_NOT_EXIST') ||
    text.includes('-502005')
  )
}

function isCollectionAlreadyExists(error) {
  const text = String(error?.errMsg || error?.message || error || '')
  return text.includes('collection already exists') || text.includes('DATABASE_COLLECTION_ALREADY_EXIST')
}

async function ensurePostLikesCollection() {
  if (typeof db.createCollection !== 'function') {
    throw new Error('postLikes collection does not exist')
  }

  try {
    await db.createCollection(POST_LIKES_COLLECTION)
  } catch (error) {
    if (!isCollectionAlreadyExists(error)) throw error
  }
}

async function getExistingLike(postId, openid) {
  try {
    return await db.collection(POST_LIKES_COLLECTION).where({ postId, openid }).limit(1).get()
  } catch (error) {
    if (!isCollectionMissing(error)) throw error
    await ensurePostLikesCollection()
    return { data: [] }
  }
}

exports.main = async event => {
  const { OPENID } = cloud.getWXContext()
  const { postId, liked } = event
  if (!OPENID) throw new Error('no openid in wx context')
  if (!postId) throw new Error('postId is required')

  const existed = await getExistingLike(postId, OPENID)
  const collection = db.collection(POST_LIKES_COLLECTION)
  let delta = 0

  if (liked && !existed.data.length) {
    await collection.add({ data: { postId, openid: OPENID, createdAt: Date.now() } })
    delta = 1
  }

  if (!liked && existed.data.length) {
    await collection.doc(existed.data[0]._id).remove()
    delta = -1
  }

  if (delta) {
    await db.collection('posts').doc(postId).update({ data: { 'counts.likes': _.inc(delta) } })
  }

  const post = await db.collection('posts').doc(postId).get()
  return { liked: Boolean(liked), likes: post.data.counts?.likes || 0 }
}
