import { chartsFilterParams, chartsGroupByParams, chartsGroupByParams2, chartsFilterKeysMl, chartsMountParams, chartsBarTypesParams, chartsBarTypesGroupByParams, chartsBarTypesWithoutLayoutParams } from "./StaticData"
import {cond, uniq, has, T} from 'ramda'

const setPeriodCharts = (filterKeys) => {
  if (filterKeys && filterKeys.length > 0) return {period: 'dayly', title: '24 часа'}
  switch(filterKeys) {
  case 'commun': return {period: 'yearly', title: "год"}
  case 'rors': return {period: 'dayly', title: "на данный момент"}
  case 'routes': return {period: 'weekly', title: "две недели"}
  default: return {period: 'dayly', title: "на данный момент"}
  }
}

const setNamesMl = (filterKey) => {
  if (!filterKey) return null
  switch(filterKey) {
  case 'routes_common': return 'Обычные'
  case 'routes_emergency': return 'Аварийные'
  case 'routes_other': return 'Прочие'
  case 'routes_repair': return 'Ремонтные'
  case 'routes_without_leaving': return 'Без выезда'
  case 'routes_without_ml': return 'СПС без МЛ'
  default: return ''
  }
}

const setMachinesClass = (typeId) => {
  if (typeId) {
    switch(typeId) {
    case 'mpt_types': return 'МРТ'
    case 'gdsm_types': return 'ЖДСМ'
    case 'sm_pss_types': return 'СМ'
    default: return ''
    }
  }
}

const setFilterValues = (machineValue, filterParams) => {
  if(filterParams.values.includes(machineValue.toLowerCase())) {
    return {name: machineValue}
  }
}

const setCountMachinesMl = (arr, counter = 0) => {
  return arr.reduce((acc, item) => {
    if (item && item.length > 0) {
      return setCountMachinesMl(item, acc)
    } else {
      if (item.charts?.value) {
        acc = acc + item.charts?.value
      } else {
        acc
      }
    }
    return acc
  }, counter)
}

/* Charts updated data */

const chartsPie = (data, filterParams) => {
  // {list, _resp} = Agents.MachineList.get_machines(set_period_loading_charts(filterKey).period, params) apiHelpers

  const countMachines = data?.length
  const machines = data.reduce((acc, machine) => {
    if (machine[filterParams.filterKey]) {
      acc.push(setFilterValues(machine[filterParams.filterKey], filterParams))
    } else {
      acc
    }
    return acc
  }, [])

  // const isFilteredMachine = machines.find((el) => filterParams.values.includes(el.name.toLowerCase()))
  const groupByfiltered = machines.reduce((acc, machine) => {
    if (filterParams.values.includes(machine.name.toLowerCase())) {
      const count = machines.filter((el) => el.name === machine.name).length
      const filteredMachines = {name: machine.name, value: count}
      acc = uniq([...acc, filteredMachines])
    } else {
      acc
    }
    return acc
  }, [])
  return {countMachines: countMachines, period: setPeriodCharts(filterParams.filterKey).title, machines: groupByfiltered}
}

const chartsPieGroupedBy = (data, groupByParams, filterParams) => {

  const filteredGroupByParams = data.filter((machine) => machine[groupByParams.groupByKey] && machine[groupByParams.groupByKey].toLowerCase() === groupByParams.value)
  const countMachines = filteredGroupByParams?.length

  const machines = filteredGroupByParams.reduce((acc, machine) => {
      
    if (machine[filterParams.filterKey]) {
      acc.push(setFilterValues(machine[filterParams.filterKey], filterParams))
    } else {
      acc
    }
    return acc
  }, [])
    
  const filteredMachines = machines.reduce((acc, machine) => {
    if (filterParams.values.includes(machine.name.toLowerCase())) {
      const count = machines.filter((el) => el.name === machine.name).length
      const filteredMachines = {name: machine.name, value: count}
      acc = uniq([...acc, filteredMachines])
    } else {
      acc
    }
    return acc
  }, [])
  return {countMachines: countMachines, period: setPeriodCharts(filterParams.filterKey).title, machines: filteredMachines}
}

