import get from 'ember-metal/get';
import { module, test } from 'qunit';
import {
  NOTIFICATION_TYPE,
  NOTIFICATION_VALUES,
  canPublish,
  isPublished,
  populateNotifications
} from 'web-client/models/notification';

module('Unit | Models | Notification');

test('populateNotifications: should not mutate the source input', assert => {
  const source = {
    metadata: {
      foo: 'baz'
    }
  };
  const actual = populateNotifications(source);
  const expected = {
    metadata: {
      foo: 'baz'
    },
    channel_feed: {
      enabled: false
    },
    email: {
      enabled: true
    }
  };
  assert.deepEqual(actual, expected, 'should merge properties');
  assert.deepEqual(source, {
    metadata: {
      foo: 'baz'
    }
  }, 'should not mutate the source');
});

test('populateNotifications: missing notifications', assert => {
  function testPopulate({ notifications = {}, expected }) {
    const actual = populateNotifications(notifications);
    const missingTypes = NOTIFICATION_VALUES.filter(key => !get(notifications, key));

    assert.deepEqual(actual, expected, `should add '${missingTypes.join(', ')}' notification(s)`);
  }

  testPopulate({
    notifications: undefined,
    expected: {
      channel_feed: {
        enabled: false
      },
      email: {
        enabled: true
      }
    }
  });

  testPopulate({
    notifications: {
      channel_feed: {
        enabled: true,
        custom_text: 'foo'
      }
    },
    expected: {
      channel_feed: {
        enabled: true,
        custom_text: 'foo'
      },
      email: {
        enabled: true
      }
    }
  });

  testPopulate({
    notifications: {
      email: {
        vod_id: 2,
        enabled: false
      }
    },
    expected: {
      channel_feed: {
        enabled: false
      },
      email: {
        vod_id: 2,
        enabled: false
      }
    }
  });
});

test('canPublish', assert => {
  function renderNotifications(notifications = {}) {
    const testInput = NOTIFICATION_VALUES.map(key => {
      const sent = isPublished(notifications, key) ? 'published' : 'unpublished';
      return `${key}=${sent}`;
    });
    return testInput.join(', ');
  }

  function testPublishable(expected, notifications) {
    const testInput = renderNotifications(notifications);
    assert.equal(canPublish(notifications), expected, `should return ${expected} when (${testInput})`);
  }

  const SENT_NOTIFICATION = Object.freeze({ sent_at: new Date().toJSON() });
  const UNSENT_NOTIFICATION = Object.freeze({});

  testPublishable(true, { channel_feed: SENT_NOTIFICATION, email: UNSENT_NOTIFICATION });
  testPublishable(true, { channel_feed: UNSENT_NOTIFICATION, email: UNSENT_NOTIFICATION });
  testPublishable(true, { channel_feed: UNSENT_NOTIFICATION, email: SENT_NOTIFICATION });
  testPublishable(false, { channel_feed: SENT_NOTIFICATION, email: SENT_NOTIFICATION });
});

test('isPublished', assert => {
  function testIsPublished(date) {
    const type = NOTIFICATION_TYPE.CHANNEL_FEED;
    const notifications = { [type]: { sent_at: date }};
    return isPublished(type, notifications);
  }

  assert.ok(testIsPublished(new Date().toJSON()), `should be 'true' when 'seen_at' is present`);
  assert.notOk(testIsPublished(null), `should be 'false' when 'seen_at' is not present`);
});
