// GCodeFileSelect.js
import PropTypes from 'prop-types'
import { TreeSelect, Badge, Space, message } from 'antd'
import React, { useEffect, useState, useContext } from 'react'
import axios from 'axios'
import GCodeFileIcon from '../../Icons/GCodeFileIcon'
import { AuthContext } from '../../Auth/AuthContext'

const propertyOrder = ['filament.diameter', 'filament.type', 'filament.brand']

const GCodeFileSelect = ({ onChange, filter, useFilter }) => {
  const [gcodeFilesTreeData, setGCodeFilesTreeData] = useState(null)
  const [loading, setLoading] = useState(true)
  const [searchValue, setSearchValue] = useState('')
  const [messageApi] = message.useMessage()

  const { authenticated } = useContext(AuthContext)

  const fetchGCodeFilesData = async (property, filter, search) => {
    if (!authenticated) {
      return
    }
    setLoading(true)
    try {
      const response = await axios.get('http://localhost:8080/gcodefiles', {
        params: {
          ...filter,
          search,
          property
        },
        headers: {
          Accept: 'application/json'
        },
        withCredentials: true // Important for including cookies
      })
      setLoading(false)
      return response.data
      // setPagination({ ...pagination, total: response.data.totalItems }); // Update total count
    } catch (error) {
      if (error.response) {
        // For other errors, show a message
        messageApi.error('Error fetching GCode files:', error.response.status)
      } else {
        messageApi.error(
          'An unexpected error occurred. Please try again later.'
        )
      }
    }
  }

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

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

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

    let search = null
    if (searchValue != '') {
      search = searchValue
    }

    const gcodeFileData = await fetchGCodeFilesData(null, filter, search)

    let newNodeList = []

    for (var i = 0; i < gcodeFileData.length; i++) {
      const gcodeFile = gcodeFileData[i]
      const random = Math.random().toString(36).substring(2, 6)

      const newNode = {
        id: random,
        pId: node.id,
        value: gcodeFile._id,
        key: gcodeFile._id,
        title: (
          <Space>
            <GCodeFileIcon />
            <Badge
              color={gcodeFile.filament.color}
              text={gcodeFile.name + ' (' + gcodeFile.filament.name + ')'}
            />
          </Space>
        ),
        isLeaf: true
      }

      newNodeList.push(newNode)
    }
    return newNodeList
  }

  const generateGCodeFileCategoryTreeNodes = 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 fetchGCodeFilesData(propertyName, filter)

    const newNodeList = []

    for (var i = 0; i < propertyData.length; i++) {
      const property =
        propertyData[i][propertyName.split('.')[0]][propertyName.split('.')[1]]
      const random = Math.random().toString(36).substring(2, 6)

      const newNode = {
        id: random,
        pId: node.id,
        value: property + '-' + random,
        key: property + '-' + random,
        propertyId: propertyId,
        title: property,
        isLeaf: false,
        selectable: false
      }

      newNodeList.push(newNode)
    }

    return newNodeList
  }

  const handleGCodeFilesTreeLoad = async (node) => {
    if (node) {
      if (node.propertyId !== propertyOrder.length - 1) {
        setGCodeFilesTreeData(
          gcodeFilesTreeData.concat(
            await generateGCodeFileCategoryTreeNodes(node)
          )
        )
      } else {
        setGCodeFilesTreeData(
          gcodeFilesTreeData.concat(await generateGCodeFileTreeNodes(node))
        ) // End of properties
      }
    } else {
      setGCodeFilesTreeData(await generateGCodeFileCategoryTreeNodes(null)) // First property
    }
  }

  const handleGCodeFilesSearch = (value) => {
    setSearchValue(value)
    setGCodeFilesTreeData(null)
  }

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

  useEffect(() => {
    if (gcodeFilesTreeData === null) {
      if (useFilter === true || searchValue != '') {
        setGCodeFilesTreeData(generateGCodeFileTreeNodes({ id: 0 }, filter))
      } else {
        handleGCodeFilesTreeLoad(null)
      }
    }
  }, [gcodeFilesTreeData])

  return (
    <TreeSelect
      showSearch
      treeDataSimpleMode
      loadData={handleGCodeFilesTreeLoad}
      treeData={gcodeFilesTreeData}
      onChange={onChange}
      onSearch={handleGCodeFilesSearch}
      loading={loading}
    />
  )
}

GCodeFileSelect.propTypes = {
  onChange: PropTypes.func.isRequired,
  filter: PropTypes.string.isRequired,
  useFilter: PropTypes.bool.isRequired
}

export default GCodeFileSelect
