import PropTypes from 'prop-types'
import {
  Typography,
  Badge,
  Input,
  InputNumber,
  Form,
  Select,
  DatePicker,
  Switch
} from 'antd'
import IdDisplay from './IdDisplay'
import TimeDisplay from './TimeDisplay'
import dayjs from 'dayjs'
import EmailDisplay from './EmailDisplay'
import UrlDisplay from './UrlDisplay'
import CountryDisplay from './CountryDisplay'
import CountrySelect from './CountrySelect'
import TagsDisplay from './TagsDisplay'
import TagsInput from './TagsInput'
import BoolDisplay from './BoolDisplay'
import ColorSelector from './ColorSelector'
import SecretDisplay from './SecretDisplay'
import EyeIcon from '../../Icons/EyeIcon'
import EyeSlashIcon from '../../Icons/EyeSlashIcon'
import { getPropertyValue } from '../../../database/ObjectModels'
import PropertyChanges from './PropertyChanges'
import NetGrossDisplay from './NetGrossDisplay'
import NetGrossInput from './NetGrossInput'
import ObjectList from './ObjectList'
import VarianceDisplay from './VarianceDisplay'
import OperationDisplay from './OperationDisplay'
import MarkdownDisplay from './MarkdownDisplay'
import MarkdownInput from './MarkdownInput'
import ObjectSelect from './ObjectSelect'
import ObjectDisplay from './ObjectDisplay'
import ObjectTypeSelect from './ObjectTypeSelect'
import ObjectTypeDisplay from './ObjectTypeDisplay'
import CodeBlockEditor from './CodeBlockEditor'
import StateDisplay from './StateDisplay'
import AlertsDisplay from './AlertsDisplay'
import FileUpload from './FileUpload'
import DataTree from './DataTree'
import FileList from './FileList'

const { Text } = Typography

const MATERIAL_OPTIONS = [
  { value: 'PLA', label: 'PLA' },
  { value: 'PETG', label: 'PETG' },
  { value: 'ABS', label: 'ABS' },
  { value: 'ASA', label: 'ASA' },
  { value: 'HIPS', label: 'HIPS' },
  { value: 'TPU', label: 'TPU' }
]

