import { Transfer, Tree, Badge, Spin } from 'antd'
import React, { useEffect, useState, useContext, useRef } from 'react'
import PropTypes from 'prop-types'
import axios from 'axios'
import { AuthContext } from '../../Auth/AuthContext'
//
const propertyOrder = ['products']

const PartTransfer = ({
  onChange,
  filter,
  useFilter,
  selectedKeys: initialSelectedKeys
}) => {
  const [partsTreeData, setPartsTreeData] = useState([])
  const [targetKeys, setTargetKeys] = useState(initialSelectedKeys || [])
  const { token } = useContext(AuthContext)
  const tokenRef = useRef(token)
  const [loading, setLoading] = useState(true)

  const fetchPartsData = async (property, filter) => {
    setLoading(true)
    try {
      const response = await axios.get(`${config.backendUrl}/parts', {
        params: {
          ...filter,
          property
        },
        headers: {
          Authorization: `Bearer ${tokenRef.current}`
        }
      })
      setLoading(false)
      return response.data
    } catch (err) {
      console.error(err)
      setLoading(false)
      return []
    }
  }

  const getFilter = (node) => {
    let filter = {}
    let currentId = node.id
    while (currentId !== 0) {
      const currentNode = partsTreeData.find(
        (treeData) => treeData.id === currentId
      )
      if (currentNode) {
        filter[propertyOrder[currentNode.propertyId]] =
          currentNode.value.split('-')[0]
        currentId = currentNode.pId
      } else {
        break
      }
    }
    return filter
  }

  const generatePartTreeNodes = async (node = null, filter = null) => {
    if (!node) return

    const actualFilter = filter === null ? getFilter(node) : filter
    const partData = await fetchPartsData(null, actualFilter)

    const newNodeList = partData.map((part) => ({
      id: part._id,
      pId: node.id,
      value: part._id,
      key: part._id,
      title: <Badge color={part.color} text={part.name} />,
      isLeaf: true
    }))

    setPartsTreeData((prev) => [...prev, ...newNodeList])
  }

  const generatePartCategoryTreeNodes = async (node = null) => {
    let filter = {}
    let propertyId = 0

    if (node) {
      filter = getFilter(node)
      propertyId = node.propertyId + 1
    }

    const propertyName = propertyOrder[propertyId]
    const propertyData = await fetchPartsData(propertyName, filter)

    const newNodeList = propertyData.map((data) => {
      const property = data[propertyName]
      const random = Math.random().toString(36).substring(2, 6)
      return {
        id: random,
        pId: node ? node.id : '0',
        value: `${property}-${random}`,
        key: `${property}-${random}`,
        propertyId: propertyId,
        title: property,
        isLeaf: false,
        selectable: false
      }
    })

    setPartsTreeData((prev) => [...prev, ...newNodeList])
  }

  const handleTreeLoad = async (node) => {
    if (node) {
      if (node.propertyId !== propertyOrder.length - 1) {
        await generatePartCategoryTreeNodes(node)
      } else {
        await generatePartTreeNodes(node)
      }
    } else {
      await generatePartCategoryTreeNodes(null)
    }
  }

  useEffect(() => {
    setPartsTreeData([])
  }, [token, filter, useFilter])

  useEffect(() => {
    if (partsTreeData.length === 0) {
      if (useFilter) {
        generatePartTreeNodes({ id: '0' }, filter)
      } else {
        handleTreeLoad(null)
      }
    }
  }, [partsTreeData.length])

  const transferDataSource = partsTreeData.filter((node) => node.isLeaf)

  const renderTransferItem = (item) => item.title

  const handleTransferChange = (newTargetKeys) => {
    setTargetKeys(newTargetKeys)
    onChange(newTargetKeys)
  }

  const renderSourceList = ({ onItemSelect }) => {
    const treeData = partsTreeData
      .map((node) => ({
        ...node,
        children: partsTreeData
          .filter((child) => child.pId === node.id)
          .map((child) => ({
            ...child,
            children: partsTreeData.filter(
              (grandChild) => grandChild.pId === child.id
            )
          }))
      }))
      .filter((node) => !node.pId)

    return (
      <Tree
        loadData={(node) => handleTreeLoad(node)}
        treeData={treeData}
        onSelect={(selectedKeys, { node }) => {
          if (node.isLeaf) {
            onItemSelect(node.key, !selectedKeys.includes(node.key))
          }
        }}
      />
    )
  }

  if (loading && partsTreeData.length === 0) {
    return <Spin />
  }

  return (
    <Transfer
      dataSource={transferDataSource}
      targetKeys={targetKeys}
      onChange={handleTransferChange}
      render={renderTransferItem}
      showSelectAll={true}
      oneWay={false}
      pagination
      listStyle={{
        width: 300,
        height: 400
      }}
    >
      {renderSourceList}
    </Transfer>
  )
}

PartTransfer.propTypes = {
  onChange: PropTypes.func.isRequired,
  filter: PropTypes.object,
  useFilter: PropTypes.bool,
  selectedKeys: PropTypes.arrayOf(PropTypes.string)
}

PartTransfer.defaultProps = {
  filter: {},
  useFilter: false,
  selectedKeys: []
}

export default PartTransfer
