import {
  DEMAND_TAG_FORMAT,
  DEMAND_TAG_HB_GAM_PLATFORMS,
  DEMAND_TAG_KEY_VALUE_TARGETING_STATUS,
  DEMAND_TAG_KEY_VALUE_TARGETING_TYPE,
  DEMAND_TAG_PAGE_BUSINESS_MODEL,
  DEMAND_TAG_PAGE_SOURCE,
  DEMAND_TAG_PAGE_TYPE_VALUES,
  DEMAND_TAG_SUPPLY_CHAIN_OVERRIDE,
  DEMAND_TAG_SUPPLY_CHAIN_VALUE,
  DEMAND_TAG_TARGETING_VIEWABILITY_TYPE,
  DEMAND_TAG_VIEWABILITY_TARGETING,
  FLOOR_PRICE,
  SOURCE_TAG_OPTIONS,
} from '@/modules/marketplace/account/constants';

import * as selectors from '../redux/selectors';

import { isFrequencyCapHasData } from './isFrequencyCapHasData';

export const getIncludeOrExclude = (isInclude, items) =>
  items.filter((item) => item.include === isInclude).map((item) => item.value);

const getFromObjectKeysWhenTrue = (object) => Object.keys(object).filter((key) => object[key]);

const createAdServerInput = ({ id, name, url }) => {
  const res = { url };

  if (name) {
    res.name = name;
  }

  if (id) {
    res.id = id;
  }

  return res;
};

export const createIncludeExcludeInput = (objectItems) => {
  let res = null;

  Object.keys(objectItems).forEach((objectItem) => {
    const item = objectItems[objectItem];
    if (item.value) {
      res = !res ? { [item.key]: item.value } : { ...res, [item.key]: item.value };
    }
  });

  return res;
};

const createEventPixelsListInput = (eventPixelsList) =>
  eventPixelsList.map((pixel) => ({
    url: pixel.url,
    name: pixel.event,
    type: pixel.type,
  }));

export const createPricesListInput = (pricesList, isCreatingNew) =>
  pricesList.map((price) => ({
    ...(isCreatingNew ? {} : { startDate: price.startDate }),
    value: price.value,
    ...(price.model ? { model: price.model } : {}),
  }));

export const createFeesListInput = (pricesList, isCreatingNew) =>
  pricesList.map((price) => ({
    ...(isCreatingNew ? {} : { startDate: price.startDate }),
    ...(price.endDate ? { endDate: price.endDate } : {}),
    value: price.value,
  }));

const createBudgetsListInput = (budgetsList) =>
  budgetsList.map((budget) => ({
    budget: budget.budget,
    pacing: budget.pacing,
    type: budget.type,
    timeframe: budget.timeFrame,
  }));

