const chai = require('chai')
const sinon = require('sinon')
const { faker } = require('@faker-js/faker')
const expect = chai.expect
const _ = require('lodash')

const cveIdController = require('../../../src/controller/cve-id.controller/cve-id.controller.js')
const OrgRepository = require('../../../src/repositories/orgRepository.js')
const CveIdRepository = require('../../../src/repositories/cveIdRepository.js')
const UserRepository = require('../../../src/repositories/userRepository.js')

const orgUUID = faker.datatype.uuid()
const orgUUID2 = faker.datatype.uuid()
const userUUID = faker.datatype.uuid()

const stubOrg = {
  short_name: 'testOrg',
  name: 'test_org',
  UUID: orgUUID,
  authority: {
    active_roles: [
      'CNA',
      'Secretariat'
    ]
  }
}

const stubOrg2 = {
  short_name: 'testOrg2',
  name: 'test_org2',
  UUID: orgUUID2,
  authority: {
    active_roles: [
      'CNA'
    ]
  }
}

const stubUser = {
  username: 'testUser',
  org_UUID: orgUUID,
  UUID: userUUID
}

const stubCveId = {
  requested_by: {
    cna: orgUUID,
    user: userUUID
  },
  cve_id: 'CVE-2017-4024',
  cve_year: '2017',
  state: 'PUBLISHED',
  owning_cna: orgUUID2,
  reserved: '2023-05-17T16:57:35.698Z'
}

const builtQuery = {
  cve_year: 1999,
  state: 'RESERVED',
  'time.modified': {
    $gt: '2022-01-07T00:00:00.000Z',
    $lt: '2023-01-07T00:00:00.000Z'
  }
}
describe('Testing getFilteredCveId function', () => {
  let sandbox, status, json, res, next, getOrgRepository,
    orgRepo, getCveIdRepository, cveIdRepo,
    getUserRepository, userRepo, req, cveIdCopy

  // Stub out functions called in insertAdp and reset them for each test
  beforeEach(() => {
    sandbox = sinon.createSandbox()
    status = sandbox.stub()
    json = sandbox.spy()
    res = { json, status }
    next = sandbox.spy()
    status.returns(res)
    cveIdCopy = _.cloneDeep(stubCveId)

    const aggPagResp = {
      itemsList: [cveIdCopy],
      itemCount: 1,
      itemsPerPage: 1000,
      currentPage: 1,
      pageCount: 1,
      pagingCounter: 1,
      hasPrevPage: false,
      hasNextPage: false,
      prevPage: null,
      nextPage: null
    }

    orgRepo = new OrgRepository()
    getOrgRepository = sandbox.stub()
    getOrgRepository.returns(orgRepo)

    userRepo = new UserRepository()
    getUserRepository = sandbox.stub()
    getUserRepository.returns(userRepo)

    cveIdRepo = new CveIdRepository()
    getCveIdRepository = sandbox.stub()
    getCveIdRepository.returns(cveIdRepo)

    sandbox.stub(cveIdRepo, 'findOneByCveId').returns(cveIdCopy)
    sandbox.stub(cveIdRepo, 'aggregatePaginate').returns(aggPagResp)

    sandbox.stub(orgRepo, 'getOrgUUID').returns(stubOrg.UUID)
    sandbox.stub(orgRepo, 'isSecretariat').returns(true)
    sandbox.stub(orgRepo, 'isBulkDownload').returns(false)
    sandbox.stub(orgRepo, 'getAllOrgs').returns([stubOrg, stubOrg2])

    sandbox.stub(userRepo, 'getUserUUID').returns(stubUser.UUID)
    sandbox.stub(userRepo, 'getAllUsers').returns([stubUser])

    sandbox.spy(cveIdController, 'CVEID_GET_FILTER')

    req = {
      ctx: {
        org: stubOrg.short_name,
        uuid: stubOrg.UUID,
        query: {
          cve_id_year: 1999,
          'time_modified.gt': '2022-01-07T00:00:00.000Z',
          'time_modified.lt': '2023-01-07T00:00:00.000Z',
          state: 'RESERVED'
        },
        repositories: {
          getOrgRepository,
          getUserRepository,
          getCveIdRepository
        }
      }
    }
  })

  afterEach(() => {
    sandbox.restore()
  })
  it('Should have correctly built query', async () => {
    await cveIdController.CVEID_GET_FILTER(req, res, next)
    expect(cveIdRepo.aggregatePaginate.calledOnce)
    expect(cveIdRepo.aggregatePaginate.args[0][0][0].$match).to.deep.equal(builtQuery)
  })

  it('Should swap UUIDs for names in Cve-ids', async () => {
    await cveIdController.CVEID_GET_FILTER(req, res, next)
    expect(res.status.args[0][0]).to.equal(200)
    expect(res.json.args[0][0].cve_ids[0].owning_cna).to.equal(stubOrg2.short_name)
    expect(res.json.args[0][0].cve_ids[0].requested_by.cna).to.equal(stubOrg.short_name)
    expect(res.json.args[0][0].cve_ids[0].requested_by.user).to.equal(stubUser.username)
  })
})
