<template>
  <div>
    <div class="flex items-center gap-3 mb-6">
      <button class="glass-button p-2 rounded-lg" @click="router.push({ name: 'cloud' })">
        <svg class="w-5 h-5 text-white" fill="none" stroke="currentColor" viewBox="0 0 24 24">
          <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 19l-7-7 7-7" />
        </svg>
      </button>
      <div>
        <h1 class="text-2xl font-bold text-white">Peer Files</h1>
        <p class="text-sm text-white/50">Browse files shared by federated nodes</p>
      </div>
    </div>

    <!-- Peer list -->
    <div v-if="!selectedPeer" class="space-y-3">
      <div v-if="loading" class="glass-card p-8 text-center">
        <p class="text-white/50 animate-pulse">Loading federation peers...</p>
      </div>

      <div v-else-if="peers.length === 0" class="glass-card p-8 text-center">
        <p class="text-white/50">No federated peers found. Join a federation from Settings to share files.</p>
      </div>

      <div
        v-for="peer in peers"
        :key="peer.did"
        data-controller-container
        tabindex="0"
        class="glass-card p-5 cursor-pointer transition-all hover:-translate-y-0.5 hover:bg-white/10"
        @click="browsePeer(peer)"
      >
        <div class="flex items-center gap-4">
          <div class="flex-shrink-0 w-10 h-10 rounded-full bg-purple-500/20 flex items-center justify-center">
            <svg class="w-5 h-5 text-purple-400" fill="none" stroke="currentColor" viewBox="0 0 24 24">
              <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 12h14M5 12a2 2 0 01-2-2V6a2 2 0 012-2h14a2 2 0 012 2v4a2 2 0 01-2 2M5 12a2 2 0 00-2 2v4a2 2 0 002 2h14a2 2 0 002-2v-4a2 2 0 00-2-2" />
            </svg>
          </div>
          <div class="flex-1 min-w-0">
            <h3 class="text-base font-semibold text-white truncate">{{ peer.name || truncateDid(peer.did) }}</h3>
            <p class="text-xs text-white/40 truncate">{{ peer.onion }}</p>
          </div>
          <div class="flex items-center gap-2">
            <span
              class="text-xs px-2 py-0.5 rounded-full"
              :class="peer.trust_level === 'trusted' ? 'bg-green-500/15 text-green-400' : 'bg-yellow-500/15 text-yellow-400'"
            >
              {{ peer.trust_level }}
            </span>
            <svg class="w-4 h-4 text-white/30" fill="none" stroke="currentColor" viewBox="0 0 24 24">
              <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5l7 7-7 7" />
            </svg>
          </div>
        </div>
      </div>
    </div>

    <!-- Peer content catalog -->
    <div v-else>
      <div class="flex items-center gap-3 mb-4">
        <button class="glass-button p-2 rounded-lg" @click="selectedPeer = null">
          <svg class="w-5 h-5 text-white" fill="none" stroke="currentColor" viewBox="0 0 24 24">
            <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 19l-7-7 7-7" />
          </svg>
        </button>
        <div>
          <h2 class="text-lg font-semibold text-white">{{ selectedPeer.name || truncateDid(selectedPeer.did) }}</h2>
          <p class="text-xs text-white/40">{{ selectedPeer.onion }}</p>
        </div>
      </div>

      <div v-if="catalogLoading" class="glass-card p-8 text-center">
        <p class="text-white/50 animate-pulse">Connecting via Tor... This may take a few seconds.</p>
      </div>

      <div v-else-if="catalogError" class="glass-card p-6">
        <p class="text-red-400 text-sm">{{ catalogError }}</p>
        <button class="glass-button mt-3 px-4 py-2 rounded-lg text-sm" @click="browsePeer(selectedPeer!)">Retry</button>
      </div>

      <div v-else-if="catalogItems.length === 0" class="glass-card p-8 text-center">
        <p class="text-white/50">This peer has no shared files.</p>
      </div>

      <div v-else class="space-y-2">
        <div
          v-for="item in catalogItems"
          :key="item.id"
          class="glass-card p-4 flex items-center gap-4"
        >
          <div class="flex-shrink-0 w-9 h-9 rounded-lg flex items-center justify-center" :class="fileIconBg(item.mime_type)">
            <svg class="w-5 h-5" :class="fileIconColor(item.mime_type)" fill="none" stroke="currentColor" viewBox="0 0 24 24">
              <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" :d="fileIconPath(item.mime_type)" />
            </svg>
          </div>
          <div class="flex-1 min-w-0">
            <p class="text-sm font-medium text-white truncate">{{ item.filename }}</p>
            <p class="text-xs text-white/40">{{ formatSize(item.size_bytes) }} &middot; {{ item.mime_type }}</p>
          </div>
          <div class="flex items-center gap-2">
            <span
              class="text-xs px-2 py-0.5 rounded-full"
              :class="accessBadgeClass(item.access)"
            >
              {{ accessLabel(item.access) }}
            </span>
            <button
              v-if="canDownload(item.access)"
              class="glass-button px-3 py-1.5 rounded-lg text-xs font-medium"
              :disabled="downloading === item.id"
              @click="downloadFile(item)"
            >
              {{ downloading === item.id ? 'Downloading...' : 'Download' }}
            </button>
          </div>
        </div>
      </div>
    </div>
  </div>
</template>