const createDemandTagRequestBody = (state) => {
  const pageConfig = selectors.pageConfigSelector(state);
  const info = selectors.infoSelector(state);
  const settings = selectors.settingsSelector(state);
  const pricing = selectors.pricingSelector(state);
  const targeting = selectors.targetingSelector(state);
  const budgeting = selectors.budgetingSelector(state);
  const frequencyCap = selectors.frequencyCapSelector(state);

  const body = {
    name: settings.name,
    tagSource:
      settings.source !== SOURCE_TAG_OPTIONS[0].value
        ? {
            source: settings.source,
            platformId: settings.platformId,
          }
        : {
            source: settings.source,
          },
    daccountId: info ? info.daccountId : pageConfig.demandAccount.id,
    advertiserId: info ? info.advertiserId : pageConfig.advertiser.id,
    defaultTier: settings.defaultTier,
    model: pricing.model,
    pricing:
      pageConfig.isCreatingNew || pageConfig.isDuplicate
        ? createPricesListInput(pricing.fixedRpmRateTable.rows, pageConfig.isCreatingNew)
        : [],
    fee:
      pageConfig.isCreatingNew || pageConfig.isDuplicate
        ? createFeesListInput(pricing.additionalFeesTable.rows, pageConfig.isCreatingNew)
        : [],
    adServingFees:
      pageConfig.isCreatingNew || pageConfig.isDuplicate
        ? createPricesListInput(pricing.adServingFeesTable.rows, pageConfig.isCreatingNew)
        : [],
    adRequestFee:
      pageConfig.isCreatingNew || pageConfig.isDuplicate
        ? createPricesListInput(pricing.adRequestFeesTable.rows, pageConfig.isCreatingNew)
        : [],
    type: settings.type,
    status: settings.status,
    format: settings.format,
    eventPixels: [],
    labels: [],
    flightsDates: settings.flightsDates || {},
    priority: settings.priority,
  };

  if (settings.uid) {
    body.id = settings.uid;
  }

  if (settings.labels && settings.labels.length) {
    body.labels = settings.labels;
  }

  if (Number.isInteger(settings.timeout)) {
    body.timeout = settings.timeout;
  }

  if (settings.eventPixelsList && settings.eventPixelsList.length) {
    body.eventPixels = createEventPixelsListInput(settings.eventPixelsList);
  }

  // include
  const includes = {
    geo: {
      key: 'geo',
      value: getIncludeOrExclude(true, targeting.countries),
    },
    os: {
      key: 'os',
      value: getIncludeOrExclude(true, targeting.os),
    },
    browsers: {
      key: 'browsers',
      value: getIncludeOrExclude(true, targeting.browsers),
    },
    devices: {
      key: 'devices',
      value: getIncludeOrExclude(true, targeting.devices),
    },
    playerSizes: {
      key: 'playerSizes',
      value: getFromObjectKeysWhenTrue(targeting.playerSize),
    },
    viewability: {
      key: 'viewability',
      value: getFromObjectKeysWhenTrue(targeting.viewability),
    },
  };

  const includesSponsored = {
    geo: {
      key: 'geo',
      value: getIncludeOrExclude(true, targeting.countries),
    },
    os: {
      key: 'os',
      value: getIncludeOrExclude(true, targeting.os),
    },
    browsers: {
      key: 'browsers',
      value: getIncludeOrExclude(true, targeting.browsers),
    },
    devices: {
      key: 'devices',
      value: getIncludeOrExclude(true, targeting.devices),
    },
  };

  const includeObject = createIncludeExcludeInput(
    settings.format === DEMAND_TAG_FORMAT.sponsored ? includesSponsored : includes,
  );

  if (includeObject) {
    body.include = includeObject;
  }

  // exclude
  const excludes = {
    geo: {
      key: 'geo',
      value: getIncludeOrExclude(false, targeting.countries),
    },
    os: {
      key: 'os',
      value: getIncludeOrExclude(false, targeting.os),
    },
    browsers: {
      key: 'browsers',
      value: getIncludeOrExclude(false, targeting.browsers),
    },
    devices: {
      key: 'devices',
      value: getIncludeOrExclude(false, targeting.devices),
    },
  };

  const excludeObject = createIncludeExcludeInput(excludes);

  if (excludeObject) {
    body.exclude = excludeObject;
  }

  body.budgets = budgeting.budgetingTabList?.length ? createBudgetsListInput(budgeting.budgetingTabList) : [];

  if (isFrequencyCapHasData(frequencyCap) && settings.format !== DEMAND_TAG_FORMAT.sponsored) {
    const { prevSavedData, ...frequencyCapData } = frequencyCap;
    body.frequency = { ...frequencyCapData };
  }

  if (settings.type === DEMAND_TAG_PAGE_TYPE_VALUES.tag) {
    body.adServer = createAdServerInput({
      name: settings.adServer.name, // optional
      url: settings.url?.trim(),
    });
  }

  if (settings.type === DEMAND_TAG_PAGE_TYPE_VALUES.mp4) {
    body.videoId = settings.videoId;

    if (settings.format !== DEMAND_TAG_FORMAT.sponsored) {
      body.clickThroughUrl = settings.clickThroughUrl;
    }
  }

  if (settings.type === DEMAND_TAG_PAGE_TYPE_VALUES.hb) {
    const {
      platform: { name, connectorId, code, ...params },
      supplyChainOverride,
      supplyChainValue,
      supplyChainNode,
      adjustFloor,
    } = settings;

    body.adjustFloor = adjustFloor;

    body.platform = {
      // name: settings.platform.name,
      connectorId,
      connectorName: name,
      code,
      params: Object.keys(params).reduce((acc, cur) => {
        if (params[cur]?.length) {
          return [...acc, { name: cur, value: params[cur] }];
        }
        return acc;
      }, []),
    };

    if (settings.platform?.code?.toUpperCase() === 'APS') {
      body.platform = {
        ...body.platform,
        bidMapping: {
          fileName: settings.bidMappingFileName,
          data: settings.bidMappingFileData,
        },
      };
    }

    if (DEMAND_TAG_HB_GAM_PLATFORMS.includes(settings.platform?.code)) {
      body.platform = {
        ...body.platform,
        maxFloor: +settings.maxFloor,
      };
    }

    if (supplyChainOverride === DEMAND_TAG_SUPPLY_CHAIN_OVERRIDE.enabled) {
      if (supplyChainValue === DEMAND_TAG_SUPPLY_CHAIN_VALUE.blank) {
        body.platform = {
          ...body.platform,
          supplyChain: '',
        };
      }

      if (supplyChainValue === DEMAND_TAG_SUPPLY_CHAIN_VALUE.custom) {
        body.platform = {
          ...body.platform,
          supplyChain: supplyChainNode.trim(),
        };
      }
    }

    if (settings.floorPrice?.override === FLOOR_PRICE.override) {
      body.floorPrice = {
        override: true,
        floor: +(settings.floorPrice?.floor ?? 0),
        viewableFloor: +(settings.floorPrice?.viewableFloor ?? 0),
      };
    } else {
      body.floorPrice = {
        override: false,
      };
    }
  }

  if (pricing.model === DEMAND_TAG_PAGE_BUSINESS_MODEL[1].value) {
    const { source, seatId, adUnitId, type: pricingType } = pricing;

    if (source === DEMAND_TAG_PAGE_SOURCE[0].value) {
      body.rateSource = {
        name: source,
        seatId,
        adUnitId,
        type: pricingType,
      };
    } else {
      body.rateSource = {
        name: source,
        adUnitId,
        type: pricingType,
      };
    }
  }

  if (
    targeting.viewability[DEMAND_TAG_TARGETING_VIEWABILITY_TYPE.inView] &&
    targeting.viewability[DEMAND_TAG_TARGETING_VIEWABILITY_TYPE.nonInView] &&
    targeting.viewabilityTargeting === DEMAND_TAG_VIEWABILITY_TARGETING.enabled
  ) {
    body.viewabilityThreshold = parseFloat(Number(targeting.viewabilityThreshold / 100).toFixed(4));
  } else {
    body.disableViewabilityThreshold = true;
  }

  if (settings.format !== DEMAND_TAG_FORMAT.sponsored) {
    if (targeting.kvTargetingStatus === DEMAND_TAG_KEY_VALUE_TARGETING_STATUS.enabled) {
      body.kvTargeting = targeting.kvTargeting
        ?.filter((item) => item?.keyName)
        .map((item) => ({
          key: item.keyName.value,
          state: item.state,
          type: item.type,
          values:
            item.type === DEMAND_TAG_KEY_VALUE_TARGETING_TYPE.list
              ? item.valueLists?.map((list) => list.value)
              : item.values,
        }));
    } else {
      body.kvTargeting = [];
    }
  }

  return body;
};

export default createDemandTagRequestBody;
