/* eslint-disable camelcase */
/* eslint-disable no-unused-expressions */
/* eslint-disable import/no-extraneous-dependencies */
/* eslint-disable no-console */
/* eslint-disable no-prototype-builtins */
/* eslint-disable no-use-before-define */
/* eslint-disable no-shadow */
import loadash from 'lodash/index.js';
import chalk from 'chalk';
import ModuleValue from '../../constants/module-value.mjs';
import { pickHTMLSitemapPageKeys } from '../../constants/pick-keys.mjs';
import { generatePlaceholderString } from '../generators.mjs';
// eslint-disable-next-line import/no-cycle
import { shouldSavePrefilled, processModule } from './modules.mjs';
import { clonePageForCards, groupBy, removeTags, updateMenuPrefixPath } from './common.mjs';
import {
  prepareSportsData,
  addSportsDataToPage,
  addExtraFieldsToShowcaseEvents,
} from './sports.mjs';
import { processRelations } from './relations.mjs';
import { zeroPadding } from '../schedule.mjs';
import { getRoundMinutes } from '../getters.mjs';
import { checkForInactiveOperatorToplist } from '../validateData.mjs';

const { cloneDeep, pick } = loadash;
const previewMode = process.env.GATSBY_PREVIEW_MODE || false;
const postSectionsMap = {
  operator: ['post_main_operators', 'pre_main_operators'],
  article: ['post_main_articles'],
  game: ['post_main_games'],
};

let rageSportType = null;
let themeType = null;
let pages = null;
let pagesCloned = null;
const pagesMappedById = [];
let relations = null;
let menus = null;
let prefilledMarketModules = null;
let prefilledMarketModulesRaw = null;
let sportsData = null;
const searchData = [];

export function processSitemapPages(pages, markets) {
  const pageListByMarket = [];
  Object.keys(markets).forEach((market) => {
    pageListByMarket[market] = [];
    let pageList = [];
    Object.keys(pages[market]).forEach((pageType) => {
      const filteredPages = pages[market][pageType].filter((page) => {
        if (page.relation_type === 'event') {
          return (
            page.relation &&
            page.relation.event &&
            page.robot_options &&
            page.robot_options.page_index === 1
          );
        }
        return page.robot_options && page.robot_options.page_index === 1;
      });

      pageList = pageList.concat(filteredPages.map((row) => pick(row, pickHTMLSitemapPageKeys)));
    });

    pageListByMarket[market] = groupBy(pageList, 'template_id');
  });

  return pageListByMarket;
}

export function transform(response) {
  const transformed = {};
  Object.keys(response.site_markets).forEach((siteMarket) => {
    const language = siteMarket.split('_')[1];
    transformed[siteMarket] = {};
    if (response.pages[language]) {
      Object.keys(response.pages[language]).forEach((pageType) => {
        transformed[siteMarket][pageType] = [];
        Object.keys(response.pages[language][pageType]).forEach((pagePath) => {
          const page = response.pages[language][pageType][pagePath][siteMarket];

          if (response.site_markets[siteMarket].path_prefix && page) {
            // set page prefix for multiple markets
            page.path = `${response.site_markets[siteMarket].path_prefix}${
              page.path !== '/' ? `/${page.path}` : ''
            }`;
            transformed[siteMarket][pageType].push(page);
          } else if (page) {
            transformed[siteMarket][pageType].push(page);
          }
        });
      });
    }
  });
  console.log('transform done');

  return transformed;
}

const savedModules = {};
export function processSections(sections, skipPost = false, page, translations, markets) {
  const siteName = page && page.siteInfo && page.siteInfo.site_name;
  // pagedId we will use it just on operator review pages
  const pageId = page ? page.id : null;
  const relationData = page && page.relation;

  Object.keys(sections).forEach((sectionKey) => {
    if (skipPost && sectionKey.includes('post_main')) {
      return;
    }
    if (sections[sectionKey] && sections[sectionKey].hasOwnProperty('extra_fields')) {
      processExtraFields(sections[sectionKey].extra_fields);
    }
    if (sections[sectionKey] && sections[sectionKey].modules) {
      sections[sectionKey].modules.forEach((module, key) => {
        if (shouldSavePrefilled(module, siteName) && savedModules[module.module_value_id]) {
          Object.assign(module, savedModules[module.module_value_id]);
        } else {
          processModule(
            module,
            pages,
            pagesCloned,
            relations,
            pagesMappedById,
            menus,
            previewMode,
            pageId,
            translations,
            relationData,
            markets
          );

          if (shouldSavePrefilled(module, siteName)) {
            savedModules[module.module_value_id] = module;
          }
        }
      });
    }
  });

  return sections;
}

