import { useState } from 'react'
import { useWaste } from '../store'
import type { PeerStatus } from '../store'
import { ShareManager } from './ShareManager'
import { Transfers } from './Transfers'

function makeYawCard(id: string, alias: string): string {
  const nick = encodeURIComponent(alias.trim().slice(0, 40))
  return nick ? `yaw:${id}?n=${nick}` : `yaw:${id}`
}

function connDot(status: PeerStatus | undefined): { color: string; label: string } {
  const ct = status?.candidateType
  const cs = status?.connState
  if (cs === 'failed' || cs === 'closed') return { color: '#e06060', label: 'failed' }
  if (cs === 'connecting' || cs === 'new') return { color: '#c8a020', label: 'connecting…' }
  if (ct === 'relay') return { color: '#c8a020', label: 'relayed (TURN)' }
  if (ct === 'srflx') return { color: '#60c060', label: 'NAT punched' }
  if (ct === 'host') return { color: '#60c060', label: 'direct (LAN)' }
  if (cs === 'connected') return { color: '#60c060', label: 'connected' }
  return { color: 'var(--muted)', label: 'unknown' }
}

function formatTs(ts: number | undefined): string {
  if (!ts) return '—'
  return new Date(ts).toLocaleTimeString([], { hour: '2-digit', minute: '2-digit', second: '2-digit' })
}

