text: const server = require('../../../test-utils/index')
  const chai = require('chai')
  const expect = chai.expect
  chai.use(require('chai-http'))
  const secretariatHeader = require('./mockObjects.cve-id').secretariatHeader
  const owningOrgHeader = require('./mockObjects.cve-id').owningOrgHeader
  const orgHeader = require('./mockObjects.cve-id').orgHeader
  const secretariatOrg = require('./mockObjects.cve-id').secretariatOrg
  const secretariatUser = require('./mockObjects.cve-id').secretariatUser
  const owningOrg = require('./mockObjects.cve-id').owningOrg
  const owningOrgUser = require('./mockObjects.cve-id').owningOrgUser
  const org = require('./mockObjects.cve-id').org
  const orgUser = require('./mockObjects.cve-id').orgUser
  const nonExistentOrg = require('./mockObjects.cve-id').nonExistentOrg
  const cvePublic = require('./mockObjects.cve-id').cvePublic
  const cveReserved = require('./mockObjects.cve-id').cveReserved
  const cveReject = require('./mockObjects.cve-id').cveReject
  const CveId = require('../../../src/model/cve-id')
  const User = require('../../../src/model/user')
  const Org = require('../../../src/model/org')
  const cveId = 'CVE-2017-4024'
  const cveIdYear = cveId.substring(4, 8)
  const nonExistentCveId = 'CVE-2017-35437'
  let timestampBeforeCreation
  let timestampAfterCreation
  let timestampCreated
  
  describe('Test ID Allocator', () => {
    before(async () => {
      await CveId.findOneAndUpdate()
        .byCveId(cveId)
        .updateOne(cveReserved)
        .setOptions({ upsert: true })
  
      await CveId.findOneAndRemove().byCveId(nonExistentCveId)
  
      await User.findOneAndUpdate()
        .byUserNameAndCnaShortName(secretariatUser.username, secretariatUser.cna_short_name)
        .updateOne(secretariatUser)
        .setOptions({ upsert: true })
  
      await User.findOneAndUpdate()
        .byUserNameAndCnaShortName(owningOrgUser.username, owningOrgUser.cna_short_name)
        .updateOne(owningOrgUser)
        .setOptions({ upsert: true })
  
      await User.findOneAndUpdate()
        .byUserNameAndCnaShortName(orgUser.username, orgUser.cna_short_name)
        .updateOne(orgUser)
        .setOptions({ upsert: true })
  
      await Org.findOneAndUpdate()
        .byShortName(secretariatOrg.short_name)
        .updateOne(secretariatOrg)
        .setOptions({ upsert: true })
  
      await Org.findOneAndUpdate()
        .byShortName(owningOrg.short_name)
        .updateOne(owningOrg)
        .setOptions({ upsert: true })
  
      await Org.findOneAndUpdate()
        .byShortName(org.short_name)
        .updateOne(org)
        .setOptions({ upsert: true })
  
      await Org.findOneAndRemove().byShortName(nonExistentOrg.short_name)
    })
  
    context('Getting CVE ID specs from a Cve document', () => {
      it('Cve does not exist', (done) => {
        // perform the request to the api
        chai.request(server)
          .get('/api/test/cve-id/' + nonExistentCveId)
          .set(secretariatHeader)
          .end((err, res) => {
            if (err) {
              done(err)
            }
  
            // assert expected response
            expect(res).to.have.status(404)
            expect(res).to.have.property('body').and.to.be.a('object')
            expect(res.body).to.have.property('message').and.to.be.a('string')
            expect(res.body.message).to.equal(nonExistentCveId + ' not found')
            done()
          })
      })
  
      it('Requester is not the owning org or the secretariat and the cve is RESERVED', (done) => {
        // perform the request to the api
        chai.request(server)
          .get('/api/test/cve-id/' + cveId)
          .set(orgHeader) // not the owning cna or secretariat
          .end((err, res) => {
            if (err) {
              done(err)
            }
  
            // assert expected response
            expect(res).to.have.status(404)
            expect(res).to.have.property('body').and.to.be.a('object')
            expect(res.body).to.have.property('message').and.to.be.a('string')
            expect(res.body.message).to.equal(cveId + ' not found')
            done()
          })
      })
  
      it('Requester is not the owning org or the secretariat and the cve is not RESERVED', (done) => {
        CveId.findOneAndReplace()
          .byCveId(cveId)
          .replaceOne(cveReject)
          .exec((err) => {
            if (err) {
              done(err)
            }
  
            // perform the request to the api
            chai.request(server)
              .get('/api/test/cve-id/' + cveId)
              .set(orgHeader) // not the owning cna or secretariat
              .end((err, res) => {
                if (err) {
                  done(err)
                }
  
                // assert expected response
                expect(res).to.have.status(200)
                expect(res).to.have.property('body').and.to.be.a('object')
                expect(res.body).to.have.property('cve_id').and.to.equal(cveId)
                expect(res.body).to.have.property('state').and.to.equal('REJECT')
                done()
              })
          })
      })
  
      it('Requester is the owning cna', (done) => {
        CveId.findOneAndReplace()
          .byCveId(cveId)
          .replaceOne(cvePublic)
          .exec((err) => {
            if (err) {
              done(err)
            }
  
            // perform the request to the api
            chai.request(server)
              .get('/api/test/cve-id/' + cveId)
              .set(owningOrgHeader) // the owning cna
              .end((err, res) => {
                if (err) {
                  done(err)
                }
  
                // assert expected response
                expect(res).to.have.status(200)
                expect(res).to.have.property('body').and.to.be.a('object')
                expect(res.body).to.have.property('cve_id').and.to.equal(cveId)
                expect(res.body).to.have.property('state').and.to.equal('PUBLIC')
                done()
              })
          })
      })
  
      it('Requester is the secretariat', (done) => {
        // perform the request to the api
        chai.request(server)
          .get('/api/test/cve-id/' + cveId)
          .set(secretariatHeader) // the secretariat
          .end((err, res) => {
            if (err) {
              done(err)
            }
  
            // assert expected response
            expect(res).to.have.status(200)
            expect(res).to.have.property('body').and.to.be.a('object')
            expect(res.body).to.have.property('cve_id').and.to.equal(cveId)
            expect(res.body).to.have.property('state').and.to.equal('PUBLIC')
            done()
          })
      })
    })
  
    context('Getting a filtered cve record', () => {
      it('Invalid query parameter is provided', (done) => {
        // perform the request to the api
        chai.request(server)
          .get('/api/test/cve-id?id=CVE-2010-1234&year=2010')
          .set(owningOrg)
          .end((err, res) => {
            if (err) {
              done(err)
            }
  
            // assert expected response
            expect(res).to.have.status(400)
            expect(res).to.have.property('body').and.to.be.a('object')
            expect(res.body).to.have.property('message').and.to.be.a('string')
            expect(res.body.message).to.equal('Invalid query parameter \'id\'')
            done()
          })
      })
  
      it('Multiple "time_created.gt" query parameters are provided', (done) => {
        // perform the request to the api
        chai.request(server)
          .get('/api/test/cve-id?time_created.gt=\'2020-06-24T23:12:46\'&time_created.gt=\'2020-07-03\'')
          .set(owningOrg)
          .end((err, res) => {
            if (err) {
              done(err)
            }
  
            // assert expected response
            expect(res).to.have.status(400)
            expect(res).to.have.property('body').and.to.be.a('object')
            expect(res.body).to.have.property('message').and.to.be.a('string')
            expect(res.body.message).to.equal('Only one query parameter of \'time_created.gt\' is allowed.')
            done()
          })
      })
  
      it('Multiple "time_created.lt" query parameters are provided', (done) => {
        // perform the request to the api
        chai.request(server)
          .get('/api/test/cve-id?time_created.lt=\'2020-06-24T23:12:46\'&time_created.lt=\'2020-07-03\'')
          .set(owningOrg)
          .end((err, res) => {
            if (err) {
              done(err)
            }
  
            // assert expected response
            expect(res).to.have.status(400)
            expect(res).to.have.property('body').and.to.be.a('object')
            expect(res.body).to.have.property('message').and.to.be.a('string')
            expect(res.body.message).to.equal('Only one query parameter of \'time_created.lt\' is allowed.')
            done()
          })
      })
  
      it('Unsupported timestamp in query parameter is provided', (done) => {
        // perform the request to the api
        chai.request(server)
          .get('/api/test/cve-id?time_created.gt=\'2020-06-24T23:12\'')
          .set(owningOrg)
          .end((err, res) => {
            if (err) {
              done(err)
            }
  
            // assert expected response
            expect(res).to.have.status(400)
            expect(res).to.have.property('body').and.to.be.a('object')
            expect(res.body).to.have.property('message').and.to.be.a('string')
            expect(res.body.message).to.equal('Timestamp query parameter only supports formats "YYYY-MM-DDTHH:mm:ss" or "YYYY-MM-DD"')
            done()
          })
      })
  
      it('No CVEs were found for the specified query parameters', (done) => {
        // perform the request to the api
        chai.request(server)
          .get('/api/test/cve-id?state=public&cve_id_year=2010')
          .set(owningOrg)
          .end((err, res) => {
            if (err) {
              done(err)
            }
  
            // assert expected response
            expect(res).to.have.status(404)
            expect(res).to.have.property('body').and.to.be.a('object')
            expect(res.body).to.have.property('message').and.to.be.a('string')
            expect(res.body.message).to.equal('No CVE IDs were found for the specified query parameters.')
            done()
          })
      })
  
      it('The "state" query parameter is provided', (done) => {
        CveId.findOneAndUpdate()
          .byCveId(cveId)
          .updateOne(cvePublic)
          .exec((err) => {
            if (err) {
              done(err)
            }
  
            // perform the request to the api
            chai.request(server)
              .get('/api/test/cve-id?state=public')
              .set(owningOrgHeader)
              .end((err, res) => {
                if (err) {
                  done(err)
                }
  
                // assert expected response
                expect(res).to.have.status(200)
                expect(res).to.have.property('body').and.to.be.an('array').and.to.have.lengthOf(1)
                expect(res.body[0]).to.have.property('cve_id').and.to.equal(cveId)
                expect(res.body[0]).to.have.property('state').and.to.equal('PUBLIC')
                timestampCreated = res.body[0].time.created
                done()
              })
          })
      })
  
      it('The "cve_id_year" query parameter is provided', (done) => {
        // perform the request to the api
        chai.request(server)
          .get('/api/test/cve-id?cve_id_year=' + cveIdYear)
          .set(owningOrgHeader)
          .end((err, res) => {
            if (err) {
              done(err)
            }
  
            // assert expected response
            expect(res).to.have.status(200)
            expect(res).to.have.property('body').and.to.be.an('array').and.to.have.lengthOf(1)
            expect(res.body[0]).to.have.property('cve_id').and.to.equal(cveId)
            expect(res.body[0]).to.have.property('cve_year').and.to.equal('2017')
            done()
          })
      })
  
      it('The "time_created.lt" query parameter is provided', (done) => {
        const date = new Date(timestampCreated.substring(0, 10))
        let day = date.getDate().toString(10)
        let month = date.getMonth().toString(10)
        const year = date.getFullYear()
  
        if (day.length < 2) {
          day = `0${day}`
        }
  
        if (month.length < 2) {
          month = `0${month}`
        }
  
        const yearBefore = (year - 1).toString(10)
        const yearAfter = (year + 1).toString(10)
  
        timestampBeforeCreation = yearBefore + '-' + month + '-' + day
        timestampAfterCreation = yearAfter + '-' + month + '-' + day
  
        // perform the request to the api
        chai.request(server)
          .get('/api/test/cve-id?time_created.lt=' + timestampAfterCreation)
          .set(owningOrgHeader)
          .end((err, res) => {
            if (err) {
              done(err)
            }
  
            // assert expected response
            expect(res).to.have.status(200)
            expect(res).to.have.property('body').and.to.be.an('array').and.to.have.lengthOf(1)
            expect(res.body[0]).to.have.property('cve_id').and.to.equal(cveId)
            expect(res.body[0].time).to.have.nested.property('created').and.to.equal(timestampCreated)
            done()
          })
      })
  
      it('The "time_created.gt" query parameter is provided', (done) => {
        // perform the request to the api
        chai.request(server)
          .get('/api/test/cve-id?time_created.gt=' + timestampBeforeCreation)
          .set(owningOrgHeader)
          .end((err, res) => {
            if (err) {
              done(err)
            }
  
            // assert expected response
            expect(res).to.have.status(200)
            expect(res).to.have.property('body').and.to.be.an('array').and.to.have.lengthOf(1)
            expect(res.body[0]).to.have.property('cve_id').and.to.equal(cveId)
            expect(res.body[0].time).to.have.nested.property('created').and.to.equal(timestampCreated)
            done()
          })
      })
  
      it('All the query parameters are provided', (done) => {
        // perform the request to the api
        chai.request(server)
          .get('/api/test/cve-id?state=public&cve_id_year=' + cveIdYear + '&time_created.gt=' + timestampBeforeCreation + '&time_created.lt=' + timestampAfterCreation)
          .set(owningOrgHeader)
          .end((err, res) => {
            if (err) {
              done(err)
            }
  
            // assert expected response
            expect(res).to.have.status(200)
            expect(res).to.have.property('body').and.to.be.an('array').and.to.have.lengthOf(1)
            expect(res.body[0]).to.have.property('cve_id').and.to.equal(cveId)
            expect(res.body[0]).to.have.property('cve_year').and.to.equal('2017')
            expect(res.body[0].time).to.have.nested.property('created').and.to.equal(timestampCreated)
            expect(res.body[0]).to.have.property('state').and.to.equal('PUBLIC')
            done()
          })
      })
  
      it('No query parameters are provided', (done) => {
        // perform the request to the api
        chai.request(server)
          .get('/api/test/cve-id')
          .set(owningOrgHeader)
          .end((err, res) => {
            if (err) {
              done(err)
            }
  
            // assert expected response
            expect(res).to.have.status(200)
            expect(res).to.have.property('body').and.to.be.an('array').and.to.have.lengthOf(1)
            expect(res.body[0]).to.have.property('cve_id').and.to.equal(cveId)
            done()
          })
      })
    })
  
    context('Modifying a cve', () => {
      it('Requestor is not the secretariat', (done) => {
        // perform the request to the api
        chai.request(server)
          .post('/api/test/cve-id/' + cveId)
          .set(owningOrgHeader) // the owning cna
          .end((err, res) => {
            if (err) {
              done(err)
            }
  
            // assert expected response
            expect(res).to.have.status(403)
            expect(res).to.have.property('body').and.to.be.a('object')
            expect(res.body).to.have.property('message').and.to.be.a('string')
            expect(res.body.message).to.equal(cveId + ' cannot be updated by other than the secretariat.')
            done()
          })
      })
  
      it('CVE ID does not exist', (done) => {
        // perform the request to the api
        chai.request(server)
          .post('/api/test/cve-id/' + nonExistentCveId + '?cna=' + secretariatOrg.short_name + '&state=public')
          .set(secretariatHeader) // the secretariat
          .end((err, res) => {
            if (err) {
              done(err)
            }
  
            // assert expected response
            expect(res).to.have.status(404)
            expect(res).to.have.property('body').and.to.be.a('object')
            expect(res.body).to.have.property('message').and.to.be.a('string')
            expect(res.body.message).to.equal(nonExistentCveId + ' not found')
            done()
          })
      })
  
      it('Cna query parameter is provided but new cna does not exist', (done) => {
        // perform the request to the api
        chai.request(server)
          .post('/api/test/cve-id/' + cveId + '?cna=' + nonExistentOrg.short_name)
          .set(secretariatHeader) // the secretariat
          .end((err, res) => {
            if (err) {
              done(err)
            }
  
            // assert expected response
            expect(res).to.have.status(404)
            expect(res).to.have.property('body').and.to.be.a('object')
            expect(res.body).to.have.property('message').and.to.be.a('string')
            expect(res.body.message).to.equal(nonExistentOrg.short_name + ' CNA does not exist.')
            done()
          })
      })
  
      it('State query parameter is provided but state is RESERVED', (done) => {
        // perform the request to the api
        chai.request(server)
          .post('/api/test/cve-id/' + cveId + '?state=RESERVED')
          .set(secretariatHeader) // the secretariat
          .end((err, res) => {
            if (err) {
              done(err)
            }
  
            // assert expected response
            expect(res).to.have.status(400)
            expect(res).to.have.property('body').and.to.be.a('object')
            expect(res.body).to.have.property('message').and.to.be.a('string')
            expect(res.body.message).to.equal('Cannot change the state to RESERVED.')
            done()
          })
      })
  
      it('Cve is reasigned to another org and state is modified', (done) => {
        // perform the request to the api
        chai.request(server)
          .post('/api/test/cve-id/' + cveId + '?cna=' + org.short_name + '&state=reject')
          .set(secretariatHeader) // the secretariat
          .end((err, res) => {
            if (err) {
              done(err)
            }
  
            // assert expected response
            expect(res).to.have.status(200)
            expect(res).to.have.property('body').and.to.be.a('object')
            expect(res.body).to.have.property('message').and.to.be.a('string')
            expect(res.body.message).to.equal(cveId + ' was successfully updated.')
            expect(res.body).to.have.property('updated').and.to.be.a('object')
            expect(res.body.updated).to.have.property('owning_cna').and.to.equal(org.short_name)
            expect(res.body.updated).to.have.property('state').and.to.equal('REJECT')
            done()
          })
      })
  
      it('No query parameters are provided', (done) => {
        // perform the request to the api
        chai.request(server)
          .post('/api/test/cve-id/' + cveId)
          .set(secretariatHeader) // the secretariat
          .end((err, res) => {
            if (err) {
              done(err)
            }
  
            // assert expected response
            expect(res).to.have.status(200)
            expect(res).to.have.property('body').and.to.be.a('object')
            expect(res.body).to.have.property('message').and.to.be.a('string')
            expect(res.body.message).to.equal(cveId + ' was successfully updated.')
            expect(res.body).to.have.property('updated').and.to.be.a('object')
            expect(res.body.updated).to.have.property('owning_cna').and.to.equal(org.short_name)
            expect(res.body.updated).to.have.property('state').and.to.equal('REJECT')
            done()
          })
      })
    })
  
    after(async () => {
      await CveId.findOneAndRemove().byCveId(cveId)
      await CveId.findOneAndRemove().byCveId(nonExistentCveId)
      await User.findOneAndRemove().byUserNameAndCnaShortName(secretariatUser.username, secretariatUser.cna_short_name)
      await User.findOneAndRemove().byUserNameAndCnaShortName(owningOrgUser.username, owningOrgUser.cna_short_name)
      await User.findOneAndRemove().byUserNameAndCnaShortName(orgUser.username, orgUser.cna_short_name)
      await Org.findOneAndRemove().byShortName(secretariatOrg.short_name)
      await Org.findOneAndRemove().byShortName(owningOrg.short_name)
      await Org.findOneAndRemove().byShortName(org.short_name)
      await Org.findOneAndRemove().byShortName(nonExistentOrg.short_name)
    })
  })
  