<template>
  <BaseModal :show="show" :title="t('web5.sendBitcoinTitle')" max-width="max-w-2xl" content-class="max-h-[90vh] overflow-y-auto" @close="close">
        <!-- ============ CONFIRM PANE (second step, mirrors the scan flow) ============ -->
        <template v-if="confirming">
          <div class="mb-3 p-3 bg-white/5 rounded-lg">
            <div class="flex items-center justify-between mb-2">
              <span class="text-xs text-white/50">Method</span>
              <span class="text-sm font-medium" :class="methodColor">{{ methodLabel }}</span>
            </div>
            <div v-if="dest.trim()" class="mb-1">
              <p class="text-xs text-white/50 mb-1">{{ effectiveMethod === 'lightning' ? 'Invoice' : effectiveMethod === 'ark' ? 'Destination' : 'Address' }}</p>
              <p class="text-xs font-mono text-white/80 break-all">{{ destDisplay }}</p>
            </div>
            <p v-else class="text-xs text-white/60">Creates a {{ methodLabel }} token you can share — sats leave your balance when it's redeemed.</p>
          </div>

          <!-- Live balance impact -->
          <div class="mb-3 p-3 bg-white/5 rounded-lg space-y-1.5">
            <div class="flex items-center justify-between">
              <span class="text-xs text-white/50">{{ methodLabel }} balance</span>
              <span class="text-sm font-medium text-white/80">{{ confirmBalance === null ? '…' : confirmBalance.toLocaleString() + ' sats' }}</span>
            </div>
            <div class="flex items-center justify-between">
              <span class="text-xs text-white/50 flex items-center gap-2">
                Amount
                <span v-if="invoiceAmountSats !== null" class="text-[11px] px-2 py-0.5 rounded-full bg-white/10 text-white/50">set by invoice</span>
              </span>
              <span class="text-sm font-medium text-white/80">−{{ confirmAmount.toLocaleString() }} sats</span>
            </div>
            <div class="flex items-center justify-between">
              <span class="text-xs text-white/50">Balance after</span>
              <span class="text-sm font-medium" :class="insufficient ? 'text-red-400' : 'text-white/80'">
                {{ confirmBalance === null ? '…' : balanceAfter.toLocaleString() + ' sats' }}
              </span>
            </div>
          </div>
          <p v-if="insufficient" class="text-xs text-red-400 mb-3">Not enough {{ methodLabel }} balance for this amount.</p>
          <p v-else-if="isSweep" class="text-xs text-white/50 mb-3">Sweeps the entire on-chain balance minus network fees.</p>
          <p v-else-if="effectiveMethod === 'onchain'" class="text-xs text-white/50 mb-3">Network fees are deducted on top of the amount.</p>

          <div v-if="error" class="mb-3 alert-error">{{ error }}</div>

          <div class="flex gap-3">
            <button @click="confirming = false" :disabled="processing" class="flex-1 glass-button px-4 py-2 rounded-lg text-sm">Back</button>
            <button @click="send" :disabled="processing || insufficient || (confirmAmount <= 0 && !isSweep)" class="flex-1 glass-button glass-button-warning px-4 py-2 rounded-lg text-sm font-medium disabled:opacity-50">
              {{ processing ? t('common.sending') : 'Confirm & Send' }}
            </button>
          </div>
        </template>

        <template v-else>
        <!-- Method tabs -->
        <div class="flex gap-1 mb-4 p-1 bg-white/5 rounded-lg">
          <button
            v-for="m in (['lightning', 'onchain', 'ecash', 'fedimint', 'ark'] as const)"
            :key="m"
            @click="sendMethod = m"
            class="flex-1 px-2 py-1.5 rounded text-xs font-medium capitalize transition-colors"
            :class="sendMethod === m ? 'bg-white/15 text-white' : 'text-white/50 hover:text-white/80'"
          >{{ m === 'onchain' ? t('sendBitcoin.onChain') : m === 'lightning' ? t('sendBitcoin.lightning') : m === 'ecash' ? 'Cashu' : m === 'fedimint' ? 'Fedi' : 'Ark' }}</button>
        </div>

        <div v-if="sendMethod === 'auto'" class="mb-3 p-2 bg-white/5 rounded-lg">
          <p class="text-xs text-white/50">{{ t('sendBitcoin.autoMethodDesc') }}</p>
        </div>

        <div class="mb-3">
          <div class="flex items-center justify-between mb-1">
            <label class="text-white/60 text-sm">{{ t('sendBitcoin.amountSats') }}</label>
            <button
              v-if="sendMethod === 'onchain'"
              @click="toggleSendAll"
              class="text-xs px-2 py-0.5 rounded border transition-colors"
              :class="sendAll
                ? 'bg-orange-500/20 border-orange-500/40 text-orange-300'
                : 'bg-white/5 border-white/15 text-white/60 hover:text-white/90'"
            >
              Send all funds
            </button>
          </div>
          <input
            v-model.number="amount"
            type="number"
            min="1"
            :placeholder="sendAll ? '' : '1000'"
            :disabled="sendAll"
            class="w-full input-glass disabled:opacity-50"
          />
          <p v-if="sendAll" class="text-xs text-white/50 mt-1">
            Sweeps your entire on-chain balance{{ onchainBalance !== null ? ` (~${onchainBalance.toLocaleString()} sats)` : '' }} minus network fees.
          </p>
        </div>

        <div v-if="effectiveMethod !== 'ecash'" class="mb-3">
          <label class="text-white/60 text-sm block mb-1">
            {{ effectiveMethod === 'lightning' ? t('sendBitcoin.lightningInvoice') : effectiveMethod === 'ark' ? 'Ark address, invoice or lightning address' : t('sendBitcoin.bitcoinAddress') }}
          </label>
          <textarea v-model="dest" rows="2" :placeholder="effectiveMethod === 'lightning' ? 'lnbc...' : effectiveMethod === 'ark' ? 'tark1… / lnbc… / user@lnaddress' : 'bc1...'" class="w-full input-glass font-mono"></textarea>
        </div>

        <div v-if="ecashToken" class="mb-3 p-2 bg-white/5 rounded-lg">
          <p class="text-white/50 text-xs mb-1">{{ t('sendBitcoin.tokenShareLabel') }}</p>
          <!-- QR so the recipient can scan the token straight off this screen
               (animated multi-frame not needed: qrcode handles these sizes). -->
          <div class="flex justify-center my-2">
            <canvas ref="tokenQrCanvas" class="rounded-lg bg-white p-2"></canvas>
          </div>
          <p class="text-xs font-mono text-white/80 break-all">{{ ecashToken }}</p>
          <button @click="copyText(ecashToken)" class="mt-2 text-xs text-orange-400 hover:text-orange-300">{{ t('common.copy') }}</button>
        </div>

        <div v-if="resultTxid" class="mb-3 alert-success">
          <p class="text-xs">{{ t('sendBitcoin.sentTx', { txid: resultTxid }) }}</p>
        </div>
        <div v-if="resultHash" class="mb-3 alert-success">
          <p class="text-xs">{{ t('sendBitcoin.paidHash', { hash: resultHash }) }}</p>
        </div>
        <div v-if="resultArk" class="mb-3 alert-success">
          <p class="text-xs">{{ resultArk }}</p>
        </div>

        <div v-if="error" class="mb-3 alert-error">{{ error }}</div>

        <div class="flex gap-3">
          <button @click="close" class="flex-1 glass-button px-4 py-2 rounded-lg text-sm">{{ t('common.close') }}</button>
          <button @click="$emit('scan')" class="flex-1 glass-button px-4 py-2 rounded-lg text-sm font-medium flex items-center justify-center gap-2">
            <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 8V6a2 2 0 012-2h2M3 16v2a2 2 0 002 2h2m10-16h2a2 2 0 012 2v2m-4 12h2a2 2 0 002-2v-2M7 12h10" />
            </svg>
            Scan
          </button>
          <button @click="review" :disabled="processing" class="flex-1 glass-button glass-button-warning px-4 py-2 rounded-lg text-sm font-medium disabled:opacity-50">
            {{ t('common.send') }}
          </button>
        </div>
        </template>
  </BaseModal>
