import type { WalletSummary } from './shared';
import { useEffect, useRef, useState } from 'react';
import { useNavigate } from 'react-router';
import { Check, Eye, KeyRound, Pencil, Star, Trash2, X } from 'lucide-react';
import { Button } from '@/components/ui/button';
import { Input } from '@/components/ui/input';
import { KIND_LABELS, walletSectionPath } from './shared';
import { ChainSourceCard } from './ChainSourceCard';
import { CopyField } from './CopyField';
import { EmptyWallet } from './EmptyWallet';
import { LockBadge } from './LockBadge';
import { RescanCard } from './RescanCard';
import { useSelectedWallet } from './useSelectedWallet';
import { useLockCountdown } from './useLockCountdown';
import { useCapabilities, useWalletConfig, useWalletLifecycle } from './useWalletData';
import { ChangePassphraseDialog } from './dialogs/ChangePassphraseDialog';
import { ExportSeedDialog } from './dialogs/ExportSeedDialog';
import { DeleteWalletDialog } from './dialogs/DeleteWalletDialog';

// Wallet-level administration: what this wallet is, what its backend can do, and the three passphrase
// operations. Nothing here needs the wallet unlocked to *read* — each destructive action asks for the
// passphrase itself, because an open unlock window is not consent to change or destroy the key material.

export const WalletSettingsView = () => {
  const navigate = useNavigate();
  const { wallet, walletId, isLoading } = useSelectedWallet();
  const { config } = useWalletConfig();
  const { capabilities, kind } = useCapabilities(walletId);
  const { hasSeed } = useLockCountdown(walletId);
  const { activate, rename } = useWalletLifecycle();

  const [passphraseOpen, setPassphraseOpen] = useState(false);
  const [exportOpen, setExportOpen] = useState(false);
  const [deleteOpen, setDeleteOpen] = useState(false);

  if (!wallet || walletId == null) return <EmptyWallet isLoading={isLoading} />;

  const xpubs = Object.entries(wallet.xpubs ?? {});

  return (
    <div className="h-full space-y-4 overflow-y-auto p-4">
      <section className="max-w-2xl rounded-xl border border-border p-4">
        <div className="flex items-start justify-between gap-3">
          <div className="min-w-0">
            <WalletNameField
              wallet={wallet}
              onSave={(name) => rename.mutateAsync({ walletId, name })}
              isPending={rename.isPending}
            />
            <p className="mt-0.5 text-xs text-muted-foreground">
              {KIND_LABELS[wallet.kind]} · {wallet.network} · added {wallet.createdAt.slice(0, 10)}
            </p>
          </div>
          <LockBadge walletId={walletId} walletName={wallet.name} />
        </div>

        <dl className="mt-4 space-y-1.5 text-xs">
          <Row label="Backend">{kind ?? wallet.kind}</Row>
          <Row label="Default derivation">BIP{wallet.defaultBip}</Row>
          {wallet.fingerprint && (
            <Row label="Fingerprint">
              <code className="font-mono">{wallet.fingerprint}</code>
            </Row>
          )}
          <Row label="Active">{wallet.isActive ? 'yes' : 'no'}</Row>
          <Row label="Holds a seed">{hasSeed === true ? 'yes' : hasSeed === false ? 'no' : '—'}</Row>
        </dl>

        {!wallet.isActive && (
          <Button
            size="sm"
            variant="outline"
            className="mt-3"
            onClick={() => activate.mutate(wallet.id)}
            disabled={activate.isPending}
          >
            <Star className="mr-1.5 h-3.5 w-3.5" />
            Make this the active wallet
          </Button>
        )}
      </section>

      {xpubs.length > 0 && (
        <section className="max-w-2xl rounded-xl border border-border p-4">
          <h3 className="mb-2 text-[11px] font-semibold uppercase tracking-wide text-muted-foreground">Account keys</h3>
          <p className="mb-3 text-xs text-muted-foreground">
            Extended public keys. They can watch this wallet but never spend it — safe to hand to a block explorer or an
            accounting tool.
          </p>
          <div className="space-y-2">
            {xpubs.map(([path, xpub]) => (
              <CopyField key={path} value={xpub} label={path} wrap />
            ))}
          </div>
        </section>
      )}

      <section className="max-w-2xl rounded-xl border border-border p-4">
        <h3 className="mb-2 text-[11px] font-semibold uppercase tracking-wide text-muted-foreground">
          What this backend can do
        </h3>
        {capabilities.length === 0 ? (
          <p className="text-xs text-muted-foreground">No capabilities reported.</p>
        ) : (
          <div className="flex flex-wrap gap-1.5">
            {capabilities.map((cap) => (
              <span key={cap} className="rounded-md bg-muted px-1.5 py-0.5 font-mono text-[10px] text-muted-foreground">
                {cap}
              </span>
            ))}
          </div>
        )}
      </section>

      {hasSeed === true && (
        <section className="max-w-2xl rounded-xl border border-border p-4">
          <h3 className="mb-2 text-[11px] font-semibold uppercase tracking-wide text-muted-foreground">Key material</h3>
          <p className="mb-3 text-xs text-muted-foreground">
            Both of these ask for the passphrase on their own, whether or not the wallet is currently unlocked.
          </p>
          <div className="flex flex-wrap gap-2">
            <Button size="sm" variant="outline" onClick={() => setPassphraseOpen(true)}>
              <KeyRound className="mr-1.5 h-3.5 w-3.5" />
              Change passphrase
            </Button>
            <Button size="sm" variant="outline" onClick={() => setExportOpen(true)}>
              <Eye className="mr-1.5 h-3.5 w-3.5" />
              Show recovery phrase
            </Button>
          </div>
        </section>
      )}

      <ChainSourceCard />

      <RescanCard walletId={walletId} />

      {config && (
        <section className="max-w-2xl rounded-xl border border-border p-4">
          <h3 className="mb-2 text-[11px] font-semibold uppercase tracking-wide text-muted-foreground">Deployment</h3>
          <dl className="space-y-1.5 text-xs">
            <Row label="Network">{config.network}</Row>
            <Row label="Max unlock window">{formatMinutes(config.unlockTtlSec)}</Row>
            <Row label="Store key">
              {config.storeKeyConfigured ? 'configured' : <span className="text-destructive">missing</span>}
            </Row>
          </dl>
        </section>
      )}

      <section className="max-w-2xl rounded-xl border border-destructive/40 p-4">
        <h3 className="mb-2 text-[11px] font-semibold uppercase tracking-wide text-destructive">Danger</h3>
        <p className="mb-3 text-xs text-muted-foreground">
          {wallet.hasSeed
            ? 'Deleting erases the encrypted seed. Only your written recovery phrase can bring the coins back.'
            : 'Deleting removes the connection. The node itself is untouched.'}
        </p>
        <Button size="sm" variant="destructive" onClick={() => setDeleteOpen(true)}>
          <Trash2 className="mr-1.5 h-3.5 w-3.5" />
          Delete wallet
        </Button>
      </section>

      {passphraseOpen && (
        <ChangePassphraseDialog open={passphraseOpen} onOpenChange={setPassphraseOpen} walletId={walletId} />
      )}
      {exportOpen && <ExportSeedDialog open={exportOpen} onOpenChange={setExportOpen} walletId={walletId} />}
      {deleteOpen && (
        <DeleteWalletDialog
          open={deleteOpen}
          onOpenChange={setDeleteOpen}
          wallet={wallet}
          // The deleted id must not stay in `?wallet=` — drop back to the bare section, which means
          // "whatever is active now".
          onDeleted={() => navigate(walletSectionPath('overview'), { replace: true })}
        />
      )}
    </div>
  );
};