const chartsBarGroupedByMl = (data, filterKeysMl) => {

  const machinesWithMl = filterKeysMl.map((filterKey) => {
    const filteredWithMl = data.reduce((acc, machine) => {
      if (machine[filterKey] === 0 || machine[filterKey]) {
        acc = [...acc, {[filterKey]: machine[filterKey]}]
      } else {
        acc
      }
      return acc
    }, [])
    const count = filteredWithMl.reduce((acc, machine) => {
      acc = acc + parseFloat(machine[filterKey])
      return acc
    }, 0)
      
    return {key: filterKey, name: setNamesMl(filterKey), machinesCount: filteredWithMl.length, value: count}
  })
    
  // console.log('machinesWithMl', machinesWithMl)

  const countMachinesWithMl = Math.floor((machinesWithMl.reduce((acc, machine) => {
    return acc + machine.machinesCount
  }, 0)) / filterKeysMl.length)

  const machinesWithoutMl = filterKeysMl.map((filterKey) => {
    const countNull = data.reduce((acc, machine) => {
      if (machine[filterKey] === null) {
        acc = acc + 1
      } else {
        acc
      }
      return acc
    }, 0)
    return {key: filterKey, value: countNull}
  })

  // console.log('machinesWithoutMl', machinesWithoutMl)

  const countMachinesWithoutMl = Math.floor((machinesWithoutMl.reduce((acc, machine) => {
    return acc + machine.value
  }, 0)) / filterKeysMl.length // Либо только машины, если без деления тогда все null МЛ суммируются
  )

  machinesWithMl.push({key: 'routes_without_ml', name: setNamesMl('routes_without_ml'), value: countMachinesWithoutMl})

  return {countMachinesWithMl: countMachinesWithMl, period: setPeriodCharts(filterKeysMl).title, machines: machinesWithMl}
}

const chartsBarMount = (data, groupByKey, filterKey, countKey) => {

  const groupByData = Object.groupBy(data, (el) => el[groupByKey])

  const yAxisData = Object.entries(groupByData).map(([key, val]) => ({key: key, val: val.reduce((acc, val) => acc + val[countKey], 0)}))
  const xAxisData = Object.entries(groupByData).map(([key, groupArr]) => {
    const groupByFilterData = Object.groupBy(groupArr, (el) => el[filterKey])
    const newArr = Object.entries(groupByFilterData).map(([key, val]) => ({name: key, value: val.reduce((acc, val) => acc + val[countKey], 0)}))
    return {yAxisData: key, totalCount: groupArr.length, charts: newArr}
  })

  const countMounts = yAxisData.reduce((acc, year) => (acc + year.val), 0)

  return {yAxisData: yAxisData, xAxisData: xAxisData, countMounts: countMounts, filterKey: filterKey}
}

const chartsBarTypes = (data, groupByKey, filterKey, prevGroupByData, prevGroupByFilters) => {

  const countMachines = data.length
  const groupByData = Object.groupBy(data, (el) => el[groupByKey])

  const yAxisData = Object.entries(groupByData).map(([key, val]) => ({key: key, val: val.length}))
  const xAxisData = Object.entries(groupByData).map(([key, groupArr]) => {
    const groupByFilterData = Object.groupBy(groupArr, (el) => el[filterKey])
    const newArr = Object.entries(groupByFilterData).map(([key, val]) => ({name: key, value: val.length, linkData: groupByKey === 'machine_type' ? val.map((el) => ({machine_type: el.machine_type, device_number: el.device_number})) : ''}))
    return {yAxisData: key, totalCount: groupArr.length, charts: newArr}
  })

  return {yAxisData: yAxisData, xAxisData: xAxisData, countMachines: countMachines, period: setPeriodCharts(filterKey).title, filterKey: filterKey, groupByKey: groupByKey, prevGroupByData: prevGroupByData, prevGroupByFilters: prevGroupByFilters}
}

const chartsBarTypesGroupedBy = (data, groupByKey, filterKey, prevGroupByData, prevGroupByFilters, typeId) => {

  const machineClass = setMachinesClass(typeId)
  const machinesFilteredClass = data.filter(({machine_class}) => machine_class === machineClass)

  const groupByData = Object.groupBy(machinesFilteredClass, (el) => el[groupByKey])

  const yAxisData = Object.entries(groupByData).map(([key, val]) => ({key: key, val: val.length}))
  const xAxisData = Object.entries(groupByData).map(([key, groupArr]) => {
    const groupByFilterData = Object.groupBy(groupArr, (el) => el[filterKey])
    const newArr = Object.entries(groupByFilterData).map(([key, val]) => ({name: key, value: val.length, linkData: groupByKey === 'machine_type' ? val.map((el) => ({machine_type: el.machine_type, device_number: el.device_number})) : ''}))
    return {yAxisData: key, totalCount: groupArr.length, charts: newArr}
  })

  const countMachines = yAxisData.reduce((acc, type) => acc + type.val, 0)

  return {yAxisData: yAxisData, xAxisData: xAxisData, countMachines: countMachines, period: setPeriodCharts(filterKey).title, filterKey: filterKey, groupByKey: groupByKey, prevGroupByData: prevGroupByData, prevGroupByFilters: prevGroupByFilters, typeId: typeId}
}
  