const ObjectProperty = ({
  type = 'text',
  prefix,
  suffix,
  value,
  min,
  max,
  difference,
  step,
  isEditing = false,
  formItemProps = {},
  required = false,
  name,
  label,
  showLabel = false,
  masterFilter = {},
  language = '',
  objectData = null,
  objectType = 'unknown',
  readOnly = false,
  disabled = false,
  empty = false,
  initial = false,
  height = 'auto',
  minimal = false,
  previewOpen = false,
  showPreview = true,
  options = [],
  showHyperlink,
  ...rest
}) => {
  if (value && typeof value == 'function' && objectData) {
    value = value(objectData)
  }

  if (objectType && typeof objectType == 'function' && objectData) {
    objectType = objectType(objectData)
  }

  if (disabled && typeof disabled == 'function' && objectData) {
    disabled = disabled(objectData)
  }

  if (empty && typeof empty == 'function' && objectData) {
    empty = empty(objectData)
  }

  if (difference && typeof difference == 'function' && objectData) {
    difference = difference(objectData)
  }

  if (prefix && typeof prefix == 'function' && objectData) {
    prefix = prefix(objectData)
  }

  if (suffix && typeof suffix == 'function' && objectData) {
    suffix = suffix(objectData)
  }

  if (masterFilter && typeof masterFilter == 'function' && objectData) {
    masterFilter = masterFilter(objectData)
  }

  if (!value) {
    value = getPropertyValue(objectData, name)
  }

  // Split the name by "." to handle nested object properties
  var formItemName = name

  if (name?.includes('.')) {
    formItemName = name ? name.split('.') : undefined
  }

  var textParams = { style: { whiteSpace: 'nowrap', minWidth: '0' } }

  if (disabled == true) {
    textParams = { ...textParams, delete: true, type: 'secondary' }
  }

  const renderProperty = () => {
    if (empty == true) {
      return <Text type='secondary'>n/a</Text>
    }
    if (!isEditing || (readOnly && !initial)) {
      switch (type) {
        case 'netGross':
          return (
            <NetGrossDisplay value={value} prefix={prefix} suffix={suffix} />
          )
        case 'secret':
          if (value != null) {
            return <SecretDisplay value={value} {...rest} />
          } else {
            return (
              <Text type='secondary' {...textParams}>
                n/a
              </Text>
            )
          }
        case 'wsprotocol':
          switch (value) {
            case 'ws':
              return <Text {...textParams}>Websocket</Text>
            case 'wss':
              return <Text {...textParams}>Websocket Secure</Text>
            default:
              return (
                <Text type='secondary' {...textParams}>
                  n/a
                </Text>
              )
          }
        case 'priceMode':
          switch (value) {
            case 'margin':
              return <Text {...textParams}>Margin %</Text>
            case 'amount':
              return <Text {...textParams}>£ Amount</Text>
            default:
              return (
                <Text type='secondary' {...textParams}>
                  n/a
                </Text>
              )
          }
        case 'bool': {
          if (value != null) {
            return <BoolDisplay value={value} yesNo={true} {...rest} />
          } else {
            return (
              <Text type='secondary' {...textParams}>
                n/a
              </Text>
            )
          }
        }
        case 'dateTime': {
          if (value != null) {
            return <TimeDisplay dateTime={value} {...rest} />
          } else {
            return (
              <Text type='secondary' {...textParams}>
                n/a
              </Text>
            )
          }
        }
        case 'country': {
          if (value != null) {
            return <CountryDisplay countryCode={value} />
          } else {
            return (
              <Text type='secondary' {...textParams}>
                n/a
              </Text>
            )
          }
        }
        case 'color': {
          if (value) {
            return <Badge color={value} text={value} />
          } else {
            return (
              <Text type='secondary' {...textParams}>
                n/a
              </Text>
            )
          }
        }
        case 'number': {
          if (value != null) {
            if (Array.isArray(value)) {
              return (
                <Text {...textParams}>
                  {prefix}
                  {value.length}
                  {suffix}
                </Text>
              )
            } else {
              return (
                <Text {...textParams}>
                  {prefix}
                  {typeof value === 'number' ? value.toFixed(2) : value}
                  {suffix}
                </Text>
              )
            }
          } else {
            return (
              <Text type='secondary' {...textParams}>
                n/a
              </Text>
            )
          }
        }
        case 'variance': {
          if (value != null) {
            return (
              <VarianceDisplay value={value} prefix={prefix} suffix={suffix} />
            )
          } else {
            return (
              <Text type='secondary' {...textParams}>
                n/a
              </Text>
            )
          }
        }
        case 'text':
          if (value != null && value != '') {
            return (
              <Text ellipsis>
                {prefix}
                {value}
                {suffix}
              </Text>
            )
          } else {
            return (
              <Text type='secondary' {...textParams}>
                n/a
              </Text>
            )
          }
        case 'codeBlock':
          if (value != null && value != '') {
            return (
              <CodeBlockEditor
                code={value}
                language={language}
                height={height}
                readOnly={true}
                minimal={minimal}
              />
            )
          } else {
            return (
              <Text type='secondary' {...textParams}>
                n/a
              </Text>
            )
          }
        case 'markdown':
          if (value != null && value != '') {
            return <MarkdownDisplay content={value} />
          } else {
            return (
              <Text type='secondary' {...textParams}>
                n/a
              </Text>
            )
          }
        case 'email':
          if (value != null && value != '') {
            return <EmailDisplay email={value} />
          } else {
            return (
              <Text type='secondary' {...textParams}>
                n/a
              </Text>
            )
          }
        case 'url':
          if (value != null && value != '') {
            return <UrlDisplay url={value} />
          } else {
            return (
              <Text type='secondary' {...textParams}>
                n/a
              </Text>
            )
          }
        case 'object': {
          if (value && value._id) {
            return <ObjectDisplay object={value} objectType={objectType} />
          } else {
            return (
              <Text type='secondary' {...textParams}>
                n/a
              </Text>
            )
          }
        }
        case 'objectType': {
          if (value) {
            return <ObjectTypeDisplay objectType={value} />
          } else {
            return (
              <Text type='secondary' {...textParams}>
                n/a
              </Text>
            )
          }
        }
        case 'objectList': {
          return <ObjectList value={value} objectType={objectType} />
        }
        case 'state': {
          if (value && value?.type) {
            return <StateDisplay {...rest} state={value} />
          } else {
            return (
              <Text type='secondary' {...textParams}>
                n/a
              </Text>
            )
          }
        }
        case 'material': {
          if (value) {
            return <Text {...textParams}>{value}</Text>
          } else {
            return (
              <Text type='secondary' {...textParams}>
                n/a
              </Text>
            )
          }
        }
        case 'id': {
          if (value) {
            return (
              <IdDisplay
                id={value}
                type={objectType}
                showHyperlink={showHyperlink}
                {...rest}
              />
            )
          } else {
            return (
              <Text type='secondary' {...textParams}>
                n/a
              </Text>
            )
          }
        }
        case 'density': {
          if (value != null) {
            return <Text {...textParams}>{`${value} g/cm³`}</Text>
          } else {
            return (
              <Text type='secondary' {...textParams}>
                n/a
              </Text>
            )
          }
        }
        case 'alerts': {
          if (value != null && value?.length != 0) {
            return <AlertsDisplay alerts={value} />
          } else {
            return (
              <Text type='secondary' {...textParams}>
                n/a
              </Text>
            )
          }
        }
        case 'tags': {
          if (value != null || value?.length != 0) {
            return <TagsDisplay tags={value} />
          } else {
            return (
              <Text type='secondary' {...textParams}>
                n/a
              </Text>
            )
          }
        }
        case 'operation': {
          if (value != null) {
            return <OperationDisplay operation={value} />
          } else {
            return (
              <Text type='secondary' {...textParams}>
                n/a
              </Text>
            )
          }
        }
        case 'propertyChanges': {
          return <PropertyChanges type={objectType} value={value} />
        }
        case 'data': {
          return <DataTree data={value} />
        }
        case 'file': {
          if (value == null || value?.length == 0 || value == undefined) {
            return (
              <Text type='secondary' {...textParams}>
                n/a
              </Text>
            )
          } else {
            return (
              <FileList
                files={value}
                multiple={false}
                card={false}
                defaultPreviewOpen={previewOpen}
                showPreview={showPreview}
                showInfo={showHyperlink}
              />
            )
          }
        }
        case 'fileList': {
          return (
            <FileList
              files={value}
              multiple={true}
              defaultPreviewOpen={previewOpen}
              showPreview={showPreview}
              showInfo={showHyperlink}
            />
          )
        }
        default: {
          if (value) {
            return <Text {...textParams}>{value}</Text>
          } else {
            return (
              <Text type='secondary' {...textParams}>
                n/a
              </Text>
            )
          }
        }
      }
    }

    // Editable mode: wrap in Form.Item
    // Merge required rule if needed
    let mergedFormItemProps = { ...formItemProps, style: { flexGrow: 1 } }
    if (required && disabled == false) {
      let rules
      if (mergedFormItemProps.rules) {
        rules = [...mergedFormItemProps.rules]
      } else {
        rules = []
      }
      const hasRequiredRule = rules.some((rule) => rule && rule.required)
      if (!hasRequiredRule) {
        rules.push({ required: true, message: '' })
      }
      mergedFormItemProps.rules = rules
    }
    // Remove name from mergedFormItemProps if present
    if (mergedFormItemProps.name) {
      delete mergedFormItemProps.name
    }
    // If label is provided, set it on Form.Item
    if (label && showLabel == true) {
      mergedFormItemProps.label = label
    }
    // Always apply style: { margin: 0 } unless overridden
    mergedFormItemProps.style = {
      margin: 0,
      ...(mergedFormItemProps.style || {})
    }
    switch (type) {
      case 'netGross':
        return (
          <Form.Item name={formItemName} {...mergedFormItemProps}>
            <NetGrossInput
              difference={difference}
              prefix={prefix}
              suffix={suffix}
            />
          </Form.Item>
        )
      case 'secret':
        return (
          <Form.Item name={formItemName} {...mergedFormItemProps}>
            <Input.Password
              placeholder={label}
              disabled={disabled}
              {...mergedFormItemProps}
              iconRender={(visible) =>
                visible ? <EyeSlashIcon /> : <EyeIcon />
              }
            />
          </Form.Item>
        )
      case 'wsprotocol':
        return (
          <Form.Item name={formItemName} {...mergedFormItemProps}>
            <Select
              defaultValue='ws'
              disabled={disabled}
              options={[
                { value: 'ws', label: 'Websocket' },
                { value: 'wss', label: 'Websocket Secure' }
              ]}
            />
          </Form.Item>
        )
      case 'select':
        return (
          <Form.Item name={formItemName} {...mergedFormItemProps}>
            <Select
              defaultValue={value}
              placeholder={'Select a ' + label.toLowerCase() + '...'}
              disabled={disabled}
              options={options}
            />
          </Form.Item>
        )
      case 'priceMode':
        return (
          <Form.Item name={formItemName} {...mergedFormItemProps}>
            <Select
              defaultValue='margin'
              disabled={disabled}
              options={[
                { value: 'margin', label: 'Margin %' },
                { value: 'amount', label: '£ Amount' }
              ]}
            />
          </Form.Item>
        )
      case 'bool':
        return (
          <Form.Item
            name={formItemName}
            {...mergedFormItemProps}
            valuePropName='checked'
          >
            <Switch disabled={disabled} />
          </Form.Item>
        )
      case 'dateTime':
        return (
          <Form.Item
            name={formItemName}
            {...mergedFormItemProps}
            getValueProps={(v) => ({ value: v ? dayjs(v) : null })}
          >
            <DatePicker
              showTime
              style={{ width: '100%' }}
              disabled={disabled}
            />
          </Form.Item>
        )
      case 'country':
        return (
          <Form.Item name={formItemName} {...mergedFormItemProps}>
            <CountrySelect disabled={disabled} />
          </Form.Item>
        )
      case 'color':
        return (
          <Form.Item
            name={formItemName}
            {...mergedFormItemProps}
            valuePropName='value'
            getValueFromEvent={(v) => v}
          >
            <ColorSelector required={required} disabled={disabled} />
          </Form.Item>
        )
      case 'weight':
        return (
          <Form.Item name={formItemName} {...mergedFormItemProps}>
            <InputNumber
              suffix='g'
              style={{ width: '100%' }}
              placeholder={label}
              disabled={disabled}
            />
          </Form.Item>
        )
      case 'number':
        return (
          <Form.Item name={formItemName} {...mergedFormItemProps}>
            <InputNumber
              placeholder={label}
              disabled={disabled}
              prefix={prefix}
              suffix={suffix}
              min={min}
              max={max}
              step={step}
              {...mergedFormItemProps}
              style={{ width: '100%' }}
            />
          </Form.Item>
        )
      case 'text':
        return (
          <Form.Item name={formItemName} {...mergedFormItemProps}>
            <Input
              placeholder={label}
              {...mergedFormItemProps}
              disabled={disabled}
            />
          </Form.Item>
        )
      case 'codeBlock':
        return (
          <Form.Item name={formItemName} {...mergedFormItemProps}>
            <CodeBlockEditor
              code={value}
              language={language}
              disabled={disabled}
              height={height}
              minimal={minimal}
            />
          </Form.Item>
        )
      case 'markdown':
        return (
          <Form.Item name={formItemName} {...mergedFormItemProps}>
            <MarkdownInput value={value} />
          </Form.Item>
        )
      case 'material':
        return (
          <Form.Item name={formItemName} {...mergedFormItemProps}>
            <Select
              options={MATERIAL_OPTIONS}
              placeholder={label}
              disabled={disabled}
            />
          </Form.Item>
        )
      case 'id':
        // id is not editable, just show view mode
        if (value) {
          return <IdDisplay id={value} type={objectType} {...rest} />
        } else {
          return (
            <Text type='secondary' {...textParams}>
              n/a
            </Text>
          )
        }
      case 'object':
        return (
          <Form.Item name={formItemName} {...mergedFormItemProps}>
            <ObjectSelect
              type={objectType}
              disabled={disabled}
              masterFilter={masterFilter}
            />
          </Form.Item>
        )
      case 'objectType':
        return (
          <Form.Item name={formItemName} {...mergedFormItemProps}>
            <ObjectTypeSelect disabled={disabled} />
          </Form.Item>
        )
      case 'objectList':
        return (
          <Form.Item name={formItemName} {...mergedFormItemProps}>
            <ObjectSelect type={objectType} multiple disabled={disabled} />
          </Form.Item>
        )
      case 'tags':
        return (
          <Form.Item name={formItemName} {...mergedFormItemProps}>
            <TagsInput />
          </Form.Item>
        )
      case 'file':
        return (
          <Form.Item name={formItemName} {...mergedFormItemProps}>
            <FileUpload
              value={value}
              multiple={false}
              defaultPreviewOpen={previewOpen}
              showPreview={showPreview}
              showInfo={showHyperlink}
            />
          </Form.Item>
        )
      case 'fileList':
        return (
          <Form.Item name={formItemName} {...mergedFormItemProps}>
            <FileUpload
              value={value}
              multiple={true}
              defaultPreviewOpen={previewOpen}
              showPreview={showPreview}
              showInfo={showHyperlink}
            />
          </Form.Item>
        )
      default:
        return (
          <Form.Item name={formItemName} {...mergedFormItemProps}>
            <Input placeholder={label} {...mergedFormItemProps} />
          </Form.Item>
        )
    }
  }

  const property = renderProperty()
  // Render the property directly (remove useDescriptions functionality)
  return property
}