/** The wallet's name is the one field here that is purely a label — editing it in place, not in a dialog. */
const MAX_NAME = 64;

type WalletNameFieldProps = {
  wallet: WalletSummary;
  onSave: (name: string) => Promise<unknown>;
  isPending: boolean;
};

const WalletNameField = ({ wallet, onSave, isPending }: WalletNameFieldProps) => {
  const [editing, setEditing] = useState(false);
  const [draft, setDraft] = useState(wallet.name);
  const inputRef = useRef<HTMLInputElement>(null);

  // Switching wallets while the editor is open would otherwise rename the NEW wallet to the old one's draft.
  useEffect(() => {
    setEditing(false);
    setDraft(wallet.name);
  }, [wallet.id, wallet.name]);

  useEffect(() => {
    if (editing) inputRef.current?.select();
  }, [editing]);

  const trimmed = draft.trim();
  const dirty = trimmed !== wallet.name;

  const commit = async () => {
    if (!trimmed || !dirty) {
      setDraft(wallet.name);
      setEditing(false);
      return;
    }
    try {
      await onSave(trimmed);
      setEditing(false);
    } catch {
      // The mutation already toasted; keep the editor open so the typed name isn't lost.
    }
  };

  const cancel = () => {
    setDraft(wallet.name);
    setEditing(false);
  };

  if (!editing) {
    return (
      <div className="flex min-w-0 items-center gap-1.5">
        <h3 className="truncate text-sm font-semibold">{wallet.name}</h3>
        <button
          type="button"
          onClick={() => setEditing(true)}
          aria-label="Rename wallet"
          className="shrink-0 rounded-md p-1 text-muted-foreground hover:bg-muted hover:text-foreground"
        >
          <Pencil className="h-3 w-3" />
        </button>
      </div>
    );
  }

  return (
    <div className="flex min-w-0 items-center gap-1.5">
      <Input
        ref={inputRef}
        autoFocus
        value={draft}
        maxLength={MAX_NAME}
        disabled={isPending}
        onChange={(ev) => setDraft(ev.target.value)}
        onKeyDown={(ev) => {
          if (ev.key === 'Enter') void commit();
          if (ev.key === 'Escape') cancel();
        }}
        className="h-7 max-w-56 text-sm font-semibold"
        aria-label="Wallet name"
        autoComplete="off"
        spellCheck={false}
      />
      <Button size="icon" variant="ghost" className="h-7 w-7" onClick={commit} disabled={isPending || !trimmed}>
        <Check className="h-3.5 w-3.5" />
      </Button>
      <Button size="icon" variant="ghost" className="h-7 w-7" onClick={cancel} disabled={isPending}>
        <X className="h-3.5 w-3.5" />
      </Button>
    </div>
  );
};

const formatMinutes = (seconds: number) => (seconds >= 60 ? `${Math.round(seconds / 60)} min` : `${seconds}s`);

const Row = ({ label, children }: { label: string; children: React.ReactNode }) => (
  <div className="flex items-baseline justify-between gap-3">
    <dt className="shrink-0 text-muted-foreground">{label}</dt>
    <dd className="min-w-0 truncate text-right">{children}</dd>
  </div>
);