</template>

<script setup lang="ts">
import { ref, computed, watch, nextTick } from 'vue'
import { useI18n } from 'vue-i18n'
import { rpcClient } from '@/api/rpc-client'
import BaseModal from '@/components/BaseModal.vue'

const { t } = useI18n()

const props = defineProps<{ show: boolean }>()
const emit = defineEmits<{ close: []; sent: []; scan: [] }>()

// 'auto' remains in the type for the effectiveMethod logic but is no longer
// offered as a tab (hidden per operator request 2026-07-22).
const sendMethod = ref<'auto' | 'lightning' | 'onchain' | 'ecash' | 'fedimint' | 'ark'>('lightning')
const amount = ref<number>(0)
const dest = ref('')
const processing = ref(false)
const error = ref('')
const resultTxid = ref('')
const resultHash = ref('')
const resultArk = ref('')
const ecashToken = ref('')

// "Send all funds" — sweeps the whole on-chain balance (explicit on-chain tab only)
const sendAll = ref(false)
const onchainBalance = ref<number | null>(null)
const isSweep = computed(() => sendMethod.value === 'onchain' && sendAll.value)

function toggleSendAll() {
  sendAll.value = !sendAll.value
  if (sendAll.value && onchainBalance.value === null) {
    rpcClient.call<{ balance_sats: number }>({ method: 'lnd.getinfo', timeout: 5000 })
      .then((res) => { onchainBalance.value = res.balance_sats || 0 })
      .catch(() => { /* balance hint is best-effort */ })
  }
}

