import { useState, useEffect } from 'react'
import { configStorage } from '@/lib/configStorage'
import type { RelayConfig } from '@/lib/configStorageTypes'
import { t } from '@/lib/i18n'
import { userConfirm } from '@/lib/userConfirm'
import { relaySessionManager } from '@/lib/relaySessionManager'

interface RelayManagerProps {
  onConfigChange?: () => void
}

export function RelayManager({ onConfigChange }: RelayManagerProps): React.ReactElement {
  const [relays, setRelays] = useState<RelayConfig[]>([])
  const [loading, setLoading] = useState(true)
  const [error, setError] = useState<string | null>(null)
  const [editingId, setEditingId] = useState<string | null>(null)
  const [newUrl, setNewUrl] = useState('')
  const [showAddForm, setShowAddForm] = useState(false)
  const [draggedId, setDraggedId] = useState<string | null>(null)
  const [dragOverId, setDragOverId] = useState<string | null>(null)

  useEffect(() => {
    void loadRelays()
  }, [])

  async function loadRelays(): Promise<void> {
    try {
      setLoading(true)
      setError(null)
      const config = await configStorage.getConfig()

      // Get failed relays from session manager and disable them in config
      const failedRelays = relaySessionManager.getFailedRelays()
      if (failedRelays.length > 0) {
        let hasChanges = false
        for (const relayUrl of failedRelays) {
          // Find the relay config by URL
          const relayConfig = config.relays.find((r) => r.url === relayUrl)
          if (relayConfig && relayConfig.enabled) {
            // Disable the failed relay
            await configStorage.updateRelay(relayConfig.id, { enabled: false })
            hasChanges = true
          }
        }
        // Reload config if we made changes
        if (hasChanges) {
          const updatedConfig = await configStorage.getConfig()
          setRelays(updatedConfig.relays.sort((a, b) => a.priority - b.priority))
        } else {
          setRelays(config.relays.sort((a, b) => a.priority - b.priority))
        }
      } else {
        setRelays(config.relays.sort((a, b) => a.priority - b.priority))
      }
    } catch (e) {
      const errorMessage = e instanceof Error ? e.message : t('settings.relay.error.loadFailed')
      setError(errorMessage)
      console.error('Error loading relays:', e)
    } finally {
      setLoading(false)
    }
  }

  async function handleToggleEnabled(id: string, enabled: boolean): Promise<void> {
    try {
      await configStorage.updateRelay(id, { enabled })
      await loadRelays()
      onConfigChange?.()
    } catch (e) {
      const errorMessage = e instanceof Error ? e.message : t('settings.relay.error.updateFailed')
      setError(errorMessage)
      console.error('Error updating relay:', e)
    }
  }

  async function handleUpdatePriorities(newOrder: RelayConfig[]): Promise<void> {
    try {
      const updatePromises = newOrder.map((relay, index) => {
        const newPriority = index + 1
        if (relay.priority !== newPriority) {
          return configStorage.updateRelay(relay.id, { priority: newPriority })
        }
        return Promise.resolve()
      })

      await Promise.all(updatePromises)
      await loadRelays()
      onConfigChange?.()
    } catch (e) {
      const errorMessage = e instanceof Error ? e.message : t('settings.relay.error.priorityFailed')
      setError(errorMessage)
      console.error('Error updating priorities:', e)
    }
  }

  function handleDragStart(e: React.DragEvent<HTMLDivElement>, id: string): void {
    setDraggedId(id)
    e.dataTransfer.effectAllowed = 'move'
    e.dataTransfer.setData('text/plain', id)
  }

  function handleDragOver(e: React.DragEvent<HTMLDivElement>, id: string): void {
    e.preventDefault()
    e.dataTransfer.dropEffect = 'move'
    setDragOverId(id)
  }

  function handleDragLeave(): void {
    setDragOverId(null)
  }

  function handleDrop(e: React.DragEvent<HTMLDivElement>, targetId: string): void {
    e.preventDefault()
    setDragOverId(null)

    if (!draggedId || draggedId === targetId) {
      setDraggedId(null)
      return
    }

    const draggedIndex = relays.findIndex((relay) => relay.id === draggedId)
    const targetIndex = relays.findIndex((relay) => relay.id === targetId)

    if (draggedIndex === -1 || targetIndex === -1) {
      setDraggedId(null)
      return
    }

    const newRelays = [...relays]
    const removed = newRelays[draggedIndex]
    if (!removed) {
      setDraggedId(null)
      return
    }
    newRelays.splice(draggedIndex, 1)
    newRelays.splice(targetIndex, 0, removed)

    setRelays(newRelays)
    setDraggedId(null)

    void handleUpdatePriorities(newRelays)
  }

  function handleDragEnd(): void {
    setDraggedId(null)
  }

  function DragHandle(): React.ReactElement {
    return (
      <div className="flex flex-col gap-1 cursor-grab active:cursor-grabbing text-cyber-accent/50 hover:text-neon-cyan transition-colors">
        <svg width="12" height="12" viewBox="0 0 12 12" fill="currentColor">
          <circle cx="2" cy="2" r="1.5" />
          <circle cx="6" cy="2" r="1.5" />
          <circle cx="10" cy="2" r="1.5" />
          <circle cx="2" cy="6" r="1.5" />
          <circle cx="6" cy="6" r="1.5" />
          <circle cx="10" cy="6" r="1.5" />
          <circle cx="2" cy="10" r="1.5" />
          <circle cx="6" cy="10" r="1.5" />
          <circle cx="10" cy="10" r="1.5" />
        </svg>
      </div>
    )
  }

  async function handleUpdateUrl(id: string, url: string): Promise<void> {
    try {
      await configStorage.updateRelay(id, { url })
      await loadRelays()
      setEditingId(null)
      onConfigChange?.()
    } catch (e) {
      const errorMessage = e instanceof Error ? e.message : t('settings.relay.error.urlFailed')
      setError(errorMessage)
      console.error('Error updating URL:', e)
    }
  }

  async function handleAddRelay(): Promise<void> {
    if (!newUrl.trim()) {
      setError(t('settings.relay.error.urlRequired'))
      return
    }

    try {
      // Normalize URL (add wss:// if missing)
      let normalizedUrl = newUrl.trim()
      if (!normalizedUrl.startsWith('ws://') && !normalizedUrl.startsWith('wss://')) {
        normalizedUrl = `wss://${normalizedUrl}`
      }

      // Validate URL format
      new URL(normalizedUrl)
      await configStorage.addRelay(normalizedUrl, true)
      setNewUrl('')
      setShowAddForm(false)
      await loadRelays()
      onConfigChange?.()
    } catch (e) {
      if (e instanceof TypeError && e.message.includes('Invalid URL')) {
        setError(t('settings.relay.error.invalidUrl'))
      } else {
        const errorMessage = e instanceof Error ? e.message : t('settings.relay.error.addFailed')
        setError(errorMessage)
      }
      console.error('Error adding relay:', e)
    }
  }

  async function handleRemoveRelay(id: string): Promise<void> {
    if (!userConfirm(t('settings.relay.remove.confirm'))) {
      return
    }

    try {
      await configStorage.removeRelay(id)
      await loadRelays()
      onConfigChange?.()
    } catch (e) {
      const errorMessage = e instanceof Error ? e.message : t('settings.relay.error.removeFailed')
      setError(errorMessage)
      console.error('Error removing relay:', e)
    }
  }

  if (loading) {
    return (
      <div className="text-center py-8 text-neon-cyan">
        <div>{t('settings.relay.loading')}</div>
      </div>
    )
  }

  return (
    <div className="space-y-6">
      {error && (
        <div className="bg-red-900/30 border border-red-500/50 rounded p-4 text-red-300">
          {error}
          <button
            onClick={() => {
              setError(null)
            }}
            className="ml-4 text-red-400 hover:text-red-200"
          >
            ×
          </button>
        </div>
      )}

      <div className="flex justify-between items-center">
        <h2 className="text-2xl font-bold text-neon-cyan">{t('settings.relay.title')}</h2>
        <button
          onClick={() => {
            setShowAddForm(!showAddForm)
          }}
          className="px-4 py-2 bg-neon-cyan/20 hover:bg-neon-cyan/30 text-neon-cyan border border-neon-cyan/50 rounded transition-colors"
        >
          {showAddForm ? t('settings.relay.add.cancel') : t('settings.relay.addButton')}
        </button>
      </div>

      {showAddForm && (
        <div className="bg-cyber-dark border border-neon-cyan/30 rounded p-4 space-y-4">
          <div>
            <label className="block text-sm font-medium text-cyber-accent mb-2">
              {t('settings.relay.add.url')}
            </label>
            <input
              type="text"
              value={newUrl}
              onChange={(e) => {
                setNewUrl(e.target.value)
              }}
              placeholder={t('settings.relay.add.placeholder')}
              className="w-full px-4 py-2 bg-cyber-darker border border-cyber-accent/30 rounded text-cyber-light focus:border-neon-cyan focus:outline-none"
            />
          </div>
          <div className="flex gap-2">
            <button
              onClick={() => {
                void handleAddRelay()
              }}
              className="px-4 py-2 bg-neon-cyan/20 hover:bg-neon-cyan/30 text-neon-cyan border border-neon-cyan/50 rounded transition-colors"
            >
              {t('settings.relay.add.add')}
            </button>
            <button
              onClick={() => {
                setShowAddForm(false)
                setNewUrl('')
                setError(null)
              }}
              className="px-4 py-2 bg-cyber-accent/20 hover:bg-cyber-accent/30 text-cyber-accent border border-cyber-accent/50 rounded transition-colors"
            >
              {t('settings.relay.add.cancel')}
            </button>
          </div>
        </div>
      )}

      <div className="space-y-4">
        {relays.length === 0 ? (
          <div className="text-center py-8 text-cyber-accent">
            {t('settings.relay.empty')}
          </div>
        ) : (
          relays.map((relay, index) => (
            <div
              key={relay.id}
              onDragOver={(e) => {
                handleDragOver(e, relay.id)
              }}
              onDragLeave={handleDragLeave}
              onDrop={(e) => {
                handleDrop(e, relay.id)
              }}
              className={`bg-cyber-dark border rounded p-4 space-y-3 transition-all ${
                (() => {
                  if (draggedId === relay.id) {
                    return 'opacity-50 border-neon-cyan'
                  }
                  if (dragOverId === relay.id) {
                    return 'border-neon-green shadow-lg'
                  }
                  return 'border-neon-cyan/30'
                })()
              }`}
            >
              <div className="flex items-start justify-between gap-4">
                <div className="flex items-center gap-3 flex-1">
                  <div
                    className="drag-handle cursor-grab active:cursor-grabbing"
                    draggable
                    onDragStart={(e) => {
                      handleDragStart(e, relay.id)
                    }}
                    onDragEnd={handleDragEnd}
                    onMouseDown={(e) => {
                      e.stopPropagation()
                    }}
                  >
                    <DragHandle />
                  </div>
                  <div className="flex-1">
                    {editingId === relay.id ? (
                      <div className="space-y-2">
                        <input
                          type="text"
                          defaultValue={relay.url}
                          onBlur={(e) => {
                            if (e.target.value !== relay.url) {
                              void handleUpdateUrl(relay.id, e.target.value)
                            } else {
                              setEditingId(null)
                            }
                          }}
                          onKeyDown={(e) => {
                            if (e.key === 'Enter') {
                              e.currentTarget.blur()
                            } else if (e.key === 'Escape') {
                              setEditingId(null)
                            }
                          }}
                          className="w-full px-3 py-2 bg-cyber-darker border border-neon-cyan/50 rounded text-cyber-light focus:border-neon-cyan focus:outline-none"
                          autoFocus
                        />
                      </div>
                    ) : (
                      <div
                        className="text-neon-cyan cursor-pointer hover:text-neon-green transition-colors"
                        onClick={() => {
                          setEditingId(relay.id)
                        }}
                        title={t('settings.relay.list.editUrl')}
                      >
                        {relay.url}
                      </div>
                    )}
                  </div>
                </div>
                <div className="flex items-center gap-2">
                  <label className="flex items-center gap-2 cursor-pointer">
                    <input
                      type="checkbox"
                      checked={relay.enabled}
                      onChange={(e) => {
                        void handleToggleEnabled(relay.id, e.target.checked)
                      }}
                      className="w-4 h-4 text-neon-cyan bg-cyber-darker border-cyber-accent rounded focus:ring-neon-cyan"
                    />
                    <span className="text-sm text-cyber-accent">
                      {relay.enabled ? t('settings.relay.list.enabled') : t('settings.relay.list.disabled')}
                    </span>
                  </label>
                  <button
                    onClick={() => {
                      void handleRemoveRelay(relay.id)
                    }}
                    className="px-3 py-1 text-sm bg-red-900/30 hover:bg-red-900/50 text-red-300 border border-red-500/50 rounded transition-colors"
                    title={t('settings.relay.list.remove')}
                  >
                    {t('settings.relay.list.remove')}
                  </button>
                </div>
              </div>
              <div className="flex items-center gap-2 text-xs text-cyber-accent/70">
                <span>
                  {t('settings.relay.list.priorityLabel', { priority: index + 1 })}
                </span>
              </div>
            </div>
          ))
        )}
      </div>

      <div className="text-sm text-cyber-accent space-y-2">
        <p>
          <strong>{t('settings.relay.note.title')}</strong> {t('settings.relay.note.priority')}
        </p>
        <p>
          {t('settings.relay.note.rotation')}
        </p>
      </div>
    </div>
  )
}
