import PropTypes from 'prop-types'
import { Descriptions, Typography, Flex } from 'antd'
import { getModelProperty } from '../../../database/ObjectModels'
import ObjectProperty from './ObjectProperty'
import ArrowRightIcon from '../../Icons/ArrowRightIcon'

const { Text } = Typography

const PropertyChanges = ({ type, value }) => {
  if (!value || (!value.new && !value.old)) {
    return <Text type='secondary'>n/a</Text>
  }

  // Helper to flatten nested objects into dot notation keys
  function flattenObject(obj, prefix = '', res = {}) {
    for (const key in obj) {
      if (Object.prototype.hasOwnProperty.call(obj, key)) {
        const val = obj[key]
        const newKey = prefix ? `${prefix}.${key}` : key

        // Keep model references and special value objects intact
        if (
          val &&
          typeof val === 'object' &&
          !Array.isArray(val) &&
          !Object.prototype.hasOwnProperty.call(val, '_id') &&
          key !== 'state' &&
          key !== 'netGross'
        ) {
          flattenObject(val, newKey, res)
        } else {
          res[newKey] = val
        }
      }
    }
    return res
  }

  const flatOld = value?.old ? flattenObject(value.old) : {}
  const flatNew = value?.new ? flattenObject(value.new) : {}
  const combinedChanges = {
    ...flatOld,
    ...flatNew
  }

  return (
    <Descriptions size='small' column={1}>
      {Object.keys(combinedChanges).map((key) => {
        var changeProperty = getModelProperty(type, key)

        if (!changeProperty) {
          return null
        }
        return (
          <Descriptions.Item key={key} label={changeProperty.label}>
            <Flex
              gap={'small'}
              style={{ minWidth: 0, width: '100%' }}
              className='property-changes'
            >
              {value?.old ? (
                <ObjectProperty
                  {...changeProperty}
                  longId={false}
                  minimal={true}
                  showPreview={false}
                  objectData={value?.old}
                  maxWidth='200px'
                />
              ) : null}
              {value?.old && value?.new ? (
                <Text type='secondary'>
                  <ArrowRightIcon />
                </Text>
              ) : null}
              {value?.new ? (
                <ObjectProperty
                  {...changeProperty}
                  longId={false}
                  minimal={true}
                  showPreview={false}
                  objectData={value?.new}
                  maxWidth='200px'
                />
              ) : null}
            </Flex>
          </Descriptions.Item>
        )
      })}
    </Descriptions>
  )
}

PropertyChanges.propTypes = {
  type: PropTypes.string.isRequired,
  value: PropTypes.shape({
    old: PropTypes.object,
    new: PropTypes.object
  })
}

export default PropertyChanges
