'use strict';

// GLOBAL
const util = require('util');
const https = require('https');
const HttpsProxyAgent = require('https-proxy-agent');

// LOCAL
const tools = require('../tools');

// FETCH COMMAND-LINE ARGS
let { dryRun, slackFeedback, debug, debugNotification } = tools.getArgs();


const PROXY = process.env.http_proxy;

const agent = PROXY ? new HttpsProxyAgent(PROXY) : void 0;




const sendMessageCore = (hook, channel, attachments, text = null) => {
  return new Promise((resolve, reject) => {
    const payload = {
      username: "eUI bot",
      channel
    };

    if (attachments) {
      payload.attachments = attachments.map(a => Object.assign({}, a, {fallback: a.fallback || a.pretext}))
    } else {
      payload.text = text;
    }

    const postData = JSON.stringify(payload);

    const options = {
      agent,
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
        'Content-Length': Buffer.byteLength(postData)
      }
    };

    if (dryRun || !slackFeedback) {
      tools.logInfo('No notifications config found...skipping');

      if (debug && debugNotification) {
        console.log(JSON.stringify(payload, null, 4));
      }

      resolve();

    } else {
      tools.logInfo(`Sending message to Slack...`);
      tools.logInfo(`Slack hook: ${hook}`);
      tools.logInfo(`Slack channel: ${channel}`);

      if (debug && debugNotification) {
        console.log(JSON.stringify(payload, null, 4));
      }

      const req = https.request(hook, options, (res) => {
        res.setEncoding('utf8');
        if (res.statusCode === 200) {
          tools.logSuccess('Message sent successfully!');
          resolve();
        } else {
          tools.logError(`Error sending message to slack.`);
          tools.logInfo('statusCode: ' + res.statusCode);
          tools.logInfo('statusMessage: ' + res.statusMessage);

          if (debug && debugNotification) {
            console.log(util.inspect(res));
          }
        }
      });

      req.on('error', (e) => {
        console.log(e);
        resolve();
      });

      req.write(postData);
      req.end();
    }
  });
};

const sendMessage = (hook, channel, attachments, text = null) => {
  return Promise.resolve()
    .then(() => {
      return sendMessageCore(hook, channel, attachments, text);
    })
    .catch((e) => {
      tools.logError('Error sending slack message');
      console.log(e); // do not rethrow
      return Promise.resolve();
    })
};



const getFields = (scope, version) => {
  const fields = [];

  if (scope) {
    fields.push({
      "title": "Scope",
      "value": scope,
      "short": true
    });
  }

  if (version) {
    fields.push({
      "title": "Version",
      "value": version,
      "short": true
    });
  }

  return fields;
}




const sendProjectMessage = (hook, channel, message) => {
  tools.logInfo('Sending project message');

  // do nothing if at least hook / channel for package can't be found
  if (!hook || !channel) {
    return;
  }

  let attachments;

  if (!message.text) {
    attachments = [];

    attachments.push({
      pretext: message.mainTitle,
      title: message.mainText,
      color: message.statusColor,
      fields: getFields(message.scope, message.version),
    });

    if (message.detailTitle) {
      attachments.push({
        title: message.detailTitle,
        text: '```' + message.detailText + '```',
      });
    }
  }

  return sendMessage(hook, channel, attachments, message.text);
}


const sendProjectDiffReportMessage = (diffMetadata, slackHook, slackChannel) => {
  tools.logInfo('Sending diff report message');

  // do nothing if at least hook / channel for project can't be found
  if (!slackHook || !slackChannel) {
    return;
  }

  let metadataText = 'No differences detected';

  if (diffMetadata.length !== 0) {
    metadataText = diffMetadata.map((pkg) => {
      return `${pkg.package} ---> from [${pkg.fromVersion}] to [${pkg.toVersion}]`
    }).join('\n ');
  }

  return sendMessage(
    slackHook,
    slackChannel,
    [
      {
        title: 'Composite packages differences from latest env version',
        text: '```' + metadataText + '```',
      }
    ]
  )
}






const sendPackageMessage = (hook, channel, message) => {
  tools.logInfo('Sending package message');

  // do nothing if at least hook / channel for package can't be found
  if (!hook || !channel) {
    return;
  }

  let attachments;

  if (!message.text) {
    attachments = [];

    attachments.push({
      pretext: message.mainTitle,
      title: message.mainText,
      color: message.statusColor,
      fields: getFields(message.scope, message.version),
    });

    if (message.detailTitle) {
      attachments.push({
        title: message.detailTitle,
        text: '```' + message.detailText + '```',
      });
    }
  }

  return sendMessage(hook, channel, attachments, message.text);
}


const sendPackageDiffReportMessage = (diffMetadata, slackHook, slackChannel) => {
  tools.logInfo('Sending diff report message');

  // do nothing if at least hook / channel for project can't be found
  if (!slackHook || !slackChannel) {
    return;
  }

  let metadataText = 'No differences detected';

  if (diffMetadata.length !== 0) {
    metadataText = diffMetadata.map((pkg) => {
      return `${pkg.npmPkg} ---> from [${pkg.old}] to [${pkg.new}]`
    }).join('\n ');
  }

  return sendMessage(
    slackHook,
    slackChannel,
    [
      {
        title: 'Composite packages differences from latest env version',
        text: '```' + metadataText + '```',
      }
    ]
  )
}


// EXPORTS

module.exports = {
  sendProjectMessage,
  sendProjectDiffReportMessage,
  sendPackageMessage,
  sendPackageDiffReportMessage,
};