const chartsBarTypesWithoutFirstLayout = (data, groupByKey, filterKey, prevGroupByData, prevGroupByFilters, groupByValue) => {

  const groupByData = Object.groupBy(data, (el) => el['org_type_name'])
  const filteredGroupByData = Object.entries(groupByData).filter(([key, ]) => key === groupByValue)

  if (filteredGroupByData.length === 0) return {yAxisData: [], xAxisData: [], countMachines: 0, period: setPeriodCharts(filterKey).title, filterKey: filterKey, groupByKey: groupByKey, prevGroupByData: prevGroupByData, prevGroupByFilters: prevGroupByFilters, groupByValue: groupByValue}

  const [groupedByGroupByKeyY] = filteredGroupByData.map(([, groupArr]) => Object.groupBy(groupArr, (el) => el[groupByKey]))
  const yAxisData = Object.entries(groupedByGroupByKeyY).map(([key, val]) => ({key: key, val: val.length}))
    
  const [groupedByGroupByKeyX] = filteredGroupByData.map(([, groupArr]) => Object.groupBy(groupArr, (el) => el[groupByKey]))
  const xAxisData = Object.entries(groupedByGroupByKeyX).map(([key, groupArr]) => {
    const groupByFilterData = Object.groupBy(groupArr, (el) => el[filterKey])
    const newArr = Object.entries(groupByFilterData).map(([key, val]) => ({name: key, value: val.length, linkData: groupByKey === 'machine_type' ? val.map((el) => ({machine_type: el.machine_type, device_number: el.device_number})) : ''}))
    return {yAxisData: key, totalCount: groupArr.length, charts: newArr}
  })

  const countMachines = yAxisData.reduce((acc, type) => acc + type.val, 0)

  return {yAxisData: yAxisData, xAxisData: xAxisData, countMachines: countMachines, period: setPeriodCharts(filterKey).title, filterKey: filterKey, groupByKey: groupByKey, prevGroupByData: prevGroupByData, prevGroupByFilters: prevGroupByFilters, groupByValue: groupByValue}
}

const chartsBarTypesGroupedByMl = (data, groupByKey, filterKeys, prevGroupByData, prevGroupByFilters) => {

  const groupByData = Object.groupBy(data, (el) => el[groupByKey])
  const yAxisData = Object.entries(groupByData).map(([key, val]) => {
    const allValuesArr = filterKeys.map((filterKey) => {
      const machinesWithMl = val.reduce((acc, el) => {
        if (el[filterKey] || el[filterKey] === 0) {
          acc = acc + el[filterKey]
        } else {
          acc
        }
        return acc
      }, 0)
      const machinesWithoutMl = val.filter((el) => el[filterKey] === null).length
      return {machinesWithMl: machinesWithMl, machinesWithoutMl: machinesWithoutMl}
    })
    // console.log('allValuesArr', allValuesArr)
    const countMachinesWithMl = allValuesArr.reduce((acc, count) => (acc + count.machinesWithMl), 0)
    const countMachinesWithoutMl = allValuesArr.reduce((acc, count) => (acc + count.machinesWithoutMl), 0) / filterKeys.length // Для исключения дублирования делим н а длину filterKeys
      
    return {key: key, val: countMachinesWithMl + countMachinesWithoutMl}
  })

  const xAxisData = Object.entries(groupByData).map(([key, groupArr]) => {
    return filterKeys.map((filterKey) => {
      const groupByFilterData = Object.groupBy(groupArr, (el) => el[filterKey])
      const newArr = Object.entries(groupByFilterData).map(([key, val]) => ({key: filterKey, name: key, value: val.reduce((acc, el) => el[filterKey] ? acc + el[filterKey] : acc, 0), linkData: groupByKey === 'machine_type' ? val.map((el) => ({machine_type: el.machine_type, device_number: el.device_number})) : ''}
      ))
      const machinesWithMl = newArr.reduce((acc, type) => {
        if (type.key === filterKey) {
          acc = {filterKey: filterKey, name: setNamesMl(filterKey), value: acc?.value + type.value, linkData: type.linkData}
        } else {
          acc = {filterKey: filterKey, name: setNamesMl(filterKey), value: acc?.value, linkData: type.linkData}
        }
        return acc
      }, {value: 0})
      // console.log('machinesWithMl', machinesWithMl)
      return {yAxisData: key, charts: machinesWithMl}
    })
  })

  const machinesWithoutMl =  Object.entries(groupByData).map(([key, val]) => {
    const countWithoutMl = val.filter((el) => filterKeys.find((filterKey) => el[filterKey] === null)).length
    return {yAxisData: key, charts: {filterKey: 'routes_without_ml', name: setNamesMl('routes_without_ml'), value: countWithoutMl, linkData: groupByKey === 'machine_type' ? val.map((el) => ({machine_type: el.machine_type, device_number: el.device_number})) : ''}}
  })

  const countMachinesWithMl = setCountMachinesMl(xAxisData)
  const countMachinesWithoutMl = Math.floor(setCountMachinesMl(machinesWithoutMl)) / filterKeys.length

  const updatedXAxisData = xAxisData.reduce((acc, group) => {
    const isFindGroup = machinesWithoutMl.find((machine) => machine.yAxisData === group[0].yAxisData)
    if (isFindGroup) {
      const updatedGroup = [...group, isFindGroup]
      acc.push(updatedGroup)
    } else {
      acc
    }
    return acc
  }, [])

  // console.log('updatedXAxisData', updatedXAxisData)

  return {yAxisData: yAxisData, xAxisData: updatedXAxisData, countMachinesWithMl: countMachinesWithMl, countMachinesWithoutMl: countMachinesWithoutMl, period: setPeriodCharts(filterKeys).title, groupByKey: groupByKey, prevGroupByData: prevGroupByData, prevGroupByFilters: prevGroupByFilters}
}
  
