const debug = require('debug')('growi:util:slack');
const urljoin = require('url-join');

/**
 * slack
 */

/* eslint-disable no-use-before-define */

const convertMarkdownToMarkdown = function(body, siteUrl) {
  return body
    .replace(/\n\*\s(.+)/g, '\n• $1')
    .replace(/#{1,}\s?(.+)/g, '\n*$1*')
    .replace(/(\[(.+)\]\((https?:\/\/.+)\))/g, '<$3|$2>')
    .replace(/(\[(.+)\]\((\/.+)\))/g, `<${siteUrl}$3|$2>`);
};

const prepareAttachmentTextForCreate = function(page, siteUrl) {
  let body = page.revision.body;
  if (body.length > 2000) {
    body = `${body.substr(0, 2000)}...`;
  }

  return convertMarkdownToMarkdown(body, siteUrl);
};

const prepareAttachmentTextForUpdate = function(page, siteUrl, previousRevision) {
  const diff = require('diff');
  let diffText = '';

  diff.diffLines(previousRevision.body, page.revision.body).forEach((line) => {
    debug('diff line', line);
    const value = line.value.replace(/\r\n|\r/g, '\n'); // eslint-disable-line no-unused-vars
    if (line.added) {
      diffText += `${line.value} ... :lower_left_fountain_pen:`;
    }
    else if (line.removed) {
      // diffText += '-' + line.value.replace(/(.+)?\n/g, '- $1\n');
      // 1以下は無視
      if (line.count > 1) {
        diffText += `:wastebasket: ... ${line.count} lines\n`;
      }
    }
    else {
      // diffText += '...\n';
    }
  });

  debug('diff is', diffText);

  return diffText;
};

const prepareAttachmentTextForComment = function(comment) {
  let body = comment.comment;
  if (body.length > 2000) {
    body = `${body.substr(0, 2000)}...`;
  }

  if (comment.isMarkdown) {
    return convertMarkdownToMarkdown(body);
  }

  return body;
};

const generateSlackMessageTextForPage = function(path, pageId, user, siteUrl, updateType) {
  let text;

  const pageUrl = `<${urljoin(siteUrl, pageId)}|${path}>`;
  if (updateType === 'create') {
    text = `:rocket: ${user.username} created a new page! ${pageUrl}`;
  }
  else {
    text = `:heavy_check_mark: ${user.username} updated ${pageUrl}`;
  }

  return text;
};

export const prepareSlackMessageForPage = (page, user, appTitle, siteUrl, channel, updateType, previousRevision) => {
  let body = page.revision.body;

  if (updateType === 'create') {
    body = prepareAttachmentTextForCreate(page, siteUrl);
  }
  else {
    body = prepareAttachmentTextForUpdate(page, siteUrl, previousRevision);
  }

  const attachment = {
    color: '#263a3c',
    author_name: `@${user.username}`,
    author_link: urljoin(siteUrl, 'user', user.username),
    author_icon: user.image,
    title: page.path,
    title_link: urljoin(siteUrl, page.id),
    text: body,
    mrkdwn_in: ['text'],
  };
  if (user.image) {
    attachment.author_icon = user.image;
  }

  const message = {
    channel: (channel != null) ? `#${channel}` : undefined,
    username: appTitle,
    text: generateSlackMessageTextForPage(page.path, page.id, user, siteUrl, updateType),
    attachments: [attachment],
  };

  return message;
};

export const prepareSlackMessageForComment = (comment, user, appTitle, siteUrl, channel, path) => {
  const body = prepareAttachmentTextForComment(comment);

  const attachment = {
    color: '#263a3c',
    author_name: `@${user.username}`,
    author_link: urljoin(siteUrl, 'user', user.username),
    author_icon: user.image,
    text: body,
    mrkdwn_in: ['text'],
  };
  if (user.image) {
    attachment.author_icon = user.image;
  }

  const pageUrl = `<${urljoin(siteUrl, String(comment.page))}|${path}>`;
  const text = `:speech_balloon: ${user.username} commented on ${pageUrl}`;

  const message = {
    channel: (channel != null) ? `#${channel}` : undefined,
    username: appTitle,
    text,
    attachments: [attachment],
  };

  return message;
};

/**
   * For GlobalNotification
   *
   * @param {string} messageBody
   * @param {string} attachmentBody
   * @param {string} slackChannel
  */
export const prepareSlackMessageForGlobalNotification = (messageBody, attachmentBody, appTitle, slackChannel) => {

  const attachment = {
    color: '#263a3c',
    text: attachmentBody,
    mrkdwn_in: ['text'],
  };

  const message = {
    channel: (slackChannel != null) ? `#${slackChannel}` : undefined,
    username: appTitle,
    text: messageBody,
    attachments: JSON.stringify([attachment]),
  };

  return message;
};
