// FilamentSelect.js
import { TreeSelect, Badge } from 'antd'
import React, { useEffect, useState, useCallback } from 'react'
import PropTypes from 'prop-types'
import axios from 'axios'

import config from '../../../config'

const propertyOrder = ['diameter', 'type', 'vendor.name']

const FilamentSelect = ({ onChange, filter, useFilter, value }) => {
  const [filamentsTreeData, setFilamentsTreeData] = useState([])
  const [filamentsData, setFilamentsData] = useState([])
  const [loading, setLoading] = useState(false)
  const [defaultValue, setDefaultValue] = useState(value)

  const fetchFilamentsData = async (property, filter) => {
    setLoading(true)
    try {
      const response = await axios.get(`${config.backendUrl}/filaments`, {
        params: {
          ...filter,
          property
        },
        headers: {
          Accept: 'application/json'
        },
        withCredentials: true
      })
      setLoading(false)
      return response.data
      //setPagination({ ...pagination, total: response.data.totalItems }); // Update total count
    } catch (err) {
      console.error(err)
    }
  }

  function getByPath(obj, path) {
    return path.split('.').reduce((acc, part) => acc && acc[part], obj)
  }

  const getFilter = useCallback(
    (node) => {
      var filter = {}
      var currentId = node.id
      while (currentId != 0) {
        const currentNode = filamentsTreeData.filter(
          (treeData) => treeData['id'] === currentId
        )[0]
        filter[propertyOrder[currentNode.propertyId]] = currentNode.value
        currentId = currentNode.pId
      }
      return filter
    },
    [filamentsTreeData]
  )

  const generateFilamentTreeNodes = useCallback(
    async (node = null, filter = null) => {
      if (!node) {
        return
      }

      if (filter === null) {
        filter = getFilter(node)
      }

      const filamentData = await fetchFilamentsData(null, filter)

      setFilamentsData(filamentData)

      for (var i = 0; i < filamentData.length; i++) {
        const filament = filamentData[i]

        const newNode = {
          id: filament._id,
          pId: node.id,
          value: filament._id,
          key: filament._id,
          title: <Badge color={filament.color} text={filament.name} />,
          isLeaf: true
        }

        setFilamentsTreeData((prev) => {
          const filtered = prev.filter((node) => node.id !== newNode.id)
          return [...filtered, newNode]
        })
      }
    },
    [filamentsTreeData, getFilter]
  )

  const generateFilamentCategoryTreeNodes = useCallback(
    async (node = null) => {
      var filter = {}

      var propertyId = 0

      if (!node) {
        node = {}
        node.id = 0
      } else {
        filter = getFilter(node)
        propertyId = node.propertyId + 1
      }

      const propertyName = propertyOrder[propertyId]

      const propertyData = await fetchFilamentsData(propertyName, filter)

      for (var i = 0; i < propertyData.length; i++) {
        const property = getByPath(propertyData[i], propertyName)
        const newNode = {
          id: property,
          pId: node.id,
          value: property,
          key: property,
          propertyId: propertyId,
          title: property,
          isLeaf: false,
          selectable: false
        }

        setFilamentsTreeData((prev) => {
          if (prev.some((node) => node.id === newNode.id)) {
            return prev // already added
          }
          return [...prev, newNode]
        })
      }
    },
    [getFilter]
  )

  const handleFilamentsTreeLoad = useCallback(
    async (node) => {
      if (node) {
        if (node.propertyId !== propertyOrder.length - 1) {
          await generateFilamentCategoryTreeNodes(node)
        } else {
          await generateFilamentTreeNodes(node) // End of properties
        }
      } else {
        await generateFilamentCategoryTreeNodes(null) // First property
      }
    },
    [generateFilamentTreeNodes, generateFilamentCategoryTreeNodes]
  )

  const handleOnChange = (value, selectedOptions) => {
    console.log('Handle onchange')
    const filamentObject = filamentsData.filter(
      (filament) => filament._id == value
    )[0]

    onChange(filamentObject, selectedOptions)
  }

  useEffect(() => {
    if (value?._id != null) {
      console.log('Setting default value...', value)
      setDefaultValue(value)
    }
  }, [value])

  useEffect(() => {
    console.log('Use Filter', useFilter)
    if (defaultValue != undefined) {
      const newNode = {
        id: defaultValue._id,
        pId: 0,
        value: defaultValue._id,
        key: defaultValue._id,
        title: <Badge color={defaultValue.color} text={defaultValue.name} />,
        isLeaf: true
      }
      console.log('setting new node')
      setFilamentsTreeData([newNode])
    } else {
      setFilamentsTreeData([])
    }
    if (useFilter === true) {
      generateFilamentTreeNodes({ id: 0 }, filter)
    } else {
      handleFilamentsTreeLoad(null)
    }
  }, [useFilter, defaultValue, filter])

  return (
    <TreeSelect
      treeDataSimpleMode
      value={defaultValue?._id}
      loadData={handleFilamentsTreeLoad}
      treeData={filamentsTreeData}
      onChange={handleOnChange}
      loading={loading}
    />
  )
}

FilamentSelect.propTypes = {
  onChange: PropTypes.func.isRequired,
  value: PropTypes.object,
  filter: PropTypes.object,
  useFilter: PropTypes.bool
}

FilamentSelect.defaultProps = {
  filter: {},
  useFilter: false
}

export default FilamentSelect