/* Charts updated data end */


const loadingChartsData = ({chartsSetup, data, dataMount, prevGroupByData, prevGroupByFilters}) => {

  // console.log('dataPie', chartsPie(data, chartsFilterParams[0]))
  // console.log('dataPieValue', chartsPieGroupByValue(data, chartsGroupByParams[0], chartsFilterParams[0]))
  // console.log('dataPieTypes', chartsPieGroupedBy(data, chartsGroupByParams2[0], chartsFilterParams[0]))
  // console.log('dataBarMl', chartsBarGroupedByMl(data, chartsFilterKeysMl))
  // console.log('dataBarMount', chartsBarMount(dataMount, 'year', 'client_type', 'device_count'))
  // console.log('chartsBarTypesGroupedByMl', chartsBarTypesGroupedByMl(data, 'org_type_name', chartsFilterKeysMl, {}, {}))

  const filteredPie = chartsFilterParams.reduce((acc, param) => {
    const idChart = `${param.filterKey}_pie`
    return {...acc, [idChart]: chartsPie(data, param)}}, {}) // Далее объединение всех типов графиков

  const filteredPieGroupByValue = chartsGroupByParams.reduce((acc, param) => {
    const idChart = `${chartsFilterParams[0].filterKey}_pie_${param.valueId}`
    return {...acc, [idChart]: chartsPieGroupedBy(data, param, chartsFilterParams[0])}}, {})

  const filteredPieGroupByTypes = chartsGroupByParams2.reduce((acc, param) => {
    const idChart = `${chartsFilterParams[0].filterKey}_pie_${param.valueId}`
    return {...acc, [idChart]: chartsPieGroupedBy(data, param, chartsFilterParams[0])}}, {})

  const filteredBarGroupByMl = {[`${chartsFilterParams[1].filterKey}_bar`]: chartsBarGroupedByMl(data, chartsFilterKeysMl)}

  const filteredBarMount = chartsMountParams.reduce((acc, param) => {
    const idChart = `mount_${param.filterKey}_bar`
    return {...acc, [idChart]: chartsBarMount(dataMount, param.groupByKey, param.filterKey, param.countKey)}}, {})

  const filteredBarTypes = chartsBarTypesParams.reduce((acc, param) => {
    const idChart = `${param.filterKey}_${param.valueId}_bar`
    return {...acc, [idChart]: chartsBarTypes(data, param.groupByKey, param.filterKey, prevGroupByData, prevGroupByFilters)}}, {})

  const filteredBarGroupByTypes = chartsBarTypesGroupByParams.reduce((acc, param) => {
    const idChart = `${param.filterKey}_${param.valueId}_bar_${param.typeId}`
    return {...acc, [idChart]: chartsBarTypesGroupedBy(data, param.groupByKey, param.filterKey, prevGroupByData, prevGroupByFilters, param.typeId)}}, {})

  const filteredBarWithoutLayoutTypes = chartsBarTypesWithoutLayoutParams.reduce((acc, param) => {
    const idChart = `${param.filterKey}_types_bar_${param.valueId}`
    return {...acc, [idChart]: chartsBarTypesWithoutFirstLayout(data, param.groupByKey, param.filterKey, prevGroupByData, prevGroupByFilters, param.groupByValue)}}, {})

  const filteredBarGroupByMlTypes = {[`${chartsFilterParams[1].filterKey}_types_bar_ml`]: chartsBarTypesGroupedByMl(data, 'org_type_name', chartsFilterKeysMl, prevGroupByData, prevGroupByFilters)}
    
  const allCharts = {...filteredPie, ...filteredPieGroupByValue, ...filteredPieGroupByTypes, ...filteredBarGroupByMl, ...filteredBarMount, ...filteredBarTypes, ...filteredBarGroupByTypes, ...filteredBarWithoutLayoutTypes, ...filteredBarGroupByMlTypes}

  console.log('allCharts', allCharts)

  // console.log('this.charts', data)
  const main = chartsSetup.main.reduce((acc, chart) => {
    if (allCharts[chart.id]) {
      const newChart = {...chart, data: allCharts[chart.id]}
      acc = [...acc, newChart]
    } else {
      acc
    }
    return acc
        
  }, [])
  const types = chartsSetup.types.reduce((acc, chart) => {
    if (allCharts[chart.id]) {
      const newChart = {...chart, data: allCharts[chart.id]}
      acc = [...acc, newChart]
    } else {
      acc
    }
    return acc
        
  }, [])
  return {...chartsSetup, main: main, types: types}
}