ObjectProperty.propTypes = {
  type: PropTypes.string.isRequired,
  value: PropTypes.oneOfType([PropTypes.any, PropTypes.func]),
  isEditing: PropTypes.bool,
  formItemProps: PropTypes.object,
  masterFilter: PropTypes.object,
  required: PropTypes.bool,
  name: PropTypes.string,
  language: PropTypes.string,
  prefix: PropTypes.oneOfType([PropTypes.string, PropTypes.func]),
  suffix: PropTypes.oneOfType([PropTypes.string, PropTypes.func]),
  min: PropTypes.number,
  max: PropTypes.number,
  step: PropTypes.number,
  showLabel: PropTypes.bool,
  objectType: PropTypes.oneOfType([PropTypes.string, PropTypes.func]),
  readOnly: PropTypes.bool,
  disabled: PropTypes.oneOfType([PropTypes.bool, PropTypes.func]),
  empty: PropTypes.oneOfType([PropTypes.bool, PropTypes.func]),
  difference: PropTypes.oneOfType([PropTypes.any, PropTypes.func]),
  objectData: PropTypes.object,
  height: PropTypes.string,
  previewOpen: PropTypes.bool,
  showPreview: PropTypes.bool,
  showHyperlink: PropTypes.bool,
  options: PropTypes.array
}

export default ObjectProperty