// Leaving the on-chain tab disarms the sweep so it can never apply elsewhere
watch(sendMethod, (m) => { if (m !== 'onchain') sendAll.value = false })

const effectiveMethod = computed(() => {
  if (sendMethod.value !== 'auto') return sendMethod.value
  const amt = amount.value || 0
  if (amt <= 0) return 'lightning'
  if (amt < 1000) return 'ecash'
  if (amt > 500000) return 'onchain'
  return 'lightning'
})

// --- Second-step confirmation (parity with the scan flow): review shows the
// --- balance reduction before anything is sent or any token is minted.

const confirming = ref(false)
const confirmBalance = ref<number | null>(null)
const invoiceAmountSats = ref<number | null>(null)

const methodLabel = computed(() => ({
  auto: 'Auto', lightning: 'Lightning', onchain: 'On-chain',
  ecash: 'Cashu', fedimint: 'Fedimint', ark: 'Ark',
}[effectiveMethod.value]))

const methodColor = computed(() => ({
  auto: 'text-white/80', lightning: 'text-yellow-400', onchain: 'text-orange-500',
  ecash: 'text-purple-400', fedimint: 'text-blue-400', ark: 'text-teal-400',
}[effectiveMethod.value]))

const destDisplay = computed(() => {
  const d = dest.value.trim()
  return d.length > 64 ? `${d.slice(0, 38)}…${d.slice(-18)}` : d
})

/** Amount encoded in a BOLT11 invoice's human-readable part, in sats (null = zero-amount). */
function parseBolt11AmountSats(invoice: string): number | null {
  const m = /^ln(?:bcrt|bc|tb)(\d+)?([munp])?1/.exec(invoice.toLowerCase())
  if (!m || !m[1]) return null
  const value = Number(m[1])
  const mult = { m: 1e-3, u: 1e-6, n: 1e-9, p: 1e-12 }[m[2] as 'm' | 'u' | 'n' | 'p'] ?? 1
  return Math.round(value * mult * 1e8)
}

// An invoice-fixed amount always wins over the typed one; a sweep is priced
// at the whole balance.
const confirmAmount = computed(() => {
  if (isSweep.value) return confirmBalance.value ?? 0
  if (effectiveMethod.value === 'lightning' && invoiceAmountSats.value !== null) return invoiceAmountSats.value
  return amount.value > 0 ? Math.floor(amount.value) : 0
})
const balanceAfter = computed(() => (confirmBalance.value ?? 0) - confirmAmount.value)
const insufficient = computed(() =>
  confirmBalance.value !== null && confirmAmount.value > confirmBalance.value && !isSweep.value
)

