import { useContext, useState, useEffect } from 'react'
import {
  Descriptions,
  Button,
  Typography,
  Flex,
  Space,
  Dropdown,
  message,
  Tag,
  Input,
  InputNumber,
  Select
} from 'antd'
import ReloadIcon from '../../Icons/ReloadIcon.jsx'
import CloudIcon from '../../Icons/CloudIcon.jsx'
import { ApiServerContext } from '../context/ApiServerContext.jsx'
import BoolDisplay from '../common/BoolDisplay.jsx'
import InfoCollapse from '../common/InfoCollapse.jsx'
import loglevel from 'loglevel'
import config from '../../../config'
const logger = loglevel.getLogger('ApiContextDebug')
logger.setLevel(config.logLevel)

const { Text, Paragraph } = Typography

const ApiContextDebug = () => {
  const {
    apiServer,
    error,
    connecting,
    connected,
    fetchLoading,
    lockObject,
    unlockObject,
    fetchObjectLock,
    updateObject,
    createObject,
    deleteObject,
    subscribeToObjectUpdates,
    subscribeToObjectEvent,
    subscribeToObjectTypeUpdates,
    subscribeToObjectLock,
    fetchObject,
    fetchObjects,
    fetchObjectsByProperty,
    fetchSpotlightData,
    fetchFileContent,
    fetchTemplatePreview,
    fetchNotes,
    fetchHostOTP,
    sendObjectAction
  } = useContext(ApiServerContext)

  const [msgApi, contextHolder] = message.useMessage()
  const [connectionStatus, setConnectionStatus] = useState('disconnected')
  const [socketId, setSocketId] = useState(null)

  // Test input states
  const [testInputs, setTestInputs] = useState({
    objectId: 'test-id',
    objectType: 'user',
    hostId: 'test-host-id',
    parentId: 'test-parent-id',
    fileName: 'test.gcode',
    query: 'test query',
    action: 'start',
    eventType: 'status',
    properties: ['name', 'email'],
    filter: { active: true },
    scale: 1.0,
    templateContent: 'Test template content',
    testObject: { name: 'Test Object' }
  })

  // Collapse states
  const [collapseStates, setCollapseStates] = useState({
    fetchTests: false,
    crudTests: false,
    subscriptionTests: false,
    specialTests: false
  })

  useEffect(() => {
    if (apiServer) {
      setConnectionStatus(apiServer.connected ? 'connected' : 'disconnected')
      setSocketId(apiServer.id)

      // Listen for connection status changes
      const handleConnect = () => {
        setConnectionStatus('connected')
        setSocketId(apiServer.id)
      }

      const handleDisconnect = () => {
        setConnectionStatus('disconnected')
        setSocketId(null)
      }

      apiServer.on('connect', handleConnect)
      apiServer.on('disconnect', handleDisconnect)

      return () => {
        apiServer.off('connect', handleConnect)
        apiServer.off('disconnect', handleDisconnect)
      }
    } else {
      setConnectionStatus('disconnected')
      setSocketId(null)
    }
  }, [apiServer])

  // Helper functions
  const updateTestInput = (key, value) => {
    setTestInputs((prev) => ({ ...prev, [key]: value }))
  }

  const toggleCollapse = (key) => {
    setCollapseStates((prev) => ({ ...prev, [key]: !prev[key] }))
  }

  const handleReconnect = () => {
    if (apiServer) {
      apiServer.connect()
      msgApi.info('Attempting to reconnect...')
    } else {
      msgApi.warning('No API server instance available')
    }
  }

  const handleDisconnect = () => {
    if (apiServer) {
      apiServer.disconnect()
      msgApi.info('Disconnected from API server')
    }
  }

  const testFetchObject = async () => {
    try {
      msgApi.loading('Testing fetchObject...', 0)
      const result = await fetchObject(
        testInputs.objectId,
        testInputs.objectType
      )
      msgApi.destroy()
      msgApi.success('fetchObject test completed')
    } catch (err) {
      msgApi.destroy()
      msgApi.error('fetchObject test failed')
      logger.error('fetchObject error:', err)
    }
  }

  const testFetchObjects = async () => {
    try {
      msgApi.loading('Testing fetchObjects...', 0)
      const result = await fetchObjects(testInputs.objectType, {
        page: 1,
        limit: 5
      })
      msgApi.destroy()
      msgApi.success('fetchObjects test completed')
    } catch (err) {
      msgApi.destroy()
      msgApi.error('fetchObjects test failed')
      logger.error('fetchObjects error:', err)
    }
  }

  const testLockObject = () => {
    try {
      lockObject(testInputs.objectId, testInputs.objectType)
      msgApi.success('Lock command sent')
    } catch (err) {
      msgApi.error('Lock command failed')
      logger.error('Lock error:', err)
    }
  }

  const testUnlockObject = () => {
    try {
      unlockObject(testInputs.objectId, testInputs.objectType)
      msgApi.success('Unlock command sent')
    } catch (err) {
      msgApi.error('Unlock command failed')
      logger.error('Unlock error:', err)
    }
  }

  const testFetchObjectLock = async () => {
    try {
      msgApi.loading('Testing fetchObjectLock...', 0)
      const result = await fetchObjectLock(
        testInputs.objectId,
        testInputs.objectType
      )
      msgApi.destroy()
      msgApi.success('fetchObjectLock test completed')
    } catch (err) {
      msgApi.destroy()
      msgApi.error('fetchObjectLock test failed')
      logger.error('fetchObjectLock error:', err)
    }
  }

  const testUpdateObject = async () => {
    try {
      msgApi.loading('Testing updateObject...', 0)
      const testData = {
        name: 'Test Update',
        updated: new Date().toISOString()
      }
      const result = await updateObject(
        testInputs.objectId,
        testInputs.objectType,
        testData
      )
      msgApi.destroy()
      msgApi.success('updateObject test completed')
    } catch (err) {
      msgApi.destroy()
      msgApi.error('updateObject test failed')
      logger.error('updateObject error:', err)
    }
  }

  const testCreateObject = async () => {
    try {
      msgApi.loading('Testing createObject...', 0)
      const testData = {
        name: 'Test Create',
        created: new Date().toISOString()
      }
      const result = await createObject(testInputs.objectType, testData)
      msgApi.destroy()
      msgApi.success('createObject test completed')
    } catch (err) {
      msgApi.destroy()
      msgApi.error('createObject test failed')
      logger.error('createObject error:', err)
    }
  }

  const testDeleteObject = async () => {
    try {
      msgApi.loading('Testing deleteObject...', 0)
      const result = await deleteObject(
        testInputs.objectId,
        testInputs.objectType
      )
      msgApi.destroy()
      msgApi.success('deleteObject test completed')
    } catch (err) {
      msgApi.destroy()
      msgApi.error('deleteObject test failed')
      logger.error('deleteObject error:', err)
    }
  }

  const testFetchObjectsByProperty = async () => {
    try {
      msgApi.loading('Testing fetchObjectsByProperty...', 0)
      const params = {
        properties: testInputs.properties,
        filter: testInputs.filter,
        masterFilter: {}
      }
      const result = await fetchObjectsByProperty(testInputs.objectType, params)
      msgApi.destroy()
      msgApi.success('fetchObjectsByProperty test completed')
    } catch (err) {
      msgApi.destroy()
      msgApi.error('fetchObjectsByProperty test failed')
      logger.error('fetchObjectsByProperty error:', err)
    }
  }

  const testFetchSpotlightData = async () => {
    try {
      msgApi.loading('Testing fetchSpotlightData...', 0)
      const result = await fetchSpotlightData(testInputs.query)
      msgApi.destroy()
      msgApi.success('fetchSpotlightData test completed')
    } catch (err) {
      msgApi.destroy()
      msgApi.error('fetchSpotlightData test failed')
      logger.error('fetchSpotlightData error:', err)
    }
  }

  const testfetchFileContent = async () => {
    try {
      msgApi.loading('Testing fetchFileContent...', 0)
      await fetchFileContent(
        testInputs.objectId,
        'gcodefile',
        testInputs.fileName
      )
      msgApi.destroy()
      msgApi.success('fetchFileContent test completed')
    } catch (err) {
      msgApi.destroy()
      msgApi.error('fetchFileContent test failed')
      logger.error('fetchFileContent error:', err)
    }
  }

  const testFetchTemplatePreview = async () => {
    try {
      msgApi.loading('Testing fetchTemplatePreview...', 0)

      fetchTemplatePreview(
        testInputs.objectId,
        testInputs.templateContent,
        testInputs.testObject,
        testInputs.scale,
        (result) => {
          msgApi.destroy()
          if (result.success) {
            msgApi.success('fetchTemplatePreview test completed')
          } else {
            msgApi.error('fetchTemplatePreview test failed')
          }
        }
      )
    } catch (err) {
      msgApi.destroy()
      msgApi.error('fetchTemplatePreview test failed')
      logger.error('fetchTemplatePreview error:', err)
    }
  }

  const testFetchNotes = async () => {
    try {
      msgApi.loading('Testing fetchNotes...', 0)
      const result = await fetchNotes(testInputs.parentId)
      msgApi.destroy()
      msgApi.success('fetchNotes test completed')
    } catch (err) {
      msgApi.destroy()
      msgApi.error('fetchNotes test failed')
      logger.error('fetchNotes error:', err)
    }
  }

  const testFetchHostOTP = async () => {
    try {
      msgApi.loading('Testing fetchHostOTP...', 0)

      fetchHostOTP(testInputs.hostId, (result) => {
        msgApi.destroy()
        if (result.otp) {
          msgApi.success('fetchHostOTP test completed: ' + result.otp)
        } else {
          msgApi.error('fetchHostOTP test failed')
        }
      })
    } catch (err) {
      msgApi.destroy()
      msgApi.error('fetchHostOTP test failed')
      logger.error('fetchHostOTP error:', err)
    }
  }

  const testSendObjectAction = async () => {
    try {
      msgApi.loading('Testing sendObjectAction...', 0)

      sendObjectAction(
        testInputs.objectId,
        'printer',
        testInputs.action,
        (result) => {
          msgApi.destroy()
          if (result.success) {
            msgApi.success('sendObjectAction test completed')
          } else {
            msgApi.error('sendObjectAction test failed')
          }
        }
      )
    } catch (err) {
      msgApi.destroy()
      msgApi.error('sendObjectAction test failed')
      logger.error('sendObjectAction error:', err)
    }
  }

  const testSubscribeToObjectUpdates = () => {
    try {
      const callback = (data) => {
        logger.debug('Object update received:', data)
      }
      const unsubscribe = subscribeToObjectUpdates(
        testInputs.objectId,
        testInputs.objectType,
        callback
      )
      msgApi.success('Subscribed to object updates')
      logger.debug('Subscribed to object updates for test-id')

      // Store unsubscribe function for cleanup
      setTimeout(() => {
        if (unsubscribe) {
          unsubscribe()
          logger.debug('Unsubscribed from object updates')
        }
      }, 10000) // Auto-unsubscribe after 10 seconds
    } catch (err) {
      msgApi.error('Subscribe to object updates failed')
      logger.error('Subscribe error:', err)
    }
  }

  const testSubscribeToObjectEvent = () => {
    try {
      const callback = (event) => {
        logger.debug('Object event received:', event)
      }
      const unsubscribe = subscribeToObjectEvent(
        testInputs.objectId,
        'printer',
        testInputs.eventType,
        callback
      )
      msgApi.success('Subscribed to object events')
      logger.debug('Subscribed to object events for test-id')

      // Store unsubscribe function for cleanup
      setTimeout(() => {
        if (unsubscribe) {
          unsubscribe()
          logger.debug('Unsubscribed from object events')
        }
      }, 10000) // Auto-unsubscribe after 10 seconds
    } catch (err) {
      msgApi.error('Subscribe to object events failed')
      logger.error('Subscribe error:', err)
    }
  }

  const testSubscribeToObjectTypeUpdates = () => {
    try {
      const callback = (data) => {
        logger.debug('Object type update received:', data)
      }
      const unsubscribe = subscribeToObjectTypeUpdates(
        testInputs.objectType,
        callback
      )
      msgApi.success('Subscribed to object type updates')
      logger.debug('Subscribed to object type updates for user')

      // Store unsubscribe function for cleanup
      setTimeout(() => {
        if (unsubscribe) {
          unsubscribe()
          logger.debug('Unsubscribed from object type updates')
        }
      }, 10000) // Auto-unsubscribe after 10 seconds
    } catch (err) {
      msgApi.error('Subscribe to object type updates failed')
      logger.error('Subscribe error:', err)
    }
  }

  const testSubscribeToObjectLock = () => {
    try {
      const callback = (lockData) => {
        logger.debug('Object lock update received:', lockData)
      }
      const unsubscribe = subscribeToObjectLock(
        testInputs.objectId,
        testInputs.objectType,
        callback
      )
      msgApi.success('Subscribed to object lock updates')
      logger.debug('Subscribed to object lock updates for test-id')

      // Store unsubscribe function for cleanup
      setTimeout(() => {
        if (unsubscribe) {
          unsubscribe()
          logger.debug('Unsubscribed from object lock updates')
        }
      }, 10000) // Auto-unsubscribe after 10 seconds
    } catch (err) {
      msgApi.error('Subscribe to object lock updates failed')
      logger.error('Subscribe error:', err)
    }
  }

  const actionItems = {
    items: [
      {
        label: 'Reconnect',
        key: 'reconnect',
        disabled: connected
      },
      {
        label: 'Disconnect',
        key: 'disconnect',
        disabled: !connected
      },
      {
        type: 'divider'
      },
      {
        label: 'Reload',
        key: 'reload',
        icon: <ReloadIcon />
      }
    ],
    onClick: ({ key }) => {
      switch (key) {
        case 'reconnect':
          handleReconnect()
          break
        case 'disconnect':
          handleDisconnect()
          break
        case 'reload':
          msgApi.info('Reloading API State...')
          window.location.reload()
          break
        default:
          break
      }
    }
  }

  const getConnectionStatusColor = () => {
    switch (connectionStatus) {
      case 'connected':
        return 'success'
      case 'connecting':
        return 'processing'
      case 'disconnected':
        return 'error'
      default:
        return 'default'
    }
  }

  return (
    <Flex vertical gap='large' style={{ height: '100%', minHeight: 0 }}>
      {contextHolder}

      {/* Header with Actions */}
      <Flex justify={'space-between'} align={'center'}>
        <Space>
          <Dropdown menu={actionItems}>
            <Button>Actions</Button>
          </Dropdown>
        </Space>
      </Flex>

      <Descriptions bordered>
        <Descriptions.Item label='Status'>
          <Space>
            <Tag color={getConnectionStatusColor()} icon={<CloudIcon />}>
              {connectionStatus.charAt(0).toUpperCase() +
                connectionStatus.slice(1)}
            </Tag>
          </Space>
        </Descriptions.Item>
        <Descriptions.Item label='Connecting'>
          <BoolDisplay value={connecting} />
        </Descriptions.Item>
        <Descriptions.Item label='Connected'>
          <BoolDisplay value={connected} />
        </Descriptions.Item>
        <Descriptions.Item label='Socket ID'>
          <Text code>{socketId || 'None'}</Text>
        </Descriptions.Item>
        <Descriptions.Item label='Fetch Loading'>
          <BoolDisplay value={fetchLoading} />
        </Descriptions.Item>
        <Descriptions.Item label='Error'>
          <Text type={error ? 'danger' : 'secondary'}>{error || 'None'}</Text>
        </Descriptions.Item>
      </Descriptions>

      <InfoCollapse
        title='Params'
        icon={<span>🔎</span>}
        active={collapseStates.params}
        onToggle={() => toggleCollapse('params')}
        collapseKey='params'
      >
        <Descriptions bordered column={2}>
          <Descriptions.Item label='Object ID'>
            <Input
              value={testInputs.objectId}
              onChange={(e) => updateTestInput('objectId', e.target.value)}
              placeholder='Enter object ID'
              size='small'
            />
          </Descriptions.Item>
          <Descriptions.Item label='Object Type'>
            <Select
              value={testInputs.objectType}
              onChange={(value) => updateTestInput('objectType', value)}
              style={{ width: '100%' }}
              options={[
                { value: 'user', label: 'User' },
                { value: 'printer', label: 'Printer' },
                { value: 'job', label: 'Job' },
                { value: 'filament', label: 'Filament' },
                { value: 'gcodefile', label: 'GCode File' }
              ]}
            />
          </Descriptions.Item>
          <Descriptions.Item label='Host ID'>
            <Input
              value={testInputs.hostId}
              onChange={(e) => updateTestInput('hostId', e.target.value)}
              placeholder='Enter host ID'
            />
          </Descriptions.Item>
          <Descriptions.Item label='Parent ID'>
            <Input
              value={testInputs.parentId}
              onChange={(e) => updateTestInput('parentId', e.target.value)}
              placeholder='Enter parent ID'
            />
          </Descriptions.Item>
          <Descriptions.Item label='File Name'>
            <Input
              value={testInputs.fileName}
              onChange={(e) => updateTestInput('fileName', e.target.value)}
              placeholder='Enter file name'
            />
          </Descriptions.Item>
          <Descriptions.Item label='Query'>
            <Input
              value={testInputs.query}
              onChange={(e) => updateTestInput('query', e.target.value)}
              placeholder='Enter search query'
            />
          </Descriptions.Item>
          <Descriptions.Item label='Action'>
            <Select
              value={testInputs.action}
              onChange={(value) => updateTestInput('action', value)}
              style={{ width: '100%' }}
              options={[
                { value: 'start', label: 'Start' },
                { value: 'stop', label: 'Stop' },
                { value: 'pause', label: 'Pause' },
                { value: 'resume', label: 'Resume' }
              ]}
            />
          </Descriptions.Item>
          <Descriptions.Item label='Event Type'>
            <Select
              value={testInputs.eventType}
              onChange={(value) => updateTestInput('eventType', value)}
              style={{ width: '100%' }}
              options={[
                { value: 'status', label: 'Status' },
                { value: 'progress', label: 'Progress' },
                { value: 'error', label: 'Error' },
                { value: 'complete', label: 'Complete' }
              ]}
            />
          </Descriptions.Item>
          <Descriptions.Item label='Scale'>
            <InputNumber
              value={testInputs.scale}
              onChange={(value) => updateTestInput('scale', value)}
              min={0.1}
              max={10}
              step={0.1}
              style={{ width: '100%' }}
            />
          </Descriptions.Item>
          <Descriptions.Item label='Template Content' span={1}>
            <Input.TextArea
              value={testInputs.templateContent}
              onChange={(e) =>
                updateTestInput('templateContent', e.target.value)
              }
              placeholder='Enter template content'
              rows={2}
            />
          </Descriptions.Item>
        </Descriptions>
      </InfoCollapse>

      {/* Test Sections */}
      <div style={{ height: '100%', overflow: 'auto' }}>
        <Flex vertical gap={'large'}>
          {/* Fetch Tests */}
          <InfoCollapse
            title='Fetch Tests'
            icon={<span>📥</span>}
            active={collapseStates.fetchTests}
            onToggle={() => toggleCollapse('fetchTests')}
            collapseKey='fetchTests'
          >
            <Space direction='vertical' style={{ width: '100%' }}>
              <Button onClick={testFetchObject} block>
                Test fetchObject
              </Button>
              <Button onClick={testFetchObjects} block>
                Test fetchObjects
              </Button>
              <Button onClick={testFetchObjectLock} block>
                Test fetchObjectLock
              </Button>
              <Button onClick={testFetchObjectsByProperty} block>
                Test fetchObjectsByProperty
              </Button>
              <Button onClick={testFetchSpotlightData} block>
                Test fetchSpotlightData
              </Button>
              <Button onClick={testfetchFileContent} block>
                Test fetchFileContent
              </Button>
              <Button onClick={testFetchNotes} block>
                Test fetchNotes
              </Button>
            </Space>
          </InfoCollapse>

          {/* CRUD Tests */}
          <InfoCollapse
            title='CRUD Tests'
            icon={<span>✏️</span>}
            active={collapseStates.crudTests}
            onToggle={() => toggleCollapse('crudTests')}
            collapseKey='crudTests'
          >
            <Space direction='vertical' style={{ width: '100%' }}>
              <Button onClick={testLockObject} block>
                Test Lock Object
              </Button>
              <Button onClick={testUnlockObject} block>
                Test Unlock Object
              </Button>
              <Button onClick={testUpdateObject} block>
                Test updateObject
              </Button>
              <Button onClick={testCreateObject} block>
                Test createObject
              </Button>
              <Button onClick={testDeleteObject} block>
                Test deleteObject
              </Button>
            </Space>
          </InfoCollapse>

          {/* Special Tests */}
          <InfoCollapse
            title='Special Tests'
            icon={<span>🔧</span>}
            active={collapseStates.specialTests}
            onToggle={() => toggleCollapse('specialTests')}
            collapseKey='specialTests'
          >
            <Space direction='vertical' style={{ width: '100%' }}>
              <Button onClick={testFetchTemplatePreview} block>
                Test fetchTemplatePreview
              </Button>
              <Button onClick={testFetchHostOTP} block>
                Test fetchHostOTP
              </Button>
              <Button onClick={testSendObjectAction} block>
                Test sendObjectAction
              </Button>
            </Space>
          </InfoCollapse>

          {/* Subscription Tests */}
          <InfoCollapse
            title='Subscription Tests'
            icon={<span>📡</span>}
            active={collapseStates.subscriptionTests}
            onToggle={() => toggleCollapse('subscriptionTests')}
            collapseKey='subscriptionTests'
          >
            <Space direction='vertical' style={{ width: '100%' }}>
              <Button onClick={testSubscribeToObjectUpdates} block>
                Test Subscribe Object Updates
              </Button>
              <Button onClick={testSubscribeToObjectEvent} block>
                Test Subscribe Object Events
              </Button>
              <Button onClick={testSubscribeToObjectTypeUpdates} block>
                Test Subscribe Object Type Updates
              </Button>
              <Button onClick={testSubscribeToObjectLock} block>
                Test Subscribe Object Lock
              </Button>
            </Space>
          </InfoCollapse>

          {/* API Server Instance Info */}
          <InfoCollapse
            title='API Server Instance'
            icon={<span>🖥️</span>}
            active={false}
            onToggle={() => {}}
            collapseKey='apiServer'
          >
            <pre style={{ margin: 0, fontSize: 12 }}>
              {apiServer ? (
                <Paragraph>
                  <pre>
                    {JSON.stringify(
                      {
                        connected: apiServer.connected,
                        id: apiServer.id,
                        transport: apiServer.io.engine.transport.name,
                        readyState: apiServer.io.engine.readyState
                      },
                      null,
                      2
                    )}
                  </pre>
                </Paragraph>
              ) : (
                <Text type='secondary'>No API server instance</Text>
              )}
            </pre>
          </InfoCollapse>
        </Flex>
      </div>
    </Flex>
  )
}

export default ApiContextDebug
