process.env.NODE_ENV = 'test';

var chai = require('chai');
var mock = require('mock-fs');
var should = chai.should();
var expect = chai.expect;

// constants
const CLASSIC_PRICE = 269.99;
const STANDOUT_PRICE = 322.99;
const PREMIUM_PRICE = 394.99;

const indexController = require('../../src/server/controllers/index');

describe('controllers : index', function() {

  beforeEach(function(done) {
    mock({
      './src/server/data': {
        // product.json
        'product.json': `{ 
          "classic": {
            "name": "Classic Ad",
            "price": 269.99
          },
          "standout": {
            "name": "Standout Ad",
            "price": 322.99
          },
          "premium": {
            "name": "Premium Ad",
            "price": 394.99
          }
        }`,
        // rule.json
        'rule.json': `{
          "UNILEVER" : {
            "classic": {
              "3": 2
            }
          },
          "APPLE": {
            "standout": {
              "price": 299.99
            }
          },
          "NIKE": {
            "premium": {
              ">= 4": 379.99
            }
          },
          "FORD" :{
            "classic": {
              "5": 4
            },
            "standout": {
              "price": 309.99
            },
            "premium": {
              ">= 3": 389.99
            }
          }
        }`
      }
    });

    done();
  });

  afterEach(function(done) {
    mock.restore();
    done();
  });

  describe('specialRule()', function() {
    it('test null and empty inputs', function(done) {

      var orders = [
        {},
        null
      ];

      var customers = [
        '',
        null
      ];

      for (var index in orders) {
        for (var i in customers) {
          var total = indexController.specialRule(customers[i], orders[index]);
          expect(total).to.equal(0);
        }
      }

      // err.should.eql('Something went wrong!');
      done();
    });

    it('test normal customer, with no rules', function(done) {

      var orders = [{
        premium: 0,
        standout: 0,
        classic: 0
      },{
        premium: 1
      },{
        standout: 1
      },{
        classic: 1
      }];
      var customer = 'Lolipop';

      for (var order of orders) {
        var total = indexController.specialRule(customer, order);
        var expectedTotal = PREMIUM_PRICE * (order.premium || 0) + STANDOUT_PRICE * (order.standout || 0) + CLASSIC_PRICE * (order.classic || 0);

        expect(total).to.equal(expectedTotal);
      }

      done();
    });

    it('test more than rule', function(done) {

      // "premium": {
      //   ">= 4": 379.99
      // }

      var orders = [{
        premium: 0,
        standout: 0,
        classic: 0
      },{
        premium: 1
      },{
        standout: 1,
        premium: 3
      },{
        premium: 4
      },{
        premium: 10,
        classic: 4
      }];
      var customer = 'NIKE';
      var expectedTotals = [0, PREMIUM_PRICE, PREMIUM_PRICE * 3 + STANDOUT_PRICE, 4 * 379.99, 4 * CLASSIC_PRICE + 10 * 379.99];
      for (var index in orders) {
        var total = indexController.specialRule(customer, orders[index]);
        expect(total).to.equal(parseFloat(expectedTotals[index].toFixed(2)));
      }

      done();
    });

    it('test discount price rule', function(done) {

      // "standout": {
      //   "price": 299.99
      // }

      var orders = [{
        premium: 0,
        standout: 0,
        classic: 0
      },{
        standout: 1
      },{
        standout: 1,
        premium: 1
      },{
        standout: 4
      },{
        standout: 10,
        classic: 4
      }];
      var customer = 'APPLE';
      var discountPrice = 299.99;
      var expectedTotals = [0, discountPrice, PREMIUM_PRICE + discountPrice, 4 * discountPrice, 4 * CLASSIC_PRICE + 10 * discountPrice];
      for (var index in orders) {
        var total = indexController.specialRule(customer, orders[index]);
        expect(total).to.equal(parseFloat(expectedTotals[index].toFixed(2)));
      }

      done();
    });

    it('test x for y deals', function(done) {

      // "classic": {
      //   "3": 2
      // }

      var orders = [{
        premium: 0,
        standout: 0,
        classic: 0
      },{
        classic: 1
      },{
        classic: 1,
        premium: 1
      },{
        classic: 4
      },{
        classic: 10,
        premium: 4
      }];
      var customer = 'UNILEVER';

      var expectedTotals = [0, CLASSIC_PRICE, CLASSIC_PRICE + PREMIUM_PRICE, 3 * CLASSIC_PRICE, 4 * PREMIUM_PRICE + 7 * CLASSIC_PRICE];
      for (var index in orders) {
        var total = indexController.specialRule(customer, orders[index]);
        expect(total).to.equal(parseFloat(expectedTotals[index].toFixed(2)));
      }

      done();
    });

    it('test all 3 coditions', function(done) {

      //    "classic": {
      //       "5": 4
      //     },
      //     "standout": {
      //       "price": 309.99
      //     },
      //     "premium": {
      //       ">= 3": 389.99
      //     }

      var orders = [{
        premium: 0,
        standout: 0,
        classic: 0
      },{
        premium: 2,
        standout: 2,
        classic: 4
      },{
        premium: 3,
        standout: 5,
        classic: 5
      },{
        premium: 10,
        standout: 15,
        classic: 12
      }];
      var customer = 'FORD';
      var discountStandoutPrice = 309.99;
      var newPremiumPrice = 389.99;
      var expectedTotals = [
        0,
        PREMIUM_PRICE * 2 + CLASSIC_PRICE * 4 + discountStandoutPrice * 2,
        newPremiumPrice * 3 + CLASSIC_PRICE * 4 + discountStandoutPrice * 5,
        newPremiumPrice * 10 + CLASSIC_PRICE * 10 + discountStandoutPrice * 15];
      for (var index in orders) {
        var total = indexController.specialRule(customer, orders[index]);
        expect(total).to.equal(parseFloat(expectedTotals[index].toFixed(2)));
      }

      done();
    });

    it('should return an error', function(done) {
      var order = {
        premium: -1
      };
      var customer = 'random';
      try {
        indexController.specialRule(customer, order);
      } catch (err) {
        err.should.eql('Negative quantity');
        done();
      }
    });
  });
});