export function Sidebar() {
  const {
    localPeer, masterId, masterAlias,
    networks, activeNetworkId, activeRoom,
    connectedPeers, peerStatus,
    setActiveRoom, setActiveNetwork, messages, browseFiles, sendFileTo, adapterMode,
    customRooms, createRoom, logout, send,
  } = useWaste()
  const [addingRoom, setAddingRoom] = useState(false)
  const [newRoomName, setNewRoomName] = useState('')
  const [addingNetwork, setAddingNetwork] = useState(false)
  const [newNetName, setNewNetName] = useState('')
  const [newNetAnchor, setNewNetAnchor] = useState('')

  const netCustomRooms = activeNetworkId ? (customRooms[activeNetworkId] ?? []) : []
  const rooms = ['general', ...netCustomRooms]
  if (activeNetworkId) {
    const prefix = `${activeNetworkId}:dm:`
    Object.keys(messages).forEach(k => {
      if (k.startsWith(prefix)) {
        const r = k.slice(activeNetworkId.length + 1)
        if (!rooms.includes(r)) rooms.push(r)
      }
    })
  }

  function submitNewRoom(e: React.FormEvent) {
    e.preventDefault()
    if (newRoomName.trim()) createRoom(newRoomName)
    setNewRoomName('')
    setAddingRoom(false)
  }

  function submitNewNetwork(e: React.FormEvent) {
    e.preventDefault()
    const name = newNetName.trim()
    if (!name) return
    if (adapterMode === 'browser') {
      // Persist to saved networks list in localStorage.
      const anchor = newNetAnchor.trim() || localStorage.getItem('waste_anchor_url') || ''
      const saved: Array<{name: string; anchor: string}> = JSON.parse(localStorage.getItem('waste_saved_networks') ?? '[]')
      if (!saved.some(n => n.name === name && n.anchor === anchor)) {
        saved.push({ name, anchor })
        localStorage.setItem('waste_saved_networks', JSON.stringify(saved))
      }
    }
    send({ type: 'join_network', network_name: name })
    setNewNetName('')
    setNewNetAnchor('')
    setAddingNetwork(false)
  }

  const displayAlias = localPeer?.alias ?? masterAlias ?? ''
  const displayId = localPeer?.id ?? masterId ?? ''
  const card = displayId ? makeYawCard(displayId, displayAlias) : null

  function copyHangLink() {
    const net = networks.find(n => n.network_id === activeNetworkId)
    if (!net) return
    const cfg = (window as unknown as { WASTE_CONFIG?: { signalURL?: string } }).WASTE_CONFIG
    const anchor = cfg?.signalURL ?? ''
    const payload = btoa(JSON.stringify({ network: net.network_name, anchor }))
      .replace(/\+/g, '-').replace(/\//g, '_')
    const url = `${window.location.origin}/#waste:${payload}`
    navigator.clipboard?.writeText(url)
  }

  function handleLogout() {
    const clearId = window.confirm('Also clear your identity keypair? (Cannot be undone — export a backup first if you want to keep it.)')
    logout(clearId)
  }

  function openDM(peerId: string) {
    setActiveRoom(`dm:${peerId}`)
  }

  function requestFiles(peerId: string) {
    browseFiles(peerId)
  }

  return (
    <nav className="sidebar">
      <div className="sidebar-identity">
        <div
          style={{ flex: 1, cursor: card ? 'pointer' : undefined }}
          title={card ?? undefined}
          onClick={() => card && navigator.clipboard?.writeText(card)}
        >
          <span className="alias">{displayAlias || '…'}</span>
          <span className="peer-id">{displayId.slice(0, 16).replace(/(.{4})/g, '$1 ').trim()}</span>
        </div>
        <button className="sidebar-logout" onClick={handleLogout} title="Leave network">⏻</button>
      </div>

      <div className="sidebar-section">
        <div className="sidebar-label-row">
          <span className="sidebar-label">Networks</span>
          <span style={{ display: 'flex', gap: 2 }}>
            {activeNetworkId && (
              <button className="sidebar-add" onClick={copyHangLink} title="Copy hang link">🔗</button>
            )}
            <button className="sidebar-add" onClick={() => setAddingNetwork(v => !v)} title="Join network">+</button>
          </span>
        </div>
        {networks.map(n => (
          <button
            key={n.network_id}
            className={`sidebar-item ${n.network_id === activeNetworkId ? 'active' : ''}`}
            onClick={() => setActiveNetwork(n.network_id)}
          >
            {n.network_name}
          </button>
        ))}
        {addingNetwork && (
          <form className="sidebar-new-room" onSubmit={submitNewNetwork}>
            <input
              autoFocus
              value={newNetName}
              onChange={e => setNewNetName(e.target.value)}
              placeholder="network name"
              onKeyDown={e => e.key === 'Escape' && (setAddingNetwork(false), setNewNetName(''))}
            />
            {adapterMode === 'browser' && (
              <input
                value={newNetAnchor}
                onChange={e => setNewNetAnchor(e.target.value)}
                placeholder="anchor URL (blank = current)"
                className="mono"
                style={{ fontSize: '0.75rem', marginTop: 4 }}
              />
            )}
            <button type="submit" disabled={!newNetName.trim()} style={{ marginTop: 4, width: '100%', fontSize: '12px', padding: '3px 8px' }}>
              Join
            </button>
          </form>
        )}
      </div>

      <div className="sidebar-section">
        <div className="sidebar-label-row">
          <span className="sidebar-label">Rooms</span>
          <button className="sidebar-add" onClick={() => setAddingRoom(v => !v)} title="New room">+</button>
        </div>
        {rooms.map(r => (
          <button
            key={r}
            className={`sidebar-item ${r === activeRoom ? 'active' : ''}`}
            onClick={() => setActiveRoom(r)}
          >
            {r.startsWith('dm:') ? `@ ${r.slice(3, 11)}…` : `# ${r}`}
          </button>
        ))}
        {addingRoom && (
          <form className="sidebar-new-room" onSubmit={submitNewRoom}>
            <input
              autoFocus
              value={newRoomName}
              onChange={e => setNewRoomName(e.target.value)}
              placeholder="room-name"
              onKeyDown={e => e.key === 'Escape' && (setAddingRoom(false), setNewRoomName(''))}
            />
          </form>
        )}
      </div>

      {adapterMode === 'browser' && (
        <div className="sidebar-section">
          <span className="sidebar-label">Sharing</span>
          <div style={{ padding: '4px 12px' }}><ShareManager /></div>
        </div>
      )}

      <Transfers />

      <div className="sidebar-section sidebar-peers">
        <span className="sidebar-label">Peers · {connectedPeers.length + 1}</span>

        {/* Self */}
        <div className="peer-row peer-row-self">
          <span className="peer-dot" style={{ background: 'var(--accent)' }} />
          <span className="peer-row-alias">{displayAlias || '…'}</span>
          <span className="peer-row-you">you</span>
        </div>

        {connectedPeers.length === 0 && (
          <span className="sidebar-empty">no peers connected</span>
        )}
        {connectedPeers.map(p => {
          const st = peerStatus[p.id]
          const dot = connDot(st)
          const tooltip = [
            p.alias,
            p.id,
            `connection: ${dot.label}`,
            st?.remoteAddress ? `remote: ${st.remoteAddress}` : null,
            st?.lastSeen ? `last seen: ${formatTs(st.lastSeen)}` : null,
          ].filter(Boolean).join('\n')
          return (
            <div key={p.id} className="peer-row" title={tooltip}>
              <span className="peer-dot" style={{ background: dot.color }} />
              <span className="peer-row-alias">{p.alias}</span>
              <span className="peer-row-id">{p.id.slice(0, 8)}</span>
              <span className="peer-row-actions">
                <button className="peer-action" onClick={() => openDM(p.id)} title="DM">↩</button>
                <button className="peer-action" onClick={() => requestFiles(p.id)} title="Browse files">⊞</button>
                <label className="peer-action" title="Send file" style={{ cursor: 'pointer' }}>
                  📎
                  <input type="file" style={{ display: 'none' }} onChange={e => {
                    const f = e.target.files?.[0]
                    if (f) sendFileTo(p.id, f)
                    e.target.value = ''
                  }} />
                </label>
              </span>
            </div>
          )
        })}
      </div>
    </nav>
  )
}