export function getReadingTime(sections) {
  let minutes = 0;
  let seconds = 0;

  Object.keys(sections).forEach((sectionKey) => {
    if (sections[sectionKey] && sections[sectionKey].modules) {
      sections[sectionKey].modules.forEach((module) => {
        // calculate reading time
        if (module.name === 'content') {
          const nrOfWords = removeTags(module.value).split(' ').length / 250;
          const minPerModule = Math.floor(nrOfWords);
          const secPerModule = Math.floor((nrOfWords % 1) * 60);

          minutes += minPerModule;
          seconds += secPerModule;
        }
      });
    }
  });

  // transform seconds to minutes as last step
  if (seconds > 60) {
    const mins = Math.floor(seconds / 60);
    const decimalSeconds = seconds % 60;

    minutes += mins;
    seconds = decimalSeconds;
  }

  return getRoundMinutes(`${zeroPadding(minutes, 2)}:${zeroPadding(seconds, 2)}`) || null;
}

function processSearchData(data, fs) {
  if (!fs) {
    return;
  }

  fs.writeFile(`./src/data/search/data.json`, JSON.stringify([...data], null, ' '), (error) => {
    if (error) {
      console.log(
        chalk.magenta('info') + chalk.whiteBright(` Error writing search json file : ${error}`)
      );
    }
  });
}

export function processExtraFields(extraFields) {
  if (!extraFields) {
    return;
  }
  Object.keys(extraFields).forEach((key) => {
    const { type, value } = extraFields[key];
    if (type === 'operator') {
      extraFields[key] = relations[type][value];
    } else if (type === 'menu') {
      extraFields[key] = menus[value];
    } else {
      extraFields[key] = value;
    }
  });
}

function updatePlaceholders(page, data) {
  const languageKey = Object.keys(data.relations.translations)[0];
  const translations = data.relations.translations[languageKey];

  page.title =
    page.title &&
    generatePlaceholderString(page.title, translations, {
      siteName: data.general.site_name,
      siteTitle: page.title,
    });
  page.meta_title =
    page.meta_title &&
    generatePlaceholderString(page.meta_title, translations, {
      siteName: data.general.site_name,
      siteTitle: page.title,
    });
  page.meta_description =
    page.meta_description &&
    generatePlaceholderString(page.meta_description, translations, {
      siteName: data.general.site_name,
      siteTitle: page.title,
    });
}

