import _isEmpty from 'lodash/isEmpty'
import _isNull from 'lodash/isNull'
import _reverse from 'lodash/reverse'
import _sortBy from 'lodash/sortBy'

interface ObjectLiteral {
  [key: string]: any;
}

export const generateSelectOptions = (minCount = 1, maxCount = 10) => {
  const options = []
  for (let i = minCount; i <= maxCount; i++) {
    options.push({ label: i, value: i })
  }
  return options
}

const generateStockBasedOnLimitations = (
  addon: any,
  ticketQuantity: number
) => {
  // Generate addon available stock count based on limitations
  const { flagLimitToTicketQuantity, maxQuantity, limitPerTicket } = addon

  let allowedStockCount

  // Generate stock
  if (flagLimitToTicketQuantity) {
    // Limited to ticket quantity case
    allowedStockCount = ticketQuantity
  } else if (maxQuantity && limitPerTicket) {
    const stockBasedOnLimitPerTicket = limitPerTicket * ticketQuantity
    // Both maximum quantity and limited to per ticket selected case, stock is minimum of them
    allowedStockCount =
      maxQuantity <= stockBasedOnLimitPerTicket
        ? maxQuantity
        : stockBasedOnLimitPerTicket
  } else if (maxQuantity && !limitPerTicket) {
    // Limited to maximum quantity case
    allowedStockCount = maxQuantity
  } else if (!maxQuantity && limitPerTicket) {
    // Limited to per ticket case
    allowedStockCount = limitPerTicket * ticketQuantity
  }

  return Number(allowedStockCount)
}

const filterStockBasedOnAvailability = (
  generatedStock: any,
  availableStock: any
) => {
  //  Check generated stock count admissibility with addon stock availability
  let filteredStockCount = generatedStock

  if (generatedStock) {
    if (generatedStock > availableStock && !_isNull(availableStock)) {
      filteredStockCount = availableStock
    }
  } else {
    // Not set any restriction
    // Here 10 value is business logic
    filteredStockCount = 10

    if (!_isNull(availableStock) && availableStock < filteredStockCount) {
      filteredStockCount = availableStock
    }
  }

  return filteredStockCount
}

export const getAddonSelectOptions = (addons: any, choosedTicketCount: any) => {
  const addonsWithOptions: ObjectLiteral = {}
  const groupsWithSelectedVariantsInfo: ObjectLiteral = {}
  const groupsWithVariants: ObjectLiteral = {}

  addons.forEach((addon: any) => {
    // Here addon can act either as simple Addon or Addon Group
    const {
      id,
      stock: simpleAddonStock,
      variants,
      active,
      flagLimitToTicketQuantity,
      maxQuantity,
      limitPerTicket,
    } = addon

    if (variants) {
      // Addon Group with inside addon variants case
      variants.forEach((variant: any) => {
        const { id: variantId, stock: variantStock } = variant

        // null checking is for unlimited stock value
        if (active && (variantStock > 0 || _isNull(variantStock))) {
          // Generate Addon Group allowed stock count based on limitations
          const stockBasedOnLimitation = generateStockBasedOnLimitations(
            addon,
            choosedTicketCount
          )

          // Detect if group has limitation or not
          if (flagLimitToTicketQuantity || maxQuantity || limitPerTicket) {
            // Generate Group with inside variants info
            if (groupsWithSelectedVariantsInfo[id]) {
              // Set group limit
              if (
                groupsWithSelectedVariantsInfo[id].limit <
                stockBasedOnLimitation
              ) {
                groupsWithSelectedVariantsInfo[
                  id
                ].limit = stockBasedOnLimitation
              }

              // Set choosed variants info
              groupsWithSelectedVariantsInfo[id] = {
                ...groupsWithSelectedVariantsInfo[id],
                choosedVariants: {
                  ...groupsWithSelectedVariantsInfo[id].choosedVariants,
                  [variantId]: 0,
                },
              }
            } else {
              groupsWithSelectedVariantsInfo[id] = {
                limit: stockBasedOnLimitation,
                selectedCount: 0,
                choosedVariants: { [variantId]: 0 },
              }
            }
          }

          // Check stock admissibility with addon stock availability
          const allowedVariantStockCount = filterStockBasedOnAvailability(
            stockBasedOnLimitation,
            variantStock
          )

          // Generate options for variant
          const variantOptions = generateSelectOptions(
            0,
            allowedVariantStockCount
          )

          addonsWithOptions[variantId] = [...variantOptions]

          // Generate Group with its variants list
          groupsWithVariants[id] = {
            ...groupsWithVariants[id],
            [variantId]: allowedVariantStockCount,
          }
        }
      })
    } else {
      // Simple addon case, null checking is for unlimited stock value
      if (active && (simpleAddonStock > 0 || _isNull(simpleAddonStock))) {
        // Generate Addon Group allowed stock count based on limitations
        const stockBasedOnLimitation = generateStockBasedOnLimitations(
          addon,
          choosedTicketCount
        )

        // Check stock admissibility with addon stock availability
        const allowedVariantStockCount = filterStockBasedOnAvailability(
          stockBasedOnLimitation,
          simpleAddonStock
        )

        const addonOptions = generateSelectOptions(0, allowedVariantStockCount)
        addonsWithOptions[id] = [...addonOptions]
      }
    }
  })

  return {
    addonsWithOptions,
    groupsWithSelectedVariantsInfo,
    groupsWithVariants,
  }
}

export const getTicketRelatedAddons = (addons: any, ticketId: any) => {
  // Filter addons based on choosed ticket
  const filteredAddons: any = addons.filter(
    (addon: any) =>
      _isNull(addon.prerequisiteTicketTypeIds) ||
      addon.prerequisiteTicketTypeIds.includes(ticketId)
  )

  return filteredAddons
}

export const getSortedAddons = (addons: any, sortDirection = 'asc') => {
  const addonsCopy = [...addons]

  addonsCopy.forEach(addon => {
    if (addon.variants) {
      const unsortedVariants: any = []
      addon.variants.forEach((variant: any) => {
        unsortedVariants.push({
          ...variant,
          sortOrder: Number(variant.sortOrder),
        })
      })
      addon.sortOrder = Number(addon.variants[0].sortOrder)
      const sortedVariants = _sortBy(
        unsortedVariants,
        variant => variant.sortOrder
      )
      addon.variants = sortedVariants
    } else {
      addon.sortOrder = Number(addon.sortOrder)
    }
  })

  const sortedAddons = _sortBy(addonsCopy, addon => addon.sortOrder)
  if (sortDirection === 'desc') {
    return _reverse(sortedAddons)
  }

  return sortedAddons
}

export const isAtLeastOneAddonSelected = (value: any) => {
  const selectedAddons = Object.fromEntries(
    Object.entries(value).filter(([_, count]) => Number(count) !== 0)
  )

  return !_isEmpty(selectedAddons)
}