async function loadConfirmBalance() {
  confirmBalance.value = null
  try {
    if (effectiveMethod.value === 'ecash') {
      const res = await rpcClient.call<{ balance_sats: number }>({ method: 'wallet.ecash-balance' })
      confirmBalance.value = res.balance_sats ?? 0
    } else if (effectiveMethod.value === 'fedimint') {
      const res = await rpcClient.call<{ balance_sats: number }>({ method: 'wallet.fedimint-balance' })
      confirmBalance.value = res.balance_sats ?? 0
    } else {
      const res = await rpcClient.call<{ balance_sats: number; channel_balance_sats: number }>({ method: 'lnd.getinfo' })
      confirmBalance.value = effectiveMethod.value === 'onchain'
        ? (res.balance_sats ?? 0)
        : (res.channel_balance_sats ?? 0)
    }
  } catch {
    confirmBalance.value = null // balance preview is best-effort; send still guarded server-side
  }
}

function review() {
  error.value = ''
  const method = effectiveMethod.value
  const d = dest.value.trim()
  if (method === 'lightning') {
    if (!d) { error.value = t('web5.pasteInvoice'); return }
    invoiceAmountSats.value = parseBolt11AmountSats(d)
  } else {
    invoiceAmountSats.value = null
    if (method === 'ark' && !d) { error.value = 'Enter an Ark address, invoice or lightning address'; return }
    if (method === 'onchain' && !d) { error.value = t('web5.enterBitcoinAddress'); return }
  }
  if (!isSweep.value && confirmAmount.value <= 0 && invoiceAmountSats.value === null) {
    error.value = t('sendBitcoin.amountSats'); return
  }
  void loadConfirmBalance()
  confirming.value = true
}

function close() {
  error.value = ''
  resultTxid.value = ''
  resultHash.value = ''
  resultArk.value = ''
  ecashToken.value = ''
  confirming.value = false
  emit('close')
}

function copyText(text: string) {
  navigator.clipboard.writeText(text).catch(() => {})
}

const tokenQrCanvas = ref<HTMLCanvasElement | null>(null)
watch(ecashToken, async (token) => {
  if (!token) return
  await nextTick()
  if (!tokenQrCanvas.value) return
  try {
    const QRCode = await import('qrcode')
    await QRCode.toCanvas(tokenQrCanvas.value, token, { width: 220, margin: 1 })
  } catch { /* QR is a convenience — the copyable text is authoritative */ }
})

async function send() {
  if (processing.value) return
  // Zero typed amount is fine when the invoice fixes the amount or we sweep.
  if (!amount.value && !isSweep.value && invoiceAmountSats.value === null) return
  processing.value = true
  error.value = ''
  ecashToken.value = ''
  resultTxid.value = ''
  resultHash.value = ''
  resultArk.value = ''

  const method = effectiveMethod.value
  try {
    if (method === 'ark') {
      if (!dest.value.trim()) { error.value = 'Enter an Ark address, invoice or lightning address'; return }
      await rpcClient.call<{ sent: boolean }>({
        method: 'wallet.ark-send',
        params: { destination: dest.value.trim(), amount_sats: amount.value },
        // Ark sends can wait on round participation.
        timeout: 130000,
      })
      resultArk.value = `Sent ${amount.value.toLocaleString()} sats via Ark`
    } else if (method === 'ecash') {
      const res = await rpcClient.call<{ token: string }>({
        method: 'wallet.ecash-send',
        params: { amount_sats: amount.value },
      })
      ecashToken.value = res.token
    } else if (method === 'fedimint') {
      const res = await rpcClient.call<{ token: string }>({
        method: 'wallet.fedimint-send',
        params: { amount_sats: amount.value },
        timeout: 60000,
      })
      ecashToken.value = res.token
    } else if (method === 'lightning') {
      if (!dest.value.trim()) { error.value = t('web5.pasteInvoice'); return }
      const res = await rpcClient.call<{ payment_hash: string }>({
        method: 'lnd.payinvoice',
        params: { payment_request: dest.value.trim() },
      })
      resultHash.value = res.payment_hash
    } else {
      if (!dest.value.trim()) { error.value = t('web5.enterBitcoinAddress'); return }
      const res = await rpcClient.call<{ txid: string }>({
        method: 'lnd.sendcoins',
        params: isSweep.value
          ? { addr: dest.value.trim(), send_all: true }
          : { addr: dest.value.trim(), amount: amount.value },
      })
      resultTxid.value = res.txid
    }
    emit('sent')
    // Back to the form pane so the success/token panes are visible.
    confirming.value = false
  } catch (err: unknown) {
    error.value = err instanceof Error ? err.message : t('web5.sendFailed')
  } finally {
    processing.value = false
  }
}
</script>
