import { useState } from 'react';
import { Loader2, Plus, RefreshCw, TriangleAlert, Zap } from 'lucide-react';
import { Button } from '@/components/ui/button';
import { formatTimestamp, truncateMiddle } from './format';
import { INVOICE_TONES } from './format';
import { Amount } from './Amount';
import { CopyField } from './CopyField';
import { EmptyWallet, UnsupportedSection } from './EmptyWallet';
import { useSelectedWallet } from './useSelectedWallet';
import { errorMessage, useCapabilities, useInvoices, useReceiveAddress } from './useWalletData';
import { CreateInvoiceDialog } from './dialogs/CreateInvoiceDialog';

// Receiving. Works while locked — deriving an address needs the account xpub, not the seed, which is why
// this whole screen is usable in the wallet's resting state.
//
// The address is fetched with `?peek=true`: it returns the current unused address without advancing the
// derivation index. Rendering must never burn an address, so advancing is an explicit button.

export const ReceiveView = () => {
  const { walletId, isLoading } = useSelectedWallet();
  const { capabilities } = useCapabilities(walletId);
  const canOnchain = capabilities.includes('onchainReceive');
  const canLightning = capabilities.includes('lightningReceive');

  const {
    address,
    addressType,
    isLoading: addressLoading,
    error: addressError,
    next,
  } = useReceiveAddress(walletId, canOnchain);
  const { invoices } = useInvoices(walletId, canLightning, 10);
  const [invoiceOpen, setInvoiceOpen] = useState(false);

  if (!walletId) return <EmptyWallet isLoading={isLoading} />;
  if (!canOnchain && !canLightning) return <UnsupportedSection what="receiving" />;

  return (
    <div className="h-full overflow-y-auto p-4">
      {canOnchain && (
        <section className="max-w-2xl rounded-xl border border-border p-4">
          <div className="mb-3 flex items-center justify-between">
            <h3 className="text-[11px] font-semibold uppercase tracking-wide text-muted-foreground">
              On-chain address
            </h3>
            <button
              type="button"
              onClick={() => next.mutate()}
              disabled={next.isPending}
              className="flex items-center gap-1 text-[11px] text-primary hover:underline disabled:opacity-50"
            >
              <RefreshCw className={`h-3 w-3 ${next.isPending ? 'animate-spin' : ''}`} />
              new address
            </button>
          </div>

          {addressLoading && !address ? (
            <div className="flex items-center gap-2 text-sm text-muted-foreground">
              <Loader2 className="h-4 w-4 animate-spin" />
              Deriving an address…
            </div>
          ) : address ? (
            <>
              <CopyField value={address} wrap />
              <p className="mt-2 text-xs text-muted-foreground">
                {addressType ? `${addressType} · ` : ''}Reuse costs you privacy, not money — take a fresh one for each
                payer.
              </p>
            </>
          ) : addressError ? (
            // Deriving an address needs the chain source, so this fails whenever the Esplora endpoint is
            // down or rate-limiting. Showing "no address available" for that sent the last debugging
            // session looking at derivation code when the answer was a 429 in the response body.
            <div className="flex items-start gap-2 text-xs text-destructive">
              <TriangleAlert className="mt-0.5 h-3.5 w-3.5 shrink-0" />
              <div className="min-w-0">
                <p className="break-words">{errorMessage(addressError, 'Could not derive an address')}</p>
                <p className="mt-1 text-muted-foreground">
                  Addresses are derived locally, but the wallet checks the chain to find an unused one. Check{' '}
                  <span className="font-medium">Settings → Chain source</span>.
                </p>
              </div>
            </div>
          ) : (
            <p className="text-xs text-muted-foreground">No address available.</p>
          )}
        </section>
      )}

      {canLightning && (
        <section className="mt-4 max-w-2xl rounded-xl border border-border p-4">
          <div className="mb-3 flex items-center justify-between">
            <h3 className="text-[11px] font-semibold uppercase tracking-wide text-muted-foreground">
              Lightning invoices
            </h3>
            <Button size="sm" variant="outline" onClick={() => setInvoiceOpen(true)}>
              <Plus className="mr-1.5 h-3.5 w-3.5" />
              New invoice
            </Button>
          </div>

          {invoices.length === 0 ? (
            <p className="text-xs text-muted-foreground">No invoices yet.</p>
          ) : (
            <ul className="divide-y divide-border">
              {invoices.map((inv) => (
                <li key={inv.paymentHash} className="py-2">
                  <div className="flex items-center gap-2">
                    <Zap className="h-3.5 w-3.5 shrink-0 text-amber-500" />
                    <span className="min-w-0 flex-1 truncate text-xs">
                      {inv.memo || truncateMiddle(inv.paymentHash, 12, 8)}
                    </span>
                    <span
                      className={`shrink-0 rounded px-1.5 py-px text-[10px] font-medium ${INVOICE_TONES[inv.state]}`}
                    >
                      {inv.state}
                    </span>
                    {/* msat stays a string all the way to the DOM — see format.ts. */}
                    <Amount msat={inv.amountMsat} className="shrink-0 text-xs" />
                  </div>
                  <div className="mt-0.5 pl-5 text-[11px] text-muted-foreground">
                    created {formatTimestamp(inv.createdAt)}
                    {inv.settledAt ? ` · settled ${formatTimestamp(inv.settledAt)}` : ''}
                  </div>
                  {inv.state === 'open' && <CopyField className="mt-1.5 pl-5" value={inv.bolt11} wrap />}
                </li>
              ))}
            </ul>
          )}
        </section>
      )}

      {invoiceOpen && <CreateInvoiceDialog open={invoiceOpen} onOpenChange={setInvoiceOpen} walletId={walletId} />}
    </div>
  );
};