export default {
  run(data, themeOptions, fs) {
    const start = new Date();
    const transformedPages = transform(data);
    const languageKey = Object.keys(data.relations.translations)[0];
    const translations = data.relations.translations[languageKey];
    const allResponsibleGaming = data.relations.responsible_gamings || null;
    const searchTemplatesAcitve = [];
    let templateFeadbackCounter = null;

    // create the list of templates that the feedback module will display
    templateFeadbackCounter = Object.keys(data.templates).filter(
      (res) => data.templates[res].feedback_counter
    );

    // Check what templates should add in the search result
    Object.keys(data.templates).forEach((el) => {
      const includeInSearch = data.templates[el].exclude_from_search_result;
      if (!includeInSearch) {
        searchTemplatesAcitve.push(data.templates[el].short_name);
      }
    });

    rageSportType = ['rage_seo', 'rage_ppc', 'sports'].includes(data.general.type);
    themeType = data.general.type ? data.general.type : null;

    const searchEnabled =
      themeOptions.searchEnabled !== undefined && themeOptions.searchEnabled !== null
        ? themeOptions.searchEnabled
        : true;

    // add sports data
    if (rageSportType) {
      // should be able to check for site type here (type: sport)
      // assign providers to events, events to schedules etc..
      sportsData = prepareSportsData(data.relations.sports_data);
    }

    menus = data.menus;

    // Menu changes when there is a path prefix configured on hercules
    Object.keys(menus).forEach((menu) => {
      if (data.site_markets[menus[menu].market].path_prefix) {
        updateMenuPrefixPath(
          menus[menu].children,
          data.site_markets[menus[menu].market].path_prefix
        );
      }
    });

    Object.keys(data.site_markets).forEach((market) => {
      relations = data.relations;
      pages = transformedPages[market];

      prefilledMarketModules = data.prefilled_market_modules || {};
      prefilledMarketModulesRaw = cloneDeep(data.prefilled_market_modules);
      Object.keys(transformedPages[market]).forEach((pageType) => {
        transformedPages[market][pageType].forEach((page, index) => {
          // process page extra fields
          page.extra_fields && processExtraFields(page.extra_fields);
          updatePlaceholders(page, data);

          // set page relation
          processRelations(
            page,
            pageType,
            transformedPages,
            market,
            data,
            index,
            pageType === 'preview',
            data.relations.translations[page.language]
          );

          // add author object to page
          if (page.author_id !== null && data.authors[page.author_id]) {
            transformedPages[market][pageType][index].author = data.authors[page.author_id];
          }

          // add reviewer object to page
          if (page.reviewer_id !== null && Object.values(data.authors).length) {
            transformedPages[market][pageType][index].reviewer = data.authors[page.reviewer_id];
          }

          // add page styles object to page
          if (page.style_id !== null && Object.values(data.page_styles).length) {
            transformedPages[market][pageType][index].page_styles = data.page_styles[page.style_id];
          }

          // add reading time for each page
          transformedPages[market][pageType][index].reading_time = getReadingTime(
            transformedPages[market][pageType][index]?.sections
          );

          // add breadcrumbs array to page
          const pageBreadcrumbIds = transformedPages[market][pageType][index].breadcrumb_ids;
          if (pageBreadcrumbIds) {
            let breadcrumbsArray = [];
            for (let i = 0; i < pageBreadcrumbIds.length; i += 1) {
              const breadcrumbData = cloneDeep(data.breadcrumbs[pageBreadcrumbIds[i]]);

              if (data.site_markets[market].path_prefix) {
                breadcrumbData[0].path = `${data.site_markets[market].path_prefix}/${breadcrumbData[0].path}`;
              }

              breadcrumbsArray = [...breadcrumbsArray, ...breadcrumbData];
            }
            transformedPages[market][pageType][index].breadcrumbs = breadcrumbsArray;
          }

          // add categories object to page
          const categoryIds = transformedPages[market][pageType][index].categories;
          transformedPages[market][pageType][index].categoryIds = categoryIds;

          if (categoryIds.length) {
            let categoryArray = [];
            for (let i = 0; i < categoryIds.length; i += 1) {
              categoryArray = [
                ...categoryArray,
                {
                  name: data.categories[categoryIds[i]].name,
                  short_name: data.categories[categoryIds[i]].short_name,
                },
              ];
            }
            transformedPages[market][pageType][index].categories = categoryArray;
          }

          // add responsible gaming to pages
          const gamingIds =
            data.relations.dms_affiliate_settings.markets_data &&
            data.relations.dms_affiliate_settings.markets_data[market] &&
            data.relations.dms_affiliate_settings.markets_data[market].responsible_gaming_ids
              ? data.relations.dms_affiliate_settings.markets_data[market].responsible_gaming_ids
              : null;
          let responsibleGaming = [];

          if (allResponsibleGaming !== null && gamingIds !== null) {
            for (let i = 0; i < gamingIds.length; i += 1) {
              const game = Object.values(allResponsibleGaming).find(
                (item) => item.id === gamingIds[i]
              );
              responsibleGaming = [...responsibleGaming, game];
            }
          }

          transformedPages[market][pageType][index].responsibleGaming = responsibleGaming;

          // add sports data
          if (rageSportType) {
            // should be able to check for site type here (type: sport)
            if (page.relation_type !== 'operator') {
              page.relation = addSportsDataToPage(sportsData, page, themeType);
            }

            if (pageType === 'page' && page.relation.showcased_events) {
              const eventPages = Object.values(transformedPages[market].event);
              const showcasedEvents = page.relation.showcased_events;

              page.relation.showcased_events = addExtraFieldsToShowcaseEvents(
                eventPages,
                showcasedEvents
              );
            }
          }

          pagesMappedById[page.id] = page;

          // add search data
          if (searchTemplatesAcitve.includes(page.template) && searchEnabled) {
            searchData.push(
              clonePageForCards(cloneDeep(transformedPages[market][pageType][index]))
            );
          }

          const sectionList = postSectionsMap[page.relation_type];

          sectionList &&
            sectionList.forEach((res) => {
              if (data.market_sections[market][res]) {
                if (page.sections.main) {
                  page.sections.main.feedbackCounter =
                    templateFeadbackCounter.includes(`${page.template_id}`) || null;
                }

                const postSectionModules = data.market_sections[market][res].modules || [];
                postSectionModules.forEach((item) => {
                  if (!page.sections.main) {
                    return;
                  }

                  if (item.value_type === ModuleValue.VALUE_TYPE_PREFILLED_MODULE_MARKET) {
                    page.sections.main.modules.push({
                      ...cloneDeep(prefilledMarketModules[item.value_id]),
                      value_type: ModuleValue.VALUE_TYPE_PREFILLED_MODULE_MARKET,
                    });
                  } else {
                    if (
                      transformedPages[market][pageType][index].relation &&
                      checkForInactiveOperatorToplist(item, page.relation.status)
                    )
                      return;

                    res === 'pre_main_operators'
                      ? page.sections.main.modules.unshift(cloneDeep(item))
                      : page.sections.main.modules.push(cloneDeep(item));
                  }
                });
              }
            });
        });
      });

      // create search data (currently only for NSA)
      if (!previewMode && searchEnabled) {
        processSearchData(searchData, fs);
      }

      pagesCloned = cloneDeep(transformedPages[market]);

      // fill market sections
      if (data.market_sections[market]) {
        data.market_sections[market] = processSections(
          data.market_sections[market],
          true,
          null,
          translations,
          data.site_markets
        );
      }

      // fill page sections
      if (transformedPages[market]) {
        Object.keys(transformedPages[market]).forEach((pageType) => {
          transformedPages[market][pageType].forEach((page, index) => {
            // Href Lang
            let hreflangs = page.page_group_id ? data.page_groups[page.page_group_id] : null;
            if (page.page_custom_hreflangs) {
              hreflangs = hreflangs
                ? [...hreflangs, ...page.page_custom_hreflangs]
                : page.page_custom_hreflangs;
            }

            hreflangs &&
              hreflangs.forEach((href, i) => {
                if (
                  pagesMappedById[href.page_id] &&
                  pagesMappedById[href.page_id].path &&
                  !data.site_markets[pagesMappedById[href.page_id].market].path_prefix
                ) {
                  hreflangs[i].default = true;
                }

                const pagePathPrefix =
                  pagesMappedById[href.page_id] &&
                  data.site_markets[pagesMappedById[href.page_id].market].path_prefix;

                if (pagePathPrefix) {
                  hreflangs[i].path = `${pagePathPrefix}${
                    href.path !== '/' ? `/${href.path}` : ''
                  }`;
                }
              });

            page.hreflangs = hreflangs;

            if (page.sections) {

              transformedPages[market][pageType][index] = Object.assign(page, {
                sections: processSections(
                  page.sections,
                  false,
                  page,
                  translations,
                  data.site_markets
                ),
              });
            }
          });
        });
      }
    });
    data.pages = transformedPages;
    const end = new Date() - start;
    console.log(chalk.green('success') + chalk.whiteBright(` processed module values - %dms`), end);
    return data;
  },
  clonePage(item) {
    return clonePageForCards(item);
  },
};