<script setup lang="ts">
import { ref, onMounted } from 'vue'
import { useRouter } from 'vue-router'
import { rpcClient } from '@/api/rpc-client'

const router = useRouter()

interface PeerNode {
  did: string
  pubkey: string
  onion: string
  name?: string
  trust_level: string
}

interface CatalogItem {
  id: string
  filename: string
  mime_type: string
  size_bytes: number
  description: string
  access: string | { paid: { price_sats: number } }
}

const loading = ref(true)
const peers = ref<PeerNode[]>([])
const selectedPeer = ref<PeerNode | null>(null)
const catalogLoading = ref(false)
const catalogError = ref('')
const catalogItems = ref<CatalogItem[]>([])
const downloading = ref<string | null>(null)

onMounted(async () => {
  try {
    const result = await rpcClient.federationListNodes()
    peers.value = result?.nodes ?? []
  } catch {
    peers.value = []
  } finally {
    loading.value = false
  }
})

function truncateDid(did: string): string {
  if (did.length <= 24) return did
  return did.slice(0, 16) + '...' + did.slice(-8)
}

async function browsePeer(peer: PeerNode) {
  selectedPeer.value = peer
  catalogLoading.value = true
  catalogError.value = ''
  catalogItems.value = []
  try {
    const result = await rpcClient.call<{ items?: CatalogItem[] }>({ method: 'content.browse-peer', params: { onion: peer.onion }, timeout: 30000 })
    catalogItems.value = result?.items ?? []
  } catch (e: unknown) {
    catalogError.value = e instanceof Error ? e.message : 'Failed to connect to peer'
  } finally {
    catalogLoading.value = false
  }
}

function formatSize(bytes: number): string {
  if (bytes === 0) return '0 B'
  const units = ['B', 'KB', 'MB', 'GB']
  const i = Math.floor(Math.log(bytes) / Math.log(1024))
  return (bytes / Math.pow(1024, i)).toFixed(i > 0 ? 1 : 0) + ' ' + units[i]
}

function fileIconBg(mime: string): string {
  if (mime.startsWith('image/')) return 'bg-blue-500/15'
  if (mime.startsWith('audio/')) return 'bg-orange-500/15'
  if (mime.startsWith('video/')) return 'bg-pink-500/15'
  if (mime.startsWith('text/')) return 'bg-green-500/15'
  return 'bg-white/10'
}

function fileIconColor(mime: string): string {
  if (mime.startsWith('image/')) return 'text-blue-400'
  if (mime.startsWith('audio/')) return 'text-orange-400'
  if (mime.startsWith('video/')) return 'text-pink-400'
  if (mime.startsWith('text/')) return 'text-green-400'
  return 'text-white/60'
}

function fileIconPath(mime: string): string {
  if (mime.startsWith('image/')) return 'M4 16l4.586-4.586a2 2 0 012.828 0L16 16m-2-2l1.586-1.586a2 2 0 012.828 0L20 14m-6-6h.01M6 20h12a2 2 0 002-2V6a2 2 0 00-2-2H6a2 2 0 00-2 2v12a2 2 0 002 2z'
  if (mime.startsWith('audio/')) return 'M9 19V6l12-3v13M9 19c0 1.105-1.343 2-3 2s-3-.895-3-2 1.343-2 3-2 3 .895 3 2zm12-3c0 1.105-1.343 2-3 2s-3-.895-3-2 1.343-2 3-2 3 .895 3 2zM9 10l12-3'
  if (mime.startsWith('video/')) return 'M15 10l4.553-2.276A1 1 0 0121 8.618v6.764a1 1 0 01-1.447.894L15 14M5 18h8a2 2 0 002-2V8a2 2 0 00-2-2H5a2 2 0 00-2 2v8a2 2 0 002 2z'
  return 'M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z'
}

function accessLabel(access: CatalogItem['access']): string {
  if (access === 'free') return 'Free'
  if (access === 'peersonly') return 'Peers Only'
  if (typeof access === 'object' && 'paid' in access) return `${access.paid.price_sats} sats`
  return String(access)
}

function accessBadgeClass(access: CatalogItem['access']): string {
  if (access === 'free') return 'bg-green-500/15 text-green-400'
  if (access === 'peersonly') return 'bg-blue-500/15 text-blue-400'
  if (typeof access === 'object' && 'paid' in access) return 'bg-orange-500/15 text-orange-400'
  return 'bg-white/10 text-white/50'
}

function canDownload(access: CatalogItem['access']): boolean {
  return access === 'free' || access === 'peersonly'
}

async function downloadFile(item: CatalogItem) {
  if (!selectedPeer.value) return
  downloading.value = item.id
  try {
    const result = await rpcClient.call<{ data?: string }>({
      method: 'content.download-peer',
      params: { onion: selectedPeer.value.onion, content_id: item.id },
      timeout: 120000,
    })
    if (result?.data) {
      const blob = new Blob([Uint8Array.from(atob(result.data), c => c.charCodeAt(0))], { type: item.mime_type })
      const url = URL.createObjectURL(blob)
      const a = document.createElement('a')
      a.href = url
      a.download = item.filename.split('/').pop() || item.filename
      a.click()
      URL.revokeObjectURL(url)
    }
  } catch (e: unknown) {
    if (import.meta.env.DEV) console.warn('Download failed', e)
  } finally {
    downloading.value = null
  }
}
</script>
