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

const router = useRouter()

// Mirrors `crate::streaming::pricing::ServicePricing` (Metric is rename_all =
// "lowercase", so it round-trips verbatim back to streaming.configure-service).
type Metric = 'bytes' | 'milliseconds' | 'requests'

interface ServicePricing {
  service_id: string
  name: string
  metric: Metric
  step_size: number
  price_per_step: number
  min_steps: number
  enabled: boolean
  description: string
  accepted_mints: string[]
}

const services = ref<ServicePricing[]>([])
const loading = ref(true)
const loadError = ref('')
const savingId = ref<string | null>(null)
const statusMsg = ref('')
const statusIsError = ref(false)

// "Free everything" is the default — every service ships disabled. The banner
// reassures the user nothing is being charged for until they opt in.
const allFree = computed(() => services.value.every((s) => !s.enabled))

function showStatus(msg: string, isError: boolean) {
  statusMsg.value = msg
  statusIsError.value = isError
  setTimeout(() => { statusMsg.value = '' }, 5000)
}

/** Human label for one priced step, e.g. "MB", "minute", "request". */
function unitLabel(metric: Metric, stepSize: number): string {
  if (metric === 'bytes') {
    if (stepSize === 1_073_741_824) return 'GB'
    if (stepSize === 1_048_576) return 'MB'
    if (stepSize === 1024) return 'KB'
    return `${stepSize.toLocaleString()} bytes`
  }
  if (metric === 'milliseconds') {
    if (stepSize === 3_600_000) return 'hour'
    if (stepSize === 60_000) return 'minute'
    if (stepSize === 1000) return 'second'
    return `${stepSize.toLocaleString()} ms`
  }
  // requests
  return stepSize === 1 ? 'request' : `${stepSize.toLocaleString()} requests`
}

function minimumNote(svc: ServicePricing): string {
  if (svc.min_steps <= 0) return ''
  return `Minimum purchase: ${svc.min_steps.toLocaleString()} ${unitLabel(svc.metric, svc.step_size)}${svc.min_steps > 1 ? 's' : ''}`
}

async function load() {
  loading.value = true
  loadError.value = ''
  try {
    const res = await rpcClient.call<{ services: ServicePricing[] }>({ method: 'streaming.list-services' })
    services.value = (res.services || []).map((s) => ({
      ...s,
      // Price must stay >= 1 sat: the backend rejects price_per_step == 0.
      price_per_step: Math.max(1, s.price_per_step),
    }))
  } catch (e) {
    loadError.value = e instanceof Error ? e.message : 'Failed to load services'
  } finally {
    loading.value = false
  }
}

async function saveService(svc: ServicePricing) {
  if (svc.price_per_step < 1) svc.price_per_step = 1
  savingId.value = svc.service_id
  try {
    await rpcClient.call({
      method: 'streaming.configure-service',
      params: {
        service_id: svc.service_id,
        name: svc.name,
        metric: svc.metric,
        step_size: svc.step_size,
        price_per_step: svc.price_per_step,
        min_steps: svc.min_steps,
        enabled: svc.enabled,
        description: svc.description,
        accepted_mints: svc.accepted_mints,
      },
    })
    showStatus(
      svc.enabled
        ? `Charging ${svc.price_per_step} sats per ${unitLabel(svc.metric, svc.step_size)} for ${svc.name}.`
        : `${svc.name} is now free.`,
      false,
    )
  } catch (e) {
    showStatus(e instanceof Error ? e.message : 'Failed to save', true)
    // Reload so the UI reflects the persisted truth after a failed write.
    void load()
  } finally {
    savingId.value = null
  }
}

onMounted(load)
</script>

<template>
  <div class="pb-6">
    <BackButton label="Back to Web5" @click="router.push('/dashboard/web5')" />

    <div class="mb-6">
      <h1 class="text-3xl font-bold text-white mb-2">Networking Profits — Settings</h1>
      <p class="text-white/70">
        Control what your node charges other peers for. By default everything is shared for
        free — turn a service on to start earning sats (ecash) for it. Payments are collected
        as Cashu tokens through your node's wallet.
      </p>
    </div>

    <!-- Status message -->
    <div
      v-if="statusMsg"
      role="status"
      aria-live="polite"
      class="mb-4 p-3 rounded-lg text-sm"
      :class="statusIsError ? 'bg-red-500/20 text-red-300' : 'bg-green-500/20 text-green-300'"
    >
      {{ statusMsg }}
    </div>

    <!-- Everything-free reassurance banner -->
    <div
      v-if="!loading && allFree"
      class="mb-6 p-4 rounded-lg bg-green-500/10 border border-green-500/20 flex items-center gap-3"
    >
      <span class="text-xl">✓</span>
      <p class="text-sm text-green-200">
        Everything is free. Your node isn't charging for anything — enable a service below to
        start earning.
      </p>
    </div>

    <div v-if="loading" class="glass-card p-6 text-white/60 text-sm">Loading services…</div>
    <div v-else-if="loadError" class="glass-card p-6 text-red-300 text-sm">{{ loadError }}</div>

    <div v-else class="space-y-4">
      <div v-for="svc in services" :key="svc.service_id" class="glass-card p-6">
        <div class="flex items-start justify-between gap-4 mb-3">
          <div class="min-w-0">
            <h2 class="text-lg font-semibold text-white">{{ svc.name }}</h2>
            <p class="text-sm text-white/60 mt-0.5">{{ svc.description }}</p>
          </div>
          <div class="flex items-center gap-2 shrink-0">
            <span class="text-xs" :class="svc.enabled ? 'text-orange-400' : 'text-white/40'">
              {{ svc.enabled ? 'Paid' : 'Free' }}
            </span>
            <ToggleSwitch :model-value="svc.enabled" @update:model-value="(v) => (svc.enabled = v)" />
          </div>
        </div>

        <div class="flex flex-col sm:flex-row sm:items-end gap-3">
          <div class="flex-1" :class="{ 'opacity-40 pointer-events-none': !svc.enabled }">
            <label class="text-xs text-white/50 block mb-1">Price</label>
            <div class="flex items-center gap-2">
              <input
                v-model.number="svc.price_per_step"
                type="number"
                min="1"
                step="1"
                :disabled="!svc.enabled"
                class="w-28 bg-black/30 border border-white/10 rounded-lg px-3 py-2 text-sm text-white focus:outline-none focus:border-orange-500/50"
              />
              <span class="text-sm text-white/70">sats per {{ unitLabel(svc.metric, svc.step_size) }}</span>
            </div>
            <p v-if="minimumNote(svc)" class="text-xs text-white/40 mt-1">{{ minimumNote(svc) }}</p>
          </div>
          <button
            @click="saveService(svc)"
            :disabled="savingId === svc.service_id"
            class="glass-button glass-button-warning px-4 py-2 rounded-lg text-sm disabled:opacity-50"
          >
            {{ savingId === svc.service_id ? 'Saving…' : 'Save' }}
          </button>
        </div>
      </div>
    </div>
  </div>
</template>
