<template>
  <!-- Decentralized Web Node (DWN) -->
  <div class="glass-card p-6">
    <div class="flex items-center justify-between mb-4">
      <div class="flex items-center gap-3">
        <div class="flex-shrink-0 w-10 h-10 rounded-lg bg-white/10 flex items-center justify-center">
          <svg class="w-5 h-5 text-white/80" fill="none" stroke="currentColor" viewBox="0 0 24 24">
            <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 7v10c0 2.21 3.582 4 8 4s8-1.79 8-4V7M4 7c0 2.21 3.582 4 8 4s8-1.79 8-4M4 7c0-2.21 3.582-4 8-4s8 1.79 8 4m0 5c0 2.21-3.582 4-8 4s-8-1.79-8-4" />
          </svg>
        </div>
        <div>
          <h2 class="text-lg font-semibold text-white">{{ t('web5.decentralizedWebNode') }}</h2>
          <p class="text-xs text-white/60">{{ t('web5.dwnDescription') }}</p>
        </div>
      </div>
      <router-link v-if="dwnInstalled && dwnRunning" to="/apps/dwn" class="glass-button glass-button-sm px-3 rounded-lg text-sm font-medium inline-flex items-center gap-2 no-underline">
        {{ t('web5.manageDwn') }}
      </router-link>
    </div>

    <!-- DWN not installed or not running -->
    <div v-if="!dwnInstalled || !dwnRunning" class="py-6 text-center">
      <p class="text-white/60 text-sm mb-4">
        {{ !dwnInstalled ? 'The DWN container is not installed.' : 'The DWN container is not running.' }}
        {{ !dwnInstalled ? 'Install it from the App Store to enable decentralized data storage and sync.' : 'Start it from the App Store to enable decentralized data storage and sync.' }}
      </p>
      <router-link to="/dashboard/marketplace" class="glass-button px-4 py-2 rounded-lg text-sm font-medium inline-flex items-center gap-2 no-underline">
        <svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
          <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M3 3h2l.4 2M7 13h10l4-8H5.4M7 13L5.4 5M7 13l-2.293 2.293c-.63.63-.184 1.707.707 1.707H17m0 0a2 2 0 100 4 2 2 0 000-4zm-8 2a2 2 0 100 4 2 2 0 000-4z" />
        </svg>
        Open App Store
      </router-link>
    </div>

    <!-- Status (only shown when DWN is installed and running) -->
    <template v-if="dwnInstalled && dwnRunning">
    <div class="grid grid-cols-2 md:grid-cols-4 gap-3 mb-4">
      <div class="bg-white/5 rounded-lg p-3">
        <div class="text-xs text-white/50 mb-1">{{ t('common.status') }}</div>
        <div class="flex items-center gap-2">
          <div class="w-2 h-2 rounded-full" :class="dwnStatus?.running ? 'bg-green-400' : 'bg-red-400'"></div>
          <span class="text-sm text-white font-medium">{{ dwnStatus?.running ? t('common.running') : t('common.stopped') }}</span>
        </div>
      </div>
      <div class="bg-white/5 rounded-lg p-3">
        <div class="text-xs text-white/50 mb-1">Sync</div>
        <div class="flex items-center gap-2">
          <div class="w-2 h-2 rounded-full" :class="{
            'bg-green-400': dwnSyncStatus === 'synced',
            'bg-yellow-400 animate-pulse': dwnSyncStatus === 'syncing',
            'bg-red-400': dwnSyncStatus === 'error',
            'bg-white/30': dwnSyncStatus === 'idle'
          }"></div>
          <span class="text-sm text-white font-medium capitalize">{{ dwnSyncStatus }}</span>
        </div>
      </div>
      <div class="bg-white/5 rounded-lg p-3">
        <div class="text-xs text-white/50 mb-1">Storage</div>
        <span class="text-sm text-white font-medium">{{ formatDwnStorage }}</span>
      </div>
      <div class="bg-white/5 rounded-lg p-3">
        <div class="text-xs text-white/50 mb-1">Messages</div>
        <span class="text-sm text-white font-medium">{{ dwnStatus?.message_count ?? 0 }}</span>
      </div>
    </div>

    <!-- Protocols -->
    <div class="mb-4">
      <div class="flex items-center justify-between mb-2">
        <div class="text-xs text-white/50">Registered Protocols ({{ dwnProtocols.length }})</div>
        <button @click="showRegisterProtocol = !showRegisterProtocol" class="text-xs text-blue-400 hover:text-blue-300 transition-colors">
          {{ showRegisterProtocol ? 'Cancel' : '+ Register' }}
        </button>
      </div>
      <div v-if="showRegisterProtocol" class="bg-white/5 rounded-lg p-3 mb-3">
        <div class="flex gap-2 items-end">
          <div class="flex-1">
            <label class="text-xs text-white/50 block mb-1">Protocol URI</label>
            <input v-model="newProtocolUri" type="text" placeholder="https://example.com/protocol" class="w-full bg-black/30 border border-white/10 rounded-lg px-3 py-1.5 text-sm text-white placeholder-white/30 focus:outline-none focus:border-blue-500/50" />
          </div>
          <label class="flex items-center gap-1.5 text-xs text-white/60 cursor-pointer whitespace-nowrap pb-1.5">
            <input v-model="newProtocolPublished" type="checkbox" class="rounded bg-black/30 border-white/20" />
            Published
          </label>
          <button @click="registerDwnProtocol" :disabled="registeringProtocol || !newProtocolUri.trim()" class="glass-button glass-button-sm px-3 rounded-lg text-xs font-medium disabled:opacity-50 whitespace-nowrap">
            {{ registeringProtocol ? 'Registering...' : 'Register' }}
          </button>
        </div>
      </div>
      <div v-if="dwnProtocols.length" class="flex flex-wrap gap-2">
        <div v-for="proto in dwnProtocols" :key="proto.protocol" class="flex items-center gap-1.5 px-2 py-1 rounded-md bg-blue-500/15 border border-blue-500/20 text-xs text-blue-300 group">
          <span>{{ proto.protocol }}</span>
          <span v-if="proto.published" class="text-green-400/60" title="Published">&#x2022;</span>
          <button @click="removeDwnProtocol(proto.protocol)" :disabled="removingProtocol === proto.protocol" class="opacity-0 group-hover:opacity-100 text-red-400/60 hover:text-red-400 transition-all ml-1" title="Remove">
            &times;
          </button>
        </div>
      </div>
      <div v-else class="text-xs text-white/30 italic">No protocols registered</div>
    </div>

    <!-- Sync Targets -->
    <div v-if="dwnStatus?.peer_sync_targets?.length" class="mb-4">
      <div class="text-xs text-white/50 mb-2">Peer Sync Targets</div>
      <div class="space-y-1">
        <div v-for="target in dwnStatus.peer_sync_targets" :key="target" class="flex items-center gap-2 text-xs text-white/70 bg-white/5 rounded-lg px-3 py-2">
          <svg class="w-3 h-3 text-green-400 flex-shrink-0" fill="currentColor" viewBox="0 0 24 24"><circle cx="12" cy="12" r="4" /></svg>
          <span class="truncate font-mono">{{ target }}</span>
        </div>
      </div>
    </div>

    <!-- Messages Browser -->
    <div class="mb-4">
      <div class="flex items-center justify-between mb-2">
        <div class="text-xs text-white/50">Messages</div>
        <button @click="toggleDwnMessages" class="text-xs text-blue-400 hover:text-blue-300 transition-colors">
          {{ showDwnMessages ? 'Hide' : 'Browse' }}
        </button>
      </div>
      <div v-if="showDwnMessages">
        <div v-if="loadingDwnMessages && dwnMessages.length === 0" class="text-xs text-white/40 py-4 text-center">Loading messages...</div>
        <div v-else-if="dwnMessages.length === 0" class="text-xs text-white/30 italic py-2">No messages stored</div>
        <div v-else class="space-y-2 max-h-64 overflow-y-auto">
          <div v-if="loadingDwnMessages" class="p-2 text-center text-white/45 text-xs flex items-center justify-center gap-2">
            <svg class="animate-spin h-3.5 w-3.5" fill="none" viewBox="0 0 24 24">
              <circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4"></circle>
              <path class="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"></path>
            </svg>
            Refreshing messages...
          </div>
          <div v-for="msg in dwnMessages" :key="msg.record_id" class="bg-white/5 rounded-lg p-3">
            <div class="flex items-center justify-between mb-1">
              <span class="text-xs font-mono text-white/50 truncate max-w-[200px]" :title="msg.record_id">{{ (msg.record_id || '').slice(0, 8) }}...</span>
              <span class="text-xs text-white/40">{{ new Date(msg.date_created).toLocaleString() }}</span>
            </div>
            <div class="flex flex-wrap gap-2 text-xs">
              <span class="text-white/70">{{ msg.author }}</span>
              <span v-if="msg.descriptor.protocol" class="text-blue-300/80">{{ msg.descriptor.protocol }}</span>
              <span v-if="msg.descriptor.schema" class="text-purple-300/80">{{ msg.descriptor.schema }}</span>
            </div>
            <div v-if="msg.data" class="mt-1 text-xs text-white/40 font-mono truncate">{{ JSON.stringify(msg.data).slice(0, 120) }}</div>
          </div>
        </div>
      </div>
    </div>

    <!-- Last Sync & Actions -->
    <div class="flex items-center justify-between pt-3 border-t border-white/10">
      <div class="text-xs text-white/40">
        {{ dwnStatus?.last_sync ? `Last sync: ${new Date(dwnStatus.last_sync).toLocaleString()}` : 'Never synced' }}
      </div>
      <button @click="syncDWNs" :disabled="syncingDWNs || !dwnStatus?.running" class="glass-button glass-button-sm px-3 rounded-lg text-sm font-medium flex items-center gap-2 disabled:opacity-50">
        <svg class="w-4 h-4" :class="{ 'animate-spin': syncingDWNs }" fill="none" stroke="currentColor" viewBox="0 0 24 24">
          <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 4v5h.582m15.356 2A8.001 8.001 0 004.582 9m0 0H9m11 11v-5h-.581m0 0a8.003 8.003 0 01-15.357-2m15.357 2H15" />
        </svg>
        {{ syncingDWNs ? t('web5.syncing') : t('web5.syncNow') }}
      </button>
    </div>
    </template>
  </div>
