import GroupedSatsInput from '@/components/GroupedSatsInput'
import QrCode from '@/components/QrCode'
import SatsAmountEquivalents from '@/components/SatsAmountEquivalents'
import { Button } from '@/components/ui/button'
import { Label } from '@/components/ui/label'
import { Skeleton } from '@/components/ui/skeleton'
import { Textarea } from '@/components/ui/textarea'
import { LIGHTNING_WALLET_PAY_ENABLED } from '@/constants'
import {
  clampZapSats,
  formatAmount,
  formatSatsGrouped,
  getAmountFromInvoice,
  LN_INVOICE_COFFEE_PRESET_SATS,
  LN_INVOICE_PRESET_SATS,
  MIN_ZAP_SATS,
} from '@/lib/lightning'
import { buildPaytoUri, formatPaytoTagValue } from '@/lib/payto'
import { superchatLightningAccentClass } from '@/lib/superchat-ui'
import { cn } from '@/lib/utils'
import { useZap } from '@/providers/ZapProvider'
import lightning from '@/services/lightning.service'
import { Check, Copy, Wallet, Zap } from 'lucide-react'
import { closeModal } from '@getalby/bitcoin-connect-react'
import { releaseBodyScrollLocks } from '@/lib/react-remove-scroll-body-cleanup'
import { useEffect, useMemo, useRef, useState } from 'react'
import { useTranslation } from 'react-i18next'
import { toast } from 'sonner'

function normalizeInvoiceZapSats(amount: number): number {
  const clamped = clampZapSats(amount)
  return clamped > 0 && clamped < MIN_ZAP_SATS ? MIN_ZAP_SATS : clamped
}

function invoiceQrPayload(pr: string): string {
  const trimmed = pr.trim()
  if (trimmed.toLowerCase().startsWith('lightning:')) return trimmed
  return `lightning:${trimmed}`
}

export default function LightningInvoiceSection({
  lightningAddress,
  paytoUri,
  onBolt11InvoiceChange,
  onPaymentFlowComplete
}: {
  lightningAddress: string
  paytoUri: string
  /** Fired when a BOLT11 invoice is created or cleared (for Phoenix / external wallet links). */
  onBolt11InvoiceChange?: (invoice: string | null) => void
  /** After a wallet payment succeeds (dialog stays open for the user to choose next steps). */
  onPaymentFlowComplete?: (details?: {
    amountMsat: number
    payto: string
    messageDraft?: string
  }) => void
}) {
  const { t } = useTranslation()
  const { defaultZapSats, isWalletConnected } = useZap()
  const [sats, setSats] = useState(() => normalizeInvoiceZapSats(defaultZapSats))
  const [description, setDescription] = useState('')
  const [commentMax, setCommentMax] = useState<number | null>(null)
  const [lnurlMetadataState, setLnurlMetadataState] = useState<'loading' | 'ready' | 'error'>(
    'loading'
  )
  const [invoice, setInvoice] = useState<string | null>(null)
  const [invoiceDescription, setInvoiceDescription] = useState<string | null>(null)
  const [creating, setCreating] = useState(false)
  const [paying, setPaying] = useState(false)
  const mountedRef = useRef(true)

  useEffect(() => {
    mountedRef.current = true
    return () => {
      mountedRef.current = false
      closeModal()
      releaseBodyScrollLocks()
    }
  }, [])

  useEffect(() => {
    setSats(normalizeInvoiceZapSats(defaultZapSats))
    setDescription('')
    setInvoice(null)
    setInvoiceDescription(null)
    setCommentMax(null)
    setLnurlMetadataState('loading')
    let cancelled = false
    void lightning.getLnurlPayInvoiceOptions(lightningAddress).then((opts) => {
      if (!cancelled && mountedRef.current) {
        if (opts) {
          setCommentMax(opts.commentAllowed)
          setLnurlMetadataState('ready')
        } else {
          setCommentMax(0)
          setLnurlMetadataState('error')
        }
      }
    })
    return () => {
      cancelled = true
    }
  }, [lightningAddress, defaultZapSats])

  useEffect(() => {
    setInvoice(null)
    setInvoiceDescription(null)
  }, [sats, description])

  useEffect(() => {
    onBolt11InvoiceChange?.(invoice)
  }, [invoice, onBolt11InvoiceChange])

  const invoiceSats = useMemo(() => {
    if (!invoice) return null
    try {
      return getAmountFromInvoice(invoice)
    } catch {
      return null
    }
  }, [invoice])

  const invoiceQrValue = useMemo(
    () => (invoice ? invoiceQrPayload(invoice) : ''),
    [invoice]
  )

  const handleCreateInvoice = async () => {
    try {
      setCreating(true)
      const trimmedDesc = description.trim()
      const pr = await lightning.createLnurlInvoice(lightningAddress, sats, {
        description: trimmedDesc || undefined
      })
      if (!mountedRef.current) return
      setInvoice(pr)
      setInvoiceDescription(trimmedDesc || null)
    } catch (error) {
      if (mountedRef.current) {
        toast.error(`${t('Failed to create invoice')}: ${(error as Error).message}`)
      }
    } finally {
      if (mountedRef.current) setCreating(false)
    }
  }

  const buildPaymentDetails = (pr: string) => {
    let amountMsat = clampZapSats(sats) * 1000
    try {
      amountMsat = getAmountFromInvoice(pr) * 1000
    } catch {
      /* use form amount */
    }
    return {
      amountMsat,
      payto: formatPaytoTagValue(buildPaytoUri('lightning', lightningAddress)),
      messageDraft: invoiceDescription?.trim() || description.trim() || undefined
    }
  }

  const handlePay = async () => {
    if (!invoice) return
    try {
      setPaying(true)
      const result = await lightning.payInvoice(invoice, undefined)
      if (!mountedRef.current) return
      if (result) {
        toast.success(t('Payment sent'))
        onPaymentFlowComplete?.(buildPaymentDetails(invoice))
        setInvoice(null)
        setInvoiceDescription(null)
      }
    } catch (error) {
      if (mountedRef.current) {
        toast.error(`${t('Lightning payment failed')}: ${(error as Error).message}`)
      }
    } finally {
      if (mountedRef.current) setPaying(false)
    }
  }

  const copyText = (text: string, message?: string) => {
    navigator.clipboard.writeText(text)
    toast.success(message ?? t('Copied to clipboard'))
  }

  return (
    <section
      className="min-w-0 space-y-5 rounded-xl border border-border/80 bg-muted/25 p-4 sm:p-5 text-base"
      aria-label={t('Lightning payment')}
    >
      <div className="min-w-0 rounded-lg bg-background/90 px-3 py-2.5 ring-1 ring-border/60">
        <p className="mb-1.5 text-xs font-medium uppercase tracking-wider text-muted-foreground">
          {t('Pay to')}
        </p>
        <p className="break-all text-base font-medium leading-snug sm:text-lg">{lightningAddress}</p>
      </div>
      <p className="text-sm leading-relaxed text-muted-foreground">
        {t(
          'Plain Lightning payments do not create NIP-57 zap receipts on Nostr. Use the zap button when available.'
        )}
      </p>

      <div className="min-w-0 space-y-3">
        <Label htmlFor="ln-invoice-sats" className="text-sm font-medium text-muted-foreground sm:text-base">
          {t('Amount (sats)')}
        </Label>
        <SatsAmountEquivalents sats={sats} id="ln-invoice-sats-equiv" />
        <div className="flex min-w-0 items-center gap-3">
          <GroupedSatsInput
            id="ln-invoice-sats"
            sats={sats}
            onSatsChange={setSats}
            className="min-w-0 flex-1"
            inputClassName="h-12 sm:h-14"
            aria-describedby="ln-invoice-sats-equiv ln-invoice-preset-hint"
          />
          <span className="shrink-0 text-base font-medium text-muted-foreground sm:text-lg">{t('sats')}</span>
        </div>
        <div
          id="ln-invoice-preset-hint"
          className="grid min-w-0 grid-cols-6 gap-1"
          role="group"
          aria-label={t('Amount (sats)')}
        >
          {LN_INVOICE_PRESET_SATS.map((preset) => {
            const active = sats === preset
            const isCoffeePreset = preset === LN_INVOICE_COFFEE_PRESET_SATS
            return (
              <Button
                key={preset}
                type="button"
                variant={active ? 'default' : 'outline'}
                size="sm"
                title={isCoffeePreset ? t('Buy them a coffee.') : undefined}
                className={cn(
                  'h-8 min-w-0 px-0.5 text-xs tabular-nums sm:h-9 sm:px-1 sm:text-sm',
                  isCoffeePreset && 'col-span-2 gap-1',
                  active && 'ring-1 ring-amber-600/45 dark:ring-yellow-400/50'
                )}
                onClick={() => setSats(preset)}
              >
                {formatAmount(preset)}
                {isCoffeePreset ? <span aria-hidden>☕</span> : null}
              </Button>
            )
          })}
        </div>
      </div>

      {lnurlMetadataState === 'loading' ? (
        <Skeleton className="h-[4.5rem] w-full rounded-lg" aria-hidden />
      ) : lnurlMetadataState === 'error' ? (
        <p className="rounded-lg border border-amber-500/40 bg-amber-500/10 px-3 py-2.5 text-sm leading-relaxed text-muted-foreground sm:text-base">
          {t(
            'Could not read this Lightning address (network or browser block). Descriptions need LNURL-pay support on the recipient side.'
          )}
        </p>
      ) : (commentMax ?? 0) > 0 ? (
        <div className="min-w-0 space-y-2">
          <div className="flex items-baseline justify-between gap-2">
            <Label htmlFor="ln-invoice-description" className="text-sm font-medium text-muted-foreground sm:text-base">
              {t('Description (optional)')}
            </Label>
            <span className="shrink-0 text-sm tabular-nums text-muted-foreground">
              {description.length}/{commentMax ?? 0}
            </span>
          </div>
          <Textarea
            id="ln-invoice-description"
            value={description}
            onChange={(e) =>
              setDescription(e.target.value.slice(0, commentMax ?? 0))
            }
            maxLength={commentMax ?? 0}
            rows={3}
            placeholder={t('Payment description')}
            className="min-h-[5rem] resize-none text-base leading-relaxed sm:text-lg"
          />
        </div>
      ) : (
        <p className="rounded-lg bg-muted/50 px-3 py-2.5 text-sm leading-relaxed text-muted-foreground sm:text-base">
          {t('This address does not support payment descriptions.')}
        </p>
      )}

      {!invoice ? (
        <Button
          type="button"
          className="h-12 w-full gap-2 text-base sm:h-14 sm:text-lg"
          disabled={creating || sats < MIN_ZAP_SATS}
          onClick={() => void handleCreateInvoice()}
        >
          {creating ? (
            <Skeleton className="size-5 shrink-0 rounded-full" aria-hidden />
          ) : (
            <Zap className={cn('size-5 shrink-0', superchatLightningAccentClass)} />
          )}
          {t('Create invoice')}
        </Button>
      ) : null}

      {invoice ? (
        <div
          className="min-w-0 space-y-3 rounded-lg border border-green-500/35 bg-green-500/[0.07] p-3 sm:p-4"
          role="status"
          aria-live="polite"
        >
          <div className="flex min-w-0 items-start gap-2">
            <div className="flex size-9 shrink-0 items-center justify-center rounded-full bg-green-500/20">
              <Check className="size-5 text-green-600 dark:text-green-400" aria-hidden />
            </div>
            <div className="min-w-0 flex-1">
              <p className="text-sm font-medium uppercase tracking-wide text-green-700 dark:text-green-400">
                {t('Invoice ready')}
              </p>
              {invoiceSats != null ? (
                <p className="mt-1 text-2xl font-bold tabular-nums tracking-tight sm:text-3xl">
                  {formatSatsGrouped(invoiceSats)}{' '}
                  <span className="text-base font-semibold text-muted-foreground sm:text-lg">{t('sats')}</span>
                </p>
              ) : null}
              {invoiceDescription ? (
                <p className="mt-2 text-base leading-snug text-foreground/90 break-words sm:text-lg">
                  {invoiceDescription}
                </p>
              ) : null}
            </div>
          </div>

          <div
            className="flex min-w-0 flex-col items-center gap-2"
            role="img"
            aria-label={t('Scan to pay with a Lightning wallet')}
          >
            <div className="w-full max-w-[min(100%,280px)]">
              <QrCode value={invoiceQrValue} fill />
            </div>
            <p className="text-center text-sm text-muted-foreground sm:text-base">
              {t('Scan to pay with a Lightning wallet')}
            </p>
          </div>

          <div className="min-w-0">
            <p className="mb-1.5 text-xs font-medium uppercase tracking-wider text-muted-foreground">
              {t('BOLT11 invoice')}
            </p>
            <div className="max-h-32 min-w-0 overflow-y-auto overflow-x-hidden rounded-md bg-background/80 p-3 ring-1 ring-border/50">
              <p className="select-text break-all font-mono text-sm leading-relaxed text-muted-foreground sm:text-base">
                {invoice}
              </p>
            </div>
          </div>

          <div className="grid min-w-0 grid-cols-1 gap-2 sm:grid-cols-2">
            <Button
              type="button"
              variant="secondary"
              className="h-11 w-full min-w-0 gap-2 text-base"
              onClick={() => copyText(invoice)}
            >
              <Copy className="size-5 shrink-0" />
              <span className="truncate">{t('Copy invoice')}</span>
            </Button>
            {LIGHTNING_WALLET_PAY_ENABLED ? (
              <Button
                type="button"
                variant="default"
                className="h-11 w-full min-w-0 gap-2 text-base"
                disabled={paying}
                onClick={() => void handlePay()}
              >
                {paying ? (
                  <Skeleton className="size-5 shrink-0 rounded-full" aria-hidden />
                ) : (
                  <Wallet className="size-5 shrink-0" />
                )}
                <span className="truncate">
                  {isWalletConnected ? t('Pay with connected wallet') : t('Open in wallet')}
                </span>
              </Button>
            ) : null}
          </div>

          <Button
            type="button"
            variant="ghost"
            className="h-10 w-full text-base text-muted-foreground"
            onClick={() => void handleCreateInvoice()}
            disabled={creating}
          >
            {t('Regenerate invoice')}
          </Button>
        </div>
      ) : null}

      <div className="grid min-w-0 grid-cols-1 gap-2 border-t border-border/60 pt-3 sm:grid-cols-2">
        <Button
          type="button"
          variant="outline"
          className="h-11 min-w-0 flex-1 gap-2 text-base"
          onClick={() => copyText(lightningAddress, t('Copied {{label}} address', { label: 'Lightning' }))}
        >
          <Copy className="size-5 shrink-0" />
          <span className="truncate">{t('Copy address')}</span>
        </Button>
        <Button
          type="button"
          variant="outline"
          className="h-11 min-w-0 flex-1 gap-2 text-base"
          onClick={() => copyText(paytoUri)}
        >
          <Copy className="size-5 shrink-0" />
          <span className="truncate">{t('Copy payto URI')}</span>
        </Button>
      </div>
    </section>
  )
}
