/**
 * @description Returns the difference between two arrays of primitive values.
 * @param a - The first array to compare.
 * @param b - The second array to compare.
 * @returns - An array containing elements that are present in one array but not the other.
 */
export function diffCollection<T extends PropertyKey>(a: T[], b: T[]) {
  const totalCollect = [
    ...a.filter((val) => !b.includes(val)),
    ...b.filter((val) => !a.includes(val)),
  ]
  return totalCollect.filter((_, index) => totalCollect.indexOf(_) === index)
}

/**
 * @description This function calculates the difference between two collections of items and returns the updated collection based on the difference.
 * @template T - the type of the keys in the collections.
 * @template U - the type of the objects in the collections.
 * @template K - the type of the key to be used to compare objects in the collections.
 * @param  oldSelectKeys - the original collection of keys.
 * @param  newSelectKeys - the new collection of keys.
 * @param  oldSelected - the original collection of objects.
 * @param  newSelected - the new collection of objects.
 * @param  key - the key to be used to compare objects in the collections.
 * @return  the updated collection of objects based on the difference between the two collections of keys.
 */
export function multipleSelectFilter<
  T extends string | number,
  U extends object,
  K extends keyof U,
>(
  oldSelectKeys: T[],
  newSelectKeys: T[],
  oldSelected: U[],
  newSelected: U[],
  key: K,
) {
  // 求出两个值的差集
  const diff = diffCollection(oldSelectKeys, newSelectKeys)
  type diffStatusType = 'add' | 'remove'
  const diffStatus = diff.reduce<{ id: T; status: diffStatusType }[]>(
    (acc, id) => {
      let status: diffStatusType = 'add'
      if (oldSelectKeys.includes(id)) {
        status = 'remove'
      }
      acc.push({ id, status })
      return acc
    },
    [],
  )
  return diffStatus.reduce<U[]>(
    (acc, cur) => {
      if (cur.status === 'add') {
        const data = newSelected.find((val) => val[key] === cur.id)
        data && acc.push(data)
      } else {
        // 删除
        const index = acc.findIndex((val) => val[key] === cur.id)
        if (index > -1) acc.splice(index, 1)
      }
      return acc
    },
    [...oldSelected],
  )
}