const setBarTypesChart = (activeChartParams, prevGroupByData, prevGroupByFilters, defaultData) => {
  switch (activeChartParams.type) {
  case 'default': {
    const dataDefault = chartsBarTypes(defaultData, activeChartParams.groupByKey, activeChartParams.filterKey, prevGroupByData, prevGroupByFilters)
    // const updatedData = currentData.types.reduce((acc, chart) => {
    //   if (chart.id === activeChartParams.id) {
    //     const newChart = {...chart, data: data}
    //     acc = [...acc, newChart]
    //   } else {
    //     acc = [...acc, chart]
    //   }
    //   return acc
    // }, [])
    // return {main: currentData.main, types: updatedData}
    return dataDefault
  }
    
  case 'without_first_layout': {
    const dataWithoutFirstLayout = chartsBarTypesWithoutFirstLayout(defaultData, activeChartParams.groupByKey, activeChartParams.filterKey, prevGroupByData, prevGroupByFilters, activeChartParams.groupByValue)
    return dataWithoutFirstLayout
  }
    
  case 'types': {
    const dataGroupBy = chartsBarTypesGroupedBy(defaultData, activeChartParams.groupByKey, activeChartParams.filterKey, prevGroupByData, prevGroupByFilters, activeChartParams.groupByValue)
    return dataGroupBy
  }
    
  case 'ml': {
    const dataMl = chartsBarTypesGroupedByMl(defaultData, activeChartParams.groupByKey, chartsFilterKeysMl, prevGroupByData, prevGroupByFilters)
    return dataMl
  }
  }
}
  
const setNextLayoutGroupByKey = (groupByKey, prevGroupByValue) => {
  if (prevGroupByValue === 'без типа') return null
  switch (groupByKey) {
  case 'org_type_name': return 'railway_name'
  case 'railway_name': return 'org_name'
  case 'org_name': return 'type'
  case 'type': return 'machine_type'
  case 'zav_nomer': return 'machine_type'
  default: return null
  }
}

const setBeforeLayoutGroupByData = (prevGroupByData, prevGroupByFilters, type) => {
  return cond([
    [has('type'), () => ({org_name: prevGroupByFilters['org_name']})],
    [has('org_name'), () => ({railway_name: prevGroupByFilters['railway_name']})],
    [has('railway_name'), () => (type === 'without_first_layout' ? {} : {org_type_name: prevGroupByFilters['org_type_name']})],
    [T, () => {}],
  ])(prevGroupByData)
}

const typesCharts = (type) => {
  switch (type) {
  case 'pie': return true
  case 'mount': return true
  case 'mainMl': return true
  default: return false
  }
}

export { loadingChartsData, setBarTypesChart, setNextLayoutGroupByKey, setBeforeLayoutGroupByData, typesCharts }