text: const should = require('should');
  const sinon = require('sinon');
  const supertest = require('supertest');
  const localUtils = require('./utils');
  const testUtils = require('../../../../utils/index');
  const models = require('../../../../../core/server/models/index');
  const security = require('@tryghost/security');
  const settingsCache = require('../../../../../core/shared/settings-cache');
  const config = require('../../../../../core/shared/config/index');
  const mailService = require('../../../../../core/server/services/mail/index');
  const configUtils = require('../../../../utils/configUtils');
  
  let request;
  
  describe('Authentication API v2', function () {
      describe('Blog setup: default config', function () {
          before(async function () {
              await localUtils.startGhost({forceStart: true});
              request = supertest.agent(config.get('url'));
          });
  
          beforeEach(function () {
              sinon.stub(mailService.GhostMailer.prototype, 'send').resolves('Mail is disabled');
          });
  
          afterEach(function () {
              sinon.restore();
          });
  
          it('is setup? no', function () {
              return request
                  .get(localUtils.API.getApiQuery('authentication/setup'))
                  .set('Origin', config.get('url'))
                  .expect('Content-Type', /json/)
                  .expect(200)
                  .then((res) => {
                      res.body.setup[0].status.should.be.false();
                  });
          });
  
          it('complete setup', function () {
              return request
                  .post(localUtils.API.getApiQuery('authentication/setup'))
                  .set('Origin', config.get('url'))
                  .send({
                      setup: [{
                          name: 'test user',
                          email: 'test@example.com',
                          password: 'thisissupersafe',
                          blogTitle: 'a test blog'
                      }]
                  })
                  .expect('Content-Type', /json/)
                  .expect(201)
                  .then((res) => {
                      const jsonResponse = res.body;
                      should.exist(jsonResponse.users);
                      should.not.exist(jsonResponse.meta);
  
                      jsonResponse.users.should.have.length(1);
                      localUtils.API.checkResponse(jsonResponse.users[0], 'user');
  
                      const newUser = jsonResponse.users[0];
                      newUser.id.should.equal(testUtils.DataGenerator.Content.users[0].id);
                      newUser.name.should.equal('test user');
                      newUser.email.should.equal('test@example.com');
  
                      mailService.GhostMailer.prototype.send.called.should.be.true();
                      mailService.GhostMailer.prototype.send.args[0][0].to.should.equal('test@example.com');
                  });
          });
  
          it('is setup? yes', function () {
              return request
                  .get(localUtils.API.getApiQuery('authentication/setup'))
                  .set('Origin', config.get('url'))
                  .expect('Content-Type', /json/)
                  .expect(200)
                  .then((res) => {
                      res.body.setup[0].status.should.be.true();
                  });
          });
  
          it('complete setup again', function () {
              return request
                  .post(localUtils.API.getApiQuery('authentication/setup'))
                  .set('Origin', config.get('url'))
                  .send({
                      setup: [{
                          name: 'test user',
                          email: 'test-leo@example.com',
                          password: 'thisissupersafe',
                          blogTitle: 'a test blog'
                      }]
                  })
                  .expect('Content-Type', /json/)
                  .expect(403);
          });
  
          it('update setup', function () {
              return localUtils.doAuth(request)
                  .then(() => {
                      return request
                          .put(localUtils.API.getApiQuery('authentication/setup'))
                          .set('Origin', config.get('url'))
                          .send({
                              setup: [{
                                  name: 'test user edit',
                                  email: 'test-edit@example.com',
                                  password: 'thisissupersafe',
                                  blogTitle: 'a test blog'
                              }]
                          })
                          .expect('Content-Type', /json/)
                          .expect(200);
                  })
                  .then((res) => {
                      const jsonResponse = res.body;
                      should.exist(jsonResponse.users);
                      should.not.exist(jsonResponse.meta);
  
                      jsonResponse.users.should.have.length(1);
                      localUtils.API.checkResponse(jsonResponse.users[0], 'user');
  
                      const newUser = jsonResponse.users[0];
                      newUser.id.should.equal(testUtils.DataGenerator.Content.users[0].id);
                      newUser.name.should.equal('test user edit');
                      newUser.email.should.equal('test-edit@example.com');
                  });
          });
      });
  
      describe('Blog setup: custom config', function () {
          before(async function () {
              await localUtils.startGhost({forceStart: true});
              request = supertest.agent(config.get('url'));
          });
  
          beforeEach(function () {
              configUtils.set({
                  sendWelcomeEmail: false // Default value is false in pro
              });
              sinon.stub(mailService.GhostMailer.prototype, 'send').resolves('Mail is disabled');
          });
  
          afterEach(function () {
              configUtils.restore();
              sinon.restore();
          });
  
          it('is setup? no', function () {
              return request
                  .get(localUtils.API.getApiQuery('authentication/setup'))
                  .set('Origin', config.get('url'))
                  .expect('Content-Type', /json/)
                  .expect(200)
                  .then((res) => {
                      res.body.setup[0].status.should.be.false();
                  });
          });
  
          it('complete setup', function () {
              return request
                  .post(localUtils.API.getApiQuery('authentication/setup'))
                  .set('Origin', config.get('url'))
                  .send({
                      setup: [{
                          name: 'test user',
                          email: 'test@example.com',
                          password: 'thisissupersafe',
                          blogTitle: 'a test blog'
                      }]
                  })
                  .expect('Content-Type', /json/)
                  .expect(201)
                  .then((res) => {
                      const jsonResponse = res.body;
                      should.exist(jsonResponse.users);
                      should.not.exist(jsonResponse.meta);
  
                      jsonResponse.users.should.have.length(1);
                      localUtils.API.checkResponse(jsonResponse.users[0], 'user');
  
                      const newUser = jsonResponse.users[0];
                      newUser.id.should.equal(testUtils.DataGenerator.Content.users[0].id);
                      newUser.name.should.equal('test user');
                      newUser.email.should.equal('test@example.com');
  
                      mailService.GhostMailer.prototype.send.called.should.be.false();
                  });
          });
  
          it('is setup? yes', function () {
              return request
                  .get(localUtils.API.getApiQuery('authentication/setup'))
                  .set('Origin', config.get('url'))
                  .expect('Content-Type', /json/)
                  .expect(200)
                  .then((res) => {
                      res.body.setup[0].status.should.be.true();
                  });
          });
  
          it('complete setup again', function () {
              return request
                  .post(localUtils.API.getApiQuery('authentication/setup'))
                  .set('Origin', config.get('url'))
                  .send({
                      setup: [{
                          name: 'test user',
                          email: 'test-leo@example.com',
                          password: 'thisissupersafe',
                          blogTitle: 'a test blog'
                      }]
                  })
                  .expect('Content-Type', /json/)
                  .expect(403);
          });
  
          it('update setup', function () {
              return localUtils.doAuth(request)
                  .then(() => {
                      return request
                          .put(localUtils.API.getApiQuery('authentication/setup'))
                          .set('Origin', config.get('url'))
                          .send({
                              setup: [{
                                  name: 'test user edit',
                                  email: 'test-edit@example.com',
                                  password: 'thisissupersafe',
                                  blogTitle: 'a test blog'
                              }]
                          })
                          .expect('Content-Type', /json/)
                          .expect(200);
                  })
                  .then((res) => {
                      const jsonResponse = res.body;
                      should.exist(jsonResponse.users);
                      should.not.exist(jsonResponse.meta);
  
                      jsonResponse.users.should.have.length(1);
                      localUtils.API.checkResponse(jsonResponse.users[0], 'user');
  
                      const newUser = jsonResponse.users[0];
                      newUser.id.should.equal(testUtils.DataGenerator.Content.users[0].id);
                      newUser.name.should.equal('test user edit');
                      newUser.email.should.equal('test-edit@example.com');
                  });
          });
      });
  
      describe('Invitation', function () {
          before(function () {
              return localUtils.startGhost()
                  .then(function () {
                      request = supertest.agent(config.get('url'));
  
                      // simulates blog setup (initialises the owner)
                      return localUtils.doAuth(request, 'invites');
                  });
          });
  
          it('check invite with invalid email', function () {
              return request
                  .get(localUtils.API.getApiQuery('authentication/invitation?email=invalidemail'))
                  .set('Origin', config.get('url'))
                  .expect('Content-Type', /json/)
                  .expect(400);
          });
  
          it('check valid invite', function () {
              return request
                  .get(localUtils.API.getApiQuery(`authentication/invitation?email=${testUtils.DataGenerator.forKnex.invites[0].email}`))
                  .set('Origin', config.get('url'))
                  .expect('Content-Type', /json/)
                  .expect(200)
                  .then((res) => {
                      res.body.invitation[0].valid.should.equal(true);
                  });
          });
  
          it('check invalid invite', function () {
              return request
                  .get(localUtils.API.getApiQuery(`authentication/invitation?email=notinvited@example.org`))
                  .set('Origin', config.get('url'))
                  .expect('Content-Type', /json/)
                  .expect(200)
                  .then((res) => {
                      res.body.invitation[0].valid.should.equal(false);
                  });
          });
  
          it('try to accept without invite', function () {
              return request
                  .post(localUtils.API.getApiQuery('authentication/invitation'))
                  .set('Origin', config.get('url'))
                  .send({
                      invitation: [{
                          token: 'lul11111',
                          password: 'lel123456',
                          email: 'not-invited@example.org',
                          name: 'not invited'
                      }]
                  })
                  .expect('Content-Type', /json/)
                  .expect(404);
          });
  
          it('try to accept with invite', function () {
              return request
                  .post(localUtils.API.getApiQuery('authentication/invitation'))
                  .set('Origin', config.get('url'))
                  .send({
                      invitation: [{
                          token: testUtils.DataGenerator.forKnex.invites[0].token,
                          password: '12345678910',
                          email: testUtils.DataGenerator.forKnex.invites[0].email,
                          name: 'invited'
                      }]
                  })
                  .expect('Content-Type', /json/)
                  .expect(200)
                  .then((res) => {
                      res.body.invitation[0].message.should.equal('Invitation accepted.');
                  });
          });
      });
  
      describe('Password reset', function () {
          const user = testUtils.DataGenerator.forModel.users[0];
  
          before(function () {
              return localUtils.startGhost({forceStart: true})
                  .then(() => {
                      request = supertest.agent(config.get('url'));
                  })
                  .then(() => {
                      return localUtils.doAuth(request);
                  });
          });
  
          beforeEach(function () {
              sinon.stub(mailService.GhostMailer.prototype, 'send').resolves('Mail is disabled');
          });
  
          afterEach(function () {
              sinon.restore();
          });
  
          it('reset password', function (done) {
              models.User.getOwnerUser(testUtils.context.internal)
                  .then(function (ownerUser) {
                      const token = security.tokens.resetToken.generateHash({
                          expires: Date.now() + (1000 * 60),
                          email: user.email,
                          dbHash: settingsCache.get('db_hash'),
                          password: ownerUser.get('password')
                      });
  
                      request.put(localUtils.API.getApiQuery('authentication/passwordreset'))
                          .set('Origin', config.get('url'))
                          .set('Accept', 'application/json')
                          .send({
                              passwordreset: [{
                                  token: token,
                                  newPassword: 'thisissupersafe',
                                  ne2Password: 'thisissupersafe'
                              }]
                          })
                          .expect('Content-Type', /json/)
                          .expect('Cache-Control', testUtils.cacheRules.private)
                          .expect(200)
                          .end(function (err, res) {
                              if (err) {
                                  return done(err);
                              }
  
                              const jsonResponse = res.body;
                              should.exist(jsonResponse.passwordreset[0].message);
                              jsonResponse.passwordreset[0].message.should.equal('Password changed successfully.');
                              done();
                          });
                  })
                  .catch(done);
          });
  
          it('reset password: invalid token', function () {
              return request
                  .put(localUtils.API.getApiQuery('authentication/passwordreset'))
                  .set('Origin', config.get('url'))
                  .set('Accept', 'application/json')
                  .send({
                      passwordreset: [{
                          token: 'invalid',
                          newPassword: 'thisissupersafe',
                          ne2Password: 'thisissupersafe'
                      }]
                  })
                  .expect('Content-Type', /json/)
                  .expect('Cache-Control', testUtils.cacheRules.private)
                  .expect(401)
                  .then((res) => {
                      should.exist(res.body.errors);
                      res.body.errors[0].type.should.eql('UnauthorizedError');
                      res.body.errors[0].message.should.eql('Cannot reset password.');
                  });
          });
  
          it('reset password: generate reset token', function () {
              return request
                  .post(localUtils.API.getApiQuery('authentication/passwordreset'))
                  .set('Origin', config.get('url'))
                  .set('Accept', 'application/json')
                  .send({
                      passwordreset: [{
                          email: user.email
                      }]
                  })
                  .expect('Content-Type', /json/)
                  .expect('Cache-Control', testUtils.cacheRules.private)
                  .expect(200)
                  .then((res) => {
                      const jsonResponse = res.body;
                      should.exist(jsonResponse.passwordreset[0].message);
                      jsonResponse.passwordreset[0].message.should.equal('Check your email for further instructions.');
                      mailService.GhostMailer.prototype.send.args[0][0].to.should.equal(user.email);
                  });
          });
      });
  });
  