<script setup lang="ts">
import { computed, ref, watch } from 'vue'
import { useForm } from 'vee-validate'
import { toTypedSchema } from '@vee-validate/zod'
import * as z from 'zod'
import { decode as decodeBolt11 } from 'light-bolt11-decoder'
import { injectService, SERVICE_TOKENS } from '@/core/di-container'
import { Dialog, DialogContent, DialogDescription, DialogHeader, DialogTitle } from '@/components/ui/dialog'
import { Button } from '@/components/ui/button'
import { Input } from '@/components/ui/input'
import { Textarea } from '@/components/ui/textarea'
import { Send, AlertCircle, Loader2, ScanLine } from 'lucide-vue-next'
import { FormControl, FormDescription, FormField, FormItem, FormLabel, FormMessage } from '@/components/ui/form'
import QRScanner from '@/components/ui/qr-scanner.vue'

interface Props {
  open: boolean
  initialDestination?: string
}

interface Emits {
  (e: 'update:open', value: boolean): void
}

interface ParsedInvoice {
  amount: number // in sats
  description: string
  bolt11: string
  paymentHash: string
  expiry?: number
}

interface ParsedLNURL {
  type: 'lnurl' | 'lightning-address'
  minSendable: number // in msats
  maxSendable: number // in msats
  description: string
}

const props = defineProps<Props>()
const emit = defineEmits<Emits>()

// Services
const walletService = injectService(SERVICE_TOKENS.WALLET_SERVICE) as any
const toastService = injectService(SERVICE_TOKENS.TOAST_SERVICE) as any

// Payment parsing state
const parsedInvoice = ref<ParsedInvoice | null>(null)
const parsedLNURL = ref<ParsedLNURL | null>(null)
const paymentType = ref<'bolt11' | 'lnurl' | 'lightning-address' | 'unknown'>('unknown')

// Payment type detection functions
function isLNURL(input: string): boolean {
  const lower = input.toLowerCase()
  return lower.startsWith('lnurl1') ||
         lower.startsWith('lnurlp://') ||
         lower.startsWith('lnurlw://') ||
         lower.startsWith('lnurlauth://')
}

function isLightningAddress(input: string): boolean {
  return /^[\w.+-~_]+@[\w.+-~_]+$/.test(input)
}

function isBolt11(input: string): boolean {
  const lower = input.toLowerCase()
  return lower.startsWith('lnbc') || lower.startsWith('lntb') || lower.startsWith('lnbcrt')
}

function parseBolt11Invoice(bolt11: string): ParsedInvoice | null {
  try {
    const decoded = decodeBolt11(bolt11)

    // Extract amount from millisatoshis
    const amountMsat = decoded.sections.find(s => s.name === 'amount')?.value
    const amount = amountMsat ? Number(amountMsat) / 1000 : 0

    // Extract description
    const description = decoded.sections.find(s => s.name === 'description')?.value || ''

    // Extract payment hash
    const paymentHash = decoded.sections.find(s => s.name === 'payment_hash')?.value || ''

    return {
      amount,
      description,
      bolt11,
      paymentHash,
    }
  } catch (error) {
    console.error('Failed to decode BOLT11 invoice:', error)
    return null
  }
}

function normalizePaymentRequest(request: string): string {
  let normalized = request.trim()
  const req = normalized.toLowerCase()

  // Handle Lightning URI prefix stripping (following LNbits implementation)
  if (req.startsWith('lightning:')) {
    normalized = normalized.slice(10) // Remove "lightning:" (10 chars)
  } else if (req.startsWith('lnurl:')) {
    normalized = normalized.slice(6) // Remove "lnurl:" (6 chars)
  } else if (req.includes('lightning=lnurl1')) {
    // Extract LNURL from lightning parameter
    normalized = normalized.split('lightning=')[1].split('&')[0]
  } else if (req.includes('lightning=')) {
    // Handle BIP-21 Bitcoin URIs with Lightning fallback
    normalized = normalized.split('lightning=')[1]
    // Remove any additional query parameters
    if (normalized.includes('&')) {
      normalized = normalized.split('&')[0]
    }
  }

  return normalized.trim()
}

function parsePaymentDestination(destination: string) {
  // Clear previous parsing results
  parsedInvoice.value = null
  parsedLNURL.value = null
  paymentType.value = 'unknown'

  if (!destination.trim()) return

  // Normalize the destination by stripping URI prefixes
  const cleanDest = normalizePaymentRequest(destination)

  if (isBolt11(cleanDest)) {
    paymentType.value = 'bolt11'
    parsedInvoice.value = parseBolt11Invoice(cleanDest)
  } else if (isLNURL(cleanDest)) {
    paymentType.value = 'lnurl'
    // LNURL parsing would require API call to resolve
    // For now, just mark as LNURL type
  } else if (isLightningAddress(cleanDest)) {
    paymentType.value = 'lightning-address'
    // Lightning address parsing would require API call
    // For now, just mark as lightning address type
  }
}

// Form validation schema - always include amount but make it optional
const formSchema = toTypedSchema(z.object({
  destination: z.string().min(1, "Destination is required"),
  amount: z.number().min(1, "Amount must be at least 1 sat").max(1000000, "Amount too large").optional(),
  comment: z.string().optional()
}))

// Form setup with dynamic schema
const form = useForm({
  validationSchema: formSchema,
  initialValues: {
    destination: props.initialDestination || '',
    amount: 100,
    comment: ''
  }
})

const { resetForm, values, setFieldValue } = form
// Custom validation logic considering payment type
const isFormValid = computed(() => {
  // Check if destination is valid
  if (!values.destination || values.destination.trim() === '') return false

  // Check if amount is required and valid
  const needsAmountInput = paymentType.value === 'lnurl' ||
                          paymentType.value === 'lightning-address' ||
                          (paymentType.value === 'bolt11' && parsedInvoice.value?.amount === 0)

  if (needsAmountInput) {
    return !!(values.amount && values.amount > 0 && values.amount <= 1000000)
  }

  // For BOLT11 invoices with fixed amounts, no amount input needed
  return true
})

// Watch for prop changes
watch(() => props.initialDestination, (newDestination) => {
  if (newDestination) {
    setFieldValue('destination', newDestination)
  }
}, { immediate: true })

// Watch destination changes to parse payment type
watch(() => values.destination, (newDestination) => {
  parsePaymentDestination(newDestination || '')
}, { immediate: true })

// State
const isSending = computed(() => walletService?.isSendingPayment?.value || false)
const showScanner = ref(false)
const error = computed(() => walletService?.error?.value)

// Computed properties for UI logic
const showAmountField = computed(() => {
  return paymentType.value === 'lnurl' ||
         paymentType.value === 'lightning-address' ||
         (paymentType.value === 'bolt11' && parsedInvoice.value?.amount === 0)
})

const displayAmount = computed(() => {
  if (parsedInvoice.value && parsedInvoice.value.amount > 0) {
    return parsedInvoice.value.amount
  }
  return null
})

const displayDescription = computed(() => {
  return parsedInvoice.value?.description || ''
})

const effectiveAmount = computed(() => {
  // Use parsed invoice amount if available, otherwise use form input
  if (parsedInvoice.value && parsedInvoice.value.amount > 0) {
    return parsedInvoice.value.amount
  }
  return values.amount || 0
})

// Methods
const onSubmit = form.handleSubmit(async (formValues) => {
  try {
    // Use normalized destination (stripped of URI prefixes)
    const normalizedDestination = normalizePaymentRequest(formValues.destination)

    const success = await walletService.sendPayment({
      destination: normalizedDestination,
      amount: effectiveAmount.value, // Use computed effective amount
      comment: formValues.comment || undefined
    })
    
    if (success) {
      toastService?.success('Payment sent successfully!')
      closeDialog()
    }
  } catch (error) {
    console.error('Failed to send payment:', error)
  }
})

function closeDialog() {
  emit('update:open', false)
  resetForm()
  showScanner.value = false
}

// QR Scanner functions
function openScanner() {
  showScanner.value = true
}

function closeScanner() {
  showScanner.value = false
}

function handleScanResult(result: string) {
  // Clean up the scanned result by removing lightning: prefix if present
  let cleanedResult = result
  if (result.toLowerCase().startsWith('lightning:')) {
    cleanedResult = result.substring(10) // Remove "lightning:" prefix
  }

  // Set the cleaned result in the destination field
  setFieldValue('destination', cleanedResult)
  closeScanner()
  toastService?.success('QR code scanned successfully!')
}

// Determine destination type helper text
const destinationType = computed(() => {
  switch (paymentType.value) {
    case 'bolt11':
      if (parsedInvoice.value) {
        const amountText = parsedInvoice.value.amount > 0 ?
          ` (${parsedInvoice.value.amount.toLocaleString()} sats)` : ' (zero amount)'
        return `Lightning Invoice${amountText}`
      }
      return 'Lightning Invoice'
    case 'lightning-address':
      return 'Lightning Address'
    case 'lnurl':
      return 'LNURL'
    default:
      return ''
  }
})
</script>

<template>
  <Dialog :open="props.open" @update:open="emit('update:open', $event)">
    <DialogContent class="sm:max-w-md">
      <DialogHeader>
        <DialogTitle class="flex items-center gap-2">
          <Send class="h-5 w-5" />
          Send Bitcoin
        </DialogTitle>
        <DialogDescription>
          Send Bitcoin via Lightning Network
        </DialogDescription>
      </DialogHeader>

      <form @submit="onSubmit" class="space-y-4">
        <FormField v-slot="{ componentField }" name="destination">
          <FormItem>
            <div class="flex items-center justify-between">
              <FormLabel>Destination *</FormLabel>
              <Button
                type="button"
                variant="outline"
                size="sm"
                @click="openScanner"
                class="h-7 px-2 text-xs"
              >
                <ScanLine class="w-3 h-3 mr-1" />
                Scan QR
              </Button>
            </div>
            <FormControl>
              <Textarea
                placeholder="Lightning invoice, LNURL, or Lightning address (user@domain.com)"
                v-bind="componentField"
                class="min-h-[80px] font-mono text-xs"
              />
            </FormControl>
            <FormDescription v-if="destinationType">
              Detected: {{ destinationType }}
            </FormDescription>
            <FormMessage />
          </FormItem>
        </FormField>

        <!-- Parsed Invoice Display (BOLT11 with fixed amount) -->
        <div v-if="parsedInvoice && displayAmount" class="bg-muted/50 rounded-lg p-4 space-y-3">
          <div class="flex items-center justify-between">
            <h4 class="font-medium">Lightning Invoice</h4>
            <div class="text-lg font-bold text-green-600">
              {{ displayAmount.toLocaleString() }} sats
            </div>
          </div>
          <div v-if="displayDescription" class="text-sm text-muted-foreground">
            <strong>Description:</strong> {{ displayDescription }}
          </div>
        </div>

        <!-- Amount Input Field (conditional) -->
        <FormField v-if="showAmountField" v-slot="{ componentField }" name="amount">
          <FormItem>
            <FormLabel>Amount (sats) *</FormLabel>
            <FormControl>
              <Input
                type="number"
                min="1"
                placeholder="100"
                v-bind="componentField"
              />
            </FormControl>
            <FormDescription>
              <span v-if="paymentType === 'lightning-address'">Amount to send to Lightning address</span>
              <span v-else-if="paymentType === 'lnurl'">Amount to send via LNURL</span>
              <span v-else>Amount to send in satoshis</span>
            </FormDescription>
            <FormMessage />
          </FormItem>
        </FormField>

        <FormField v-slot="{ componentField }" name="comment">
          <FormItem>
            <FormLabel>Comment (Optional)</FormLabel>
            <FormControl>
              <Input
                placeholder="Optional message with payment"
                v-bind="componentField"
              />
            </FormControl>
            <FormDescription>Add a note to your payment (if supported)</FormDescription>
            <FormMessage />
          </FormItem>
        </FormField>

        <div v-if="error" class="flex items-start gap-2 p-3 bg-destructive/15 text-destructive rounded-lg">
          <AlertCircle class="h-4 w-4 mt-0.5" />
          <span class="text-sm">{{ error }}</span>
        </div>

        <div class="flex gap-2 pt-4">
          <Button
            type="submit"
            :disabled="!isFormValid || isSending"
            class="flex-1"
          >
            <Loader2 v-if="isSending" class="w-4 h-4 mr-2 animate-spin" />
            <Send v-else class="w-4 h-4 mr-2" />
            {{ isSending ? 'Sending...' : 'Send Payment' }}
          </Button>
          <Button type="button" variant="outline" @click="closeDialog" :disabled="isSending">
            Cancel
          </Button>
        </div>
      </form>
    </DialogContent>
  </Dialog>

  <!-- QR Scanner Dialog -->
  <Dialog :open="showScanner" @update:open="showScanner = $event">
    <DialogContent class="sm:max-w-lg">
      <DialogHeader>
        <DialogTitle class="flex items-center gap-2">
          <ScanLine class="h-5 w-5" />
          Scan QR Code
        </DialogTitle>
        <DialogDescription>
          Point your camera at a Lightning invoice QR code
        </DialogDescription>
      </DialogHeader>

      <QRScanner
        @result="handleScanResult"
        @close="closeScanner"
      />
    </DialogContent>
  </Dialog>
</template>