nock = require 'nock'
chai = require 'chai'
sinon = require 'sinon'
sinonChai = require 'sinon-chai'
expect = chai.expect
proxyquire = require('proxyquire').noCallThru()

chai.use sinonChai
chai.should()


User = proxyquire('../../../models/User', {
  '../boot/redis': {
    getClient: () => {}
  }
})
revoke = proxyquire('../../../oidc/revoke', {
  '../models/User': User
})


describe 'Revoke third party access token', ->
  { req, res, next, err } = {}


  describe 'with unknown provider', ->
    before ->
      req =
        params:
          provider: 'unknown'
      res = {}
      next = sinon.spy()

      revoke req, res, next

    it 'should provide an error', ->
      next.should.have.been.calledWith sinon.match({
        message: 'invalid_request'
        description: 'Unknown provider'
      })


  describe 'with undefined revoke endpoint', ->
    before ->
      req =
        params:
          provider: 'oauth2test'
      res = {}
      next = sinon.spy()

      revoke req, res, next

    it 'should provide an error', ->
      next.should.have.been.calledWith sinon.match({
        message: 'invalid_request'
        description: 'Undefined revoke endpoint'
      })


  describe 'with unknown user', ->
    before ->
      sinon.stub(User, 'get').callsArgWith(1, null, null)
      req =
        claims:
          sub: 'unknown'
        params:
          provider: 'google'
      res = {}
      next = sinon.spy()

      revoke req, res, next

    after ->
      User.get.restore()

    it 'should provide an error', ->
      next.should.have.been.calledWith sinon.match({
        message: 'invalid_request'
        description: 'Unknown user'
      })


  describe 'with no provider for this user', ->
    before ->
      sinon.stub(User, 'get').callsArgWith(1, null, { providers: {} })
      req =
        claims:
          sub: 'uuid'
        params:
          provider: 'google'
      res = {}
      next = sinon.spy()

      revoke req, res, next

    after ->
      User.get.restore()

    it 'should provide an error', ->
      next.should.have.been.calledWith sinon.match({
        message: 'invalid_request'
        description: 'No provider for this user'
      })


  describe 'with error response from provider', ->
    before ->
      sinon.stub(User, 'get').callsArgWith(1, null, {
        providers:
          google:
            auth:
              access_token: 't0k3n'
      })
      req =
        claims:
          sub: 'uuid'
        params:
          provider: 'google'
      res =
        json: sinon.spy()
      next = sinon.spy()

      scope = nock('https://accounts.google.com')
        .get('/o/oauth2/revoke')
        .reply(400, 'meh')

      revoke req, res, next

    after ->
      User.get.restore()


    it 'should not provide an error', ->
      next.should.not.have.been.called

    it 'should respond ...'


  describe 'with ok response from provider', ->
    before ->
      sinon.stub(User, 'get').callsArgWith(1, null, {
        providers:
          google:
            auth:
              access_token: 't0k3n'
      })
      req =
        claims:
          sub: 'uuid'
        params:
          provider: 'google'
      res =
        json: sinon.spy()
      next = sinon.spy()

      scope = nock('https://accounts.google.com')
        .get('/o/oauth2/revoke')
        .reply(200, 'meh')

      revoke req, res, next

    after ->
      User.get.restore()

    it 'should not provide an error', ->
      next.should.not.have.been.called

    it 'should respond ...'


