import { aql } from 'arangojs'
import { chain, get } from 'lodash'
import { hasReadAccess } from '../../../../utils/auth/access'
import { verifyIdToken } from '../../../../utils/auth/firebaseAdmin'
import { rg2cy } from '../../../../utils/cyHelpers'

const { db, rg } = require('../../../../utils/arangoWrapper')

const MindMapAPI = async (req, res) => {
  const { token } = req.headers

  try {
    const claims = await verifyIdToken(token)
    const ukey = claims.uid
    const userId = `users/${ukey}`
    const { key, timestamp } = req.query
    const id = `mindmaps/${key}`

    let mindmap, query, cursor, edgeStartIdx

    switch (req.method) {
      case 'GET':
        if (timestamp && (await hasReadAccess(id, userId))) {
          const response = await rg.post(
            '/history/traverse',
            {
              edges: { access: 'outbound', links: 'outbound' },
            },
            {
              timestamp,
              svid: id,
              minDepth: 0,
              maxDepth: Number.MAX_SAFE_INTEGER,
              uniqueVertices: 'global',
              returnPaths: false,
            }
          )

          mindmap = response.body
          edgeStartIdx = 0
        } else {
          query = aql`
            for v, e, p in 1..${Number.MAX_SAFE_INTEGER}
            any ${userId}
            graph 'mindmaps'
            
            options { uniqueVertices: 'global', bfs: true }
            
            filter p.vertices[1]._id == ${id}
            
            collect aggregate vertices = unique(v), edges = unique(e)
            
            return { vertices, edges }
          `
          cursor = await db.query(query)
          mindmap = await cursor.next()
          edgeStartIdx = 1
        }

        if (get(mindmap, ['vertices', 'length'])) {
          const meta = mindmap.vertices[0]
          const access = mindmap.edges[0]
          const vertices = [],
            edges = []

          for (let i = 0; i < mindmap.vertices.length; i++) {
            vertices.push(mindmap.vertices[i])
          }
          for (let i = edgeStartIdx; i < mindmap.edges.length; i++) {
            edges.push(mindmap.edges[i])
          }

          const userIds = chain(vertices)
            .flatMap((v) => [v.createdBy, v.lastUpdatedBy])
            .compact()
            .uniq()
            .value()
          query = aql`
            for u in users
            filter u._id in ${userIds}
            
            return keep(u, '_id', 'displayName', 'email')
          `
          cursor = await db.query(query)
          const users = await cursor.all()

          for (const v of vertices) {
            for (const field of ['createdBy', 'lastUpdatedBy']) {
              if (v[field]) {
                const user = users.find((u) => u._id === v[field])
                v[field] = user.displayName || user.email
              }
            }
          }

          const result = {
            meta,
            access,
            elements: rg2cy([
              {
                type: 'vertex',
                nodes: vertices,
              },
              {
                type: 'edge',
                nodes: edges,
              },
            ]),
          }

          return res.status(200).json(result)
        }

        return res.status(401).json({ message: 'Access Denied.' })

      default:
        return res.status(405).json({ message: 'Method Not Allowed' })
    }
  } catch (error) {
    console.error(error.message, error.stack)
    return res.status(401).json({ message: 'Access Denied.' })
  }
}

export default MindMapAPI