require('dotenv').config();
const { createSpinner } = require('nanospinner');
const get = require('./get-data');
const writeTouchpoint = require('./write-touchpoint');
const writeItem = require('./write-item');
const writeClaims = require('./write-claims');
const print = require('../../helpers/print');

/**
 *
 * @param {Promise<any>} promise
 * @param {string} text
 * @returns
 */
function spinPromise(promise, text) {
  const spinner = createSpinner(text).start();

  try {
    promise.then(() => spinner.success()).catch(() => spinner.error());
  } catch (e) {
    spinner.error();
  }

  return spinner;
}

async function download({
  host = 'eu1.kaskocloud.com',
  key = process.env.WEBAPP_PUBLIC_KEY,
  touchpointId = process.env.WEBAPP_TOUCHPOINT_ID,
  language = process.env.WEBAPP_LANGUAGE,
} = {}) {
  // Validate
  if (!key) {
    throw new Error('`WEBAPP_PUBLIC_KEY` environment variable not found');
  }

  if (!touchpointId) {
    throw new Error('`WEBAPP_TOUCHPOINT_ID` environment variable not found');
  }

  if (!language) {
    throw new Error('`WEBAPP_LANGUAGE` environment variable not found');
  }

  // Download the touchpoint
  const downloadTouchpointAction = get(`https://feapi.${host}/touchpoints/${touchpointId}`, {
    language,
    key,
  });
  spinPromise(downloadTouchpointAction, 'Downloading Touchpoint');
  const touchpoint = await downloadTouchpointAction;

  // Write touchpoint
  const writeTouchpointAction = writeTouchpoint(touchpoint);
  spinPromise(writeTouchpointAction, 'Writing Touchpoint');
  await writeTouchpointAction;

  // Download and write all items (in parallel)
  await Promise.all(
    touchpoint.items.map(async ({ id: itemId }) => {
      const downloadItemAction = get(
        `https://feapi.${host}/touchpoints/${touchpointId}/items/${itemId}`,
        {
          language,
          key,
        },
      );
      spinPromise(downloadItemAction, `Downloading Item: ${itemId}`);
      const item = await downloadItemAction;

      const writeItemAction = writeItem(item);
      spinPromise(writeItemAction, `Writing Item: ${itemId}`);
      return writeItemAction;
    }),
  );

  // Download and write all claims settings (in parallel)
  await Promise.all(
    touchpoint.items
      .filter((item) => item.has_claims === true || typeof item.has_claims === 'undefined')
      .map(async ({ id: itemId }) => {
        /** @type {string} */
        let error;
        let claim;
        try {
          const downloadClaimAction = get(
            `https://feapi.${host}/touchpoints/${touchpointId}/items/${itemId}/claim_settings`,
            {
              language,
              key,
            },
          );
          spinPromise(downloadClaimAction, `Downloading Claims: ${itemId}`);
          claim = await downloadClaimAction;
        } catch (e) {
          error = e.message;
        }

        if (!claim) {
          print(`\t  - Skipping writing because ${error}`);
          return Promise.resolve;
        }

        const writeClaimAction = writeClaims(itemId, claim);
        spinPromise(writeClaimAction, `Writing Claims: ${itemId}`);
        return writeClaimAction;
      }),
  );
}

module.exports = download;
