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

import FilamentStockDisplay from './FilamentStockDisplay'

const FilamentStockSelect = ({ onChange, filter, useFilter, value }) => {
  const [filamentStocksTreeData, setFilamentStocksTreeData] = useState([])
  const [filamentStocksData, setFilamentStocksData] = useState([])
  const [loading, setLoading] = useState(false)
  const [defaultValue, setDefaultValue] = useState(value)

  const getFilamentStockTitle = (filamentStock) => {
    return (
      <FilamentStockDisplay filamentStock={filamentStock} showCopy={false} />
    )
  }

  const fetchFilamentStocksData = async (property, filter) => {
    setLoading(true)
    try {
      const response = await axios.get(`${config.backendUrl}/filamentstocks`, {
        params: {
          ...filter,
          property
        },
        headers: {
          Accept: 'application/json'
        },
        withCredentials: true
      })
      setLoading(false)
      return response.data
    } catch (err) {
      console.error(err)
    }
  }

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

      const filamentStockData = await fetchFilamentStocksData(null, filter)
      setFilamentStocksData(filamentStockData)

      for (const filamentStock of filamentStockData) {
        const newNode = {
          id: filamentStock._id,
          pId: node.id,
          value: filamentStock._id,
          key: filamentStock._id,
          title: getFilamentStockTitle(filamentStock),
          isLeaf: true
        }

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

  const handleFilamentStocksTreeLoad = useCallback(
    async (node) => {
      if (node) {
        await generateFilamentStockTreeNodes(node)
      } else {
        await generateFilamentStockTreeNodes({ id: 0 })
      }
    },
    [generateFilamentStockTreeNodes]
  )

  const handleOnChange = (value, selectedOptions) => {
    const filamentStockObject = filamentStocksData.filter(
      (filamentStock) => filamentStock._id === value
    )[0]

    onChange(filamentStockObject, selectedOptions)
  }

  useEffect(() => {
    if (value?._id != null) {
      setDefaultValue(value)
    }
  }, [value])

  useEffect(() => {
    if (defaultValue != undefined) {
      const newNode = {
        id: defaultValue._id,
        pId: 0,
        value: defaultValue._id,
        key: defaultValue._id,
        title: getFilamentStockTitle(defaultValue),
        isLeaf: true
      }
      setFilamentStocksTreeData([newNode])
    } else {
      setFilamentStocksTreeData([])
    }
    if (useFilter === true) {
      generateFilamentStockTreeNodes({ id: 0 }, filter)
    } else {
      handleFilamentStocksTreeLoad(null)
    }
  }, [useFilter, defaultValue, filter])

  return (
    <TreeSelect
      treeDataSimpleMode
      value={defaultValue?._id}
      loadData={handleFilamentStocksTreeLoad}
      treeData={filamentStocksTreeData}
      onChange={handleOnChange}
      loading={loading}
      placeholder='Select a filament stock'
    />
  )
}

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

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

export default FilamentStockSelect