</template>

<script setup lang="ts">
import { ref, computed } from 'vue'
import { useI18n } from 'vue-i18n'
import { rpcClient } from '@/api/rpc-client'
import { useAppStore } from '@/stores/app'
import { PackageState } from '@/types/api'
import type { DwnStatusData, DwnProtocol, DwnMessageEntry } from './types'

const { t } = useI18n()
const appStore = useAppStore()

const dwnStatus = ref<DwnStatusData | null>(null)
const dwnSyncStatus = ref<'synced' | 'syncing' | 'error' | 'idle'>('idle')
const dwnInstalled = computed(() => !!appStore.packages['dwn'])
const dwnRunning = computed(() => appStore.packages['dwn']?.state === PackageState.Running)
const syncingDWNs = ref(false)
const dwnProtocols = ref<DwnProtocol[]>([])
const dwnMessages = ref<DwnMessageEntry[]>([])
const showDwnMessages = ref(false)
const loadingDwnMessages = ref(false)
const showRegisterProtocol = ref(false)
const newProtocolUri = ref('')
const newProtocolPublished = ref(false)
const registeringProtocol = ref(false)
const removingProtocol = ref<string | null>(null)

const formatDwnStorage = computed(() => {
  if (!dwnStatus.value) return '0 B'
  const bytes = dwnStatus.value.storage_bytes
  if (bytes < 1024) return `${bytes} B`
  if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`
  if (bytes < 1024 * 1024 * 1024) return `${(bytes / (1024 * 1024)).toFixed(1)} MB`
  return `${(bytes / (1024 * 1024 * 1024)).toFixed(2)} GB`
})

async function loadDwnStatus() {
  try {
    const res = await rpcClient.call<DwnStatusData>({ method: 'dwn.status' })
    dwnStatus.value = res
    dwnSyncStatus.value = (res.sync_status as 'synced' | 'syncing' | 'error' | 'idle') || 'idle'
  } catch {
    dwnStatus.value = null
    dwnSyncStatus.value = 'idle'
  }
}

async function syncDWNs() {
  syncingDWNs.value = true
  dwnSyncStatus.value = 'syncing'
  try {
    const res = await rpcClient.call<{ sync_status: string; last_sync: string; messages_synced: number }>({ method: 'dwn.sync' })
    dwnSyncStatus.value = (res.sync_status as 'synced' | 'syncing' | 'error' | 'idle') || 'synced'
    await loadDwnStatus()
  } catch {
    dwnSyncStatus.value = 'error'
  } finally {
    syncingDWNs.value = false
  }
}

async function loadDwnProtocols() {
  try {
    const res = await rpcClient.call<{ protocols: DwnProtocol[] }>({ method: 'dwn.list-protocols' })
    dwnProtocols.value = res.protocols || []
  } catch {
    dwnProtocols.value = []
  }
}

async function registerDwnProtocol() {
  if (registeringProtocol.value || !newProtocolUri.value.trim()) return
  registeringProtocol.value = true
  try {
    await rpcClient.call({ method: 'dwn.register-protocol', params: { protocol: newProtocolUri.value.trim(), published: newProtocolPublished.value } })
    newProtocolUri.value = ''
    newProtocolPublished.value = false
    showRegisterProtocol.value = false
    await loadDwnProtocols()
    await loadDwnStatus()
  } catch {
    if (import.meta.env.DEV) console.error('Failed to register protocol')
  } finally {
    registeringProtocol.value = false
  }
}

async function removeDwnProtocol(protocol: string) {
  removingProtocol.value = protocol
  try {
    await rpcClient.call({ method: 'dwn.remove-protocol', params: { protocol } })
    await loadDwnProtocols()
    await loadDwnStatus()
  } catch {
    if (import.meta.env.DEV) console.error('Failed to remove protocol')
  } finally {
    removingProtocol.value = null
  }
}

async function toggleDwnMessages() {
  showDwnMessages.value = !showDwnMessages.value
  if (showDwnMessages.value) {
    await loadDwnMessages()
  }
}

async function loadDwnMessages() {
  const hadMessages = dwnMessages.value.length > 0
  loadingDwnMessages.value = true
  try {
    const res = await rpcClient.call<{ messages: DwnMessageEntry[]; count: number }>({ method: 'dwn.query-messages', params: { limit: 50 } })
    dwnMessages.value = res.messages || []
  } catch {
    if (!hadMessages) dwnMessages.value = []
  } finally {
    loadingDwnMessages.value = false
  }
}

defineExpose({ loadDwnStatus, loadDwnProtocols, loadDwnMessages, dwnMessages, showDwnMessages })
</script>
