import { useState, useCallback } from 'react';
import {
  createMultisigWallet,
  getMultisigBalance,
  getMultisigUtxos,
  createMultisigPsbt,
  signMultisigPsbt,
  combinePsbt,
  finalizeMultisigPsbt,
  broadcastTx,
  type MultisigParticipant,
  type MultisigWallet,
} from './api';

function satToBtc(sats: number): string {
  return (sats / 100_000_000).toFixed(8);
}

function shortenAddr(addr: string): string {
  if (addr.length < 20) return addr;
  return addr.slice(0, 10) + '…' + addr.slice(-6);
}

function shortenHex(hex: string, start = 10, end = 8): string {
  if (hex.length < start + end) return hex;
  return hex.slice(0, start) + '…' + hex.slice(-end);
}

type MultisigFlow = 'create' | 'created' | 'psbt_create' | 'psbt_unsigned' | 'signing' | 'psbt_signed' | 'broadcasting' | 'broadcast_done' | 'error';

export default function MultisigCreation({ onBack }: { onBack: () => void }) {
  const [m, setM] = useState(2);
  const [n, setN] = useState(3);
  const [walletName, setWalletName] = useState('Multisig 1');
  const [password, setPassword] = useState('');
  const [confirmPassword, setConfirmPassword] = useState('');
  const [participants, setParticipants] = useState<MultisigParticipant[]>([]);
  const [wallet, setWallet] = useState<MultisigWallet | null>(null);
  const [flow, setFlow] = useState<MultisigFlow>('create');
  const [loading, setLoading] = useState(false);
  const [error, setError] = useState('');
  const [toast, setToast] = useState('');

  // PSBT state
  const [psbtHex, setPsbtHex] = useState('');
  const [rawTxHex, setRawTxHex] = useState('');
  const [broadcastTxid, setBroadcastTxid] = useState('');
  const [externalPsbt, setExternalPsbt] = useState('');
  const [walletPath, setWalletPath] = useState('');
  const [balance, setBalance] = useState<{ balance_btc: number; balance_sats: number } | null>(null);
  const [utxos, setUtxos] = useState<any[]>([]);
  const [signaturesCollected, setSignaturesCollected] = useState(0);
  const [txOutputAddr, setTxOutputAddr] = useState('');
  const [txOutputAmt, setTxOutputAmt] = useState('');
  const [txFeeRate, setTxFeeRate] = useState(10);

  const showToast = (msg: string) => {
    setToast(msg);
    setTimeout(() => setToast(''), 2000);
  };

  const addParticipant = () => {
    if (participants.length >= n) {
      setError(`Already have ${n} participants (matching n)`);
      return;
    }
    setParticipants([...participants, { name: '', local: false }]);
  };

  const updateParticipant = (idx: number, field: string, value: string | boolean) => {
    const updated = [...participants];
    updated[idx] = { ...updated[idx], [field]: value };
    setParticipants(updated);
  };

  const removeParticipant = (idx: number) => {
    setParticipants(participants.filter((_, i) => i !== idx));
  };

  const handleCreate = async () => {
    if (m < 1 || m > n) {
      setError('m must be between 1 and n');
      return;
    }
    if (participants.length !== n) {
      setError(`Need exactly ${n} participants to match n`);
      return;
    }
    if (password && password !== confirmPassword) {
      setError('Passwords do not match');
      return;
    }
    setLoading(true);
    setError('');
    try {
      const result = await createMultisigWallet(m, n, participants, walletName, password);
      setWallet(result.wallet);
      setBalance(result.balance);
      if (result.wallet.file_path) setWalletPath(result.wallet.file_path);
      setFlow('created');
    } catch (e: any) {
      setError(e.message || 'Failed to create multisig wallet');
    } finally {
      setLoading(false);
    }
  };

  const handleRefresh = async () => {
    if (!wallet) return;
    setLoading(true);
    try {
      const bal = await getMultisigBalance(wallet);
      setBalance(bal);
      const utxosResult = await getMultisigUtxos(wallet);
      setUtxos(utxosResult.utxos);
    } catch (e: any) {
      setError(e.message || 'Failed to refresh');
    } finally {
      setLoading(false);
    }
  };

  const handleCreatePsbt = async () => {
    if (!wallet) return;
    if (!txOutputAddr || !txOutputAmt) {
      setError('Fill in recipient and amount');
      return;
    }
    setLoading(true);
    setError('');
    try {
      const currentUtxos = utxos.length > 0 ? utxos : null;
      if (!currentUtxos) {
        const utxosResult = await getMultisigUtxos(wallet);
        setUtxos(utxosResult.utxos);
        const result = await createMultisigPsbt(wallet, [{ address: txOutputAddr, amount: parseFloat(txOutputAmt) }], txFeeRate, utxosResult.utxos);
        if (result.error) { setError(result.error); setFlow('error'); }
        else { setPsbtHex(result.psbt); setFlow('psbt_unsigned'); }
      } else {
        const result = await createMultisigPsbt(wallet, [{ address: txOutputAddr, amount: parseFloat(txOutputAmt) }], txFeeRate, currentUtxos);
        if (result.error) { setError(result.error); setFlow('error'); }
        else { setPsbtHex(result.psbt); setFlow('psbt_unsigned'); }
      }
    } catch (e: any) {
      setError(e.message || 'Failed to create PSBT');
      setFlow('error');
    } finally {
      setLoading(false);
    }
  };

  const handleSign = async () => {
    if (!wallet) return;
    setLoading(true);
    setError('');
    try {
      const result = await signMultisigPsbt(psbtHex, wallet, password);
      if (result.error) { setError(result.error); setFlow('error'); }
      else { setPsbtHex(result.psbt); setSignaturesCollected(result.signatures_added); setFlow('psbt_signed'); }
    } catch (e: any) {
      setError(e.message || 'Failed to sign PSBT');
      setFlow('error');
    } finally {
      setLoading(false);
    }
  };

  const handleCombine = async () => {
    setLoading(true);
    setError('');
    try {
      const lines = externalPsbt.split('\n').map(s => s.trim()).filter(s => s.length > 20);
      const myPsbt = psbtHex.trim();
      const allPsbt = [myPsbt, ...lines];
      const result = await combinePsbt(allPsbt);
      setPsbtHex(result.psbt);
      setSignaturesCollected(prev => prev + lines.length);
      setExternalPsbt('');
      showToast(`Combined ${lines.length} external PSBT(s)`);
    } catch (e: any) {
      setError(e.message || 'Failed to combine PSBTs');
      setFlow('error');
    } finally {
      setLoading(false);
    }
  };

  const handleFinalize = async () => {
    setLoading(true);
    setError('');
    try {
      const result = await finalizeMultisigPsbt(psbtHex);
      if (result.error) { setError(result.error); setFlow('error'); }
      else if (result.raw_tx_hex) { setRawTxHex(result.raw_tx_hex); setFlow('broadcasting'); }
      else { setError('Finalize did not produce a raw transaction'); setFlow('error'); }
    } catch (e: any) {
      setError(e.message || 'Failed to finalize PSBT');
      setFlow('error');
    } finally {
      setLoading(false);
    }
  };

  const handleBroadcast = async () => {
    setLoading(true);
    setError('');
    try {
      const result = await broadcastTx(rawTxHex);
      if (result.error) { setError(result.error); setFlow('error'); }
      else { setBroadcastTxid(result.txid); setFlow('broadcast_done'); }
    } catch (e: any) {
      setError(e.message || 'Broadcast failed');
      setFlow('error');
    } finally {
      setLoading(false);
    }
  };

  const handleReset = () => {
    setFlow('created');
    setPsbtHex('');
    setRawTxHex('');
    setBroadcastTxid('');
    setError('');
    setSignaturesCollected(0);
    setExternalPsbt('');
    setTxOutputAddr('');
    setTxOutputAmt('');
  };

  const copyToClipboard = (text: string, label: string) => {
    navigator.clipboard.writeText(text).then(() => showToast(`${label} copied!`));
  };

  const localCount = participants.filter(p => p.local).length;
  const remoteCount = participants.length - localCount;

  // ================= CREATION FORM =================
  if (flow === 'create') {
    return (
      <div className="multisig-container">
        {toast && <div className="toast-notification">{toast}</div>}
        <button className="btn-secondary" onClick={onBack}>← Back</button>
        <h2>Create Multisig Wallet</h2>
        <p className="subtitle">Set up an m-of-n P2WSH multisig wallet with descriptor-based address generation</p>

        {error && <div className="error-box">{error}</div>}

        <div className="multisig-form">
          <div className="form-row">
            <div className="form-group">
              <label>Threshold (m)</label>
              <input type="number" min={1} max={n} value={m} onChange={e => setM(parseInt(e.target.value) || 1)} className="input" />
            </div>
            <div className="form-group">
              <label>Participants (n)</label>
              <input type="number" min={2} max={8} value={n} onChange={e => setN(parseInt(e.target.value) || 2)} className="input" />
            </div>
          </div>

          <div className="multisig-quorum">
            <span className="badge badge-ok">{m}-of-{n}</span>
            <span className="mono">{m} signature{m > 1 ? 's' : ''} required to spend</span>
          </div>

          <label>Wallet Name</label>
          <input type="text" value={walletName} onChange={e => setWalletName(e.target.value)} className="input" />

          <label>Password (optional)</label>
          <input type="password" value={password} onChange={e => setPassword(e.target.value)} placeholder="Encrypt wallet" className="input" />

          {password && (
            <>
              <label>Confirm password</label>
              <input type="password" value={confirmPassword} onChange={e => setConfirmPassword(e.target.value)} className="input" />
            </>
          )}

          <div className="section-header">
            <h4>Participants ({participants.length}/{n})</h4>
            <button className="btn-small" onClick={addParticipant} disabled={participants.length >= n}>+ Add</button>
          </div>

          {participants.map((p, idx) => (
            <div key={idx} className="participant-row">
              <span className="mono">#{idx + 1}</span>
              <input type="text" value={p.name} onChange={e => updateParticipant(idx, 'name', e.target.value)} placeholder="Name" className="input" />
              <label className="checkbox-label">
                <input type="checkbox" checked={p.local} onChange={e => updateParticipant(idx, 'local', e.target.checked)} />
                Local (I have the seed)
              </label>
              {participants.length > 1 && (
                <button className="btn-icon" onClick={() => removeParticipant(idx)} title="Remove">✕</button>
              )}
            </div>
          ))}

          {participants.length > 0 && (
            <div className="participant-summary">
              {localCount > 0 && <span className="badge badge-ok">🔑 {localCount} local</span>}
              {remoteCount > 0 && <span className="badge badge-warn">🌐 {remoteCount} external</span>}
            </div>
          )}

          {participants.length < n && (
            <div className="warn-box">Add {n - participants.length} more participant{ n - participants.length > 1 ? 's' : ''} to match n={n}</div>
          )}

          <button className="btn-primary" onClick={handleCreate} disabled={loading || participants.length !== n}>
            {loading ? 'Creating…' : `Create ${m}-of-${n} Multisig`}
          </button>
        </div>
      </div>
    );
  }

  // ================= CREATED VIEW =================
  if (flow === 'created' && wallet) {
    return (
      <div className="multisig-container">
        {toast && <div className="toast-notification">{toast}</div>}
        <button className="btn-secondary" onClick={onBack}>← Back</button>
        <div className="created-header">
          <h2>✓ {wallet.name}</h2>
          <button className="btn-small" onClick={handleRefresh} disabled={loading}>{loading ? '⟳' : '↻ Refresh'}</button>
        </div>

        <div className="multisig-created">
          <div className="meta-row">
            <span className="meta-label">Threshold</span>
            <span className="multisig-quorum">
              <span className="badge badge-ok">{wallet.m}-of-{wallet.n}</span>
            </span>
          </div>

          <div className="meta-row">
            <span className="meta-label">Address</span>
            <div className="addr-copy">
              <span className="mono" title={wallet.address}>{shortenAddr(wallet.address)}</span>
              <button className="btn-icon" onClick={() => copyToClipboard(wallet.address, 'Address')} title="Copy">📋</button>
            </div>
          </div>

          <div className="meta-row">
            <span className="meta-label">Descriptor</span>
            <span className="mono" title={wallet.descriptor}>{shortenHex(wallet.descriptor, 16, 12)}</span>
          </div>

          {walletPath && (
            <div className="meta-row">
              <span className="meta-label">Saved</span>
              <span className="mono">{walletPath}</span>
            </div>
          )}

          <div className="balance-display">
            {balance ? (
              <span className="balance-value">{satToBtc(balance.balance_sats)} BTC</span>
            ) : (
              <span className="stat-placeholder">Loading balance…</span>
            )}
          </div>

          {utxos.length > 0 && (
            <div className="section">
              <h4>UTXOs ({utxos.length})</h4>
              <table className="utxo-table">
                <thead><tr><th>TxID</th><th>VOut</th><th>Amount</th><th>Confs</th></tr></thead>
                <tbody>
                  {utxos.map((u, i) => (
                    <tr key={i}>
                      <td className="mono" title={u.txid}>{shortenHex(u.txid, 8, 6)}</td>
                      <td className="mono">{u.vout}</td>
                      <td className="mono">{(u.amount ?? 0).toFixed(8)} BTC</td>
                      <td className="mono">{u.confirmations ?? 0}</td>
                    </tr>
                  ))}
                </tbody>
              </table>
            </div>
          )}

          {/* Participants */}
          <div className="section">
            <h4>Participants</h4>
            <div className="participant-list">
              {wallet.participants.map((p: any) => (
                <div key={p.index} className="participant-card">
                  <span className="mono">#{p.index + 1}</span>
                  <span>{p.name}</span>
                  <span className={`badge ${p.local ? 'badge-ok' : 'badge-warn'}`}>
                    {p.local ? '🔑 Local' : '🌐 External'}
                  </span>
                </div>
              ))}
            </div>
          </div>

          {/* Export wallet JSON */}
          <div className="psbt-output">
            <h4>Share with participants</h4>
            <div className="psbt-hex" onClick={() => copyToClipboard(JSON.stringify(wallet, null, 2), 'Wallet JSON')}>
              {JSON.stringify({ name: wallet.name, m: wallet.m, n: wallet.n, address: wallet.address, descriptor: wallet.descriptor, participants: wallet.participants.map(p => ({ index: p.index, name: p.name, xpub: p.xpub })) }, null, 2)}
            </div>
            <div className="psbt-actions">
              <button className="btn-small" onClick={() => copyToClipboard(JSON.stringify(wallet, null, 2), 'Wallet JSON')}>📋 Copy JSON</button>
              <button className="btn-small" onClick={() => {
                const blob = new Blob([JSON.stringify(wallet, null, 2)], { type: 'application/json' });
                const url = URL.createObjectURL(blob);
                const a = document.createElement('a');
                a.href = url;
                a.download = `${wallet.name.replace(/\s+/g, '_')}_multisig.json`;
                a.click();
                URL.revokeObjectURL(url);
                showToast('Wallet JSON downloaded');
              }}>💾 Download</button>
            </div>
          </div>
        </div>

        {/* Signature workflow */}
        <div className="section">
          <h3>Signature Workflow</h3>

          {flow === 'created' && (
            <div className="send-form">
              <h4>Create Transaction</h4>
              <label>Recipient Address</label>
              <input className="input" type="text" value={txOutputAddr} onChange={e => setTxOutputAddr(e.target.value)} placeholder="bc1q..." />
              <label>Amount (BTC)</label>
              <input className="input" type="number" step="0.00000001" min="0" value={txOutputAmt} onChange={e => setTxOutputAmt(e.target.value)} placeholder="0.00000000" />
              <label>Fee Rate: {txFeeRate} sats/vB</label>
              <input type="range" min="1" max="10000" step="1" value={txFeeRate} onChange={e => setTxFeeRate(parseInt(e.target.value))} className="fee-slider" />
              <button className="btn-primary" onClick={handleCreatePsbt} disabled={loading || !txOutputAddr || !txOutputAmt}>
                {loading ? 'Creating…' : 'Create PSBT'}
              </button>
            </div>
          )}

          {flow === 'psbt_unsigned' && (
            <div className="psbt-output">
              <h4>Unsigned PSBT — Sign locally, then share</h4>
              <div className="psbt-hex" onClick={() => copyToClipboard(psbtHex, 'PSBT hex')}>{shortenHex(psbtHex)}</div>
              <div className="psbt-actions">
                <button className="btn-small" onClick={() => copyToClipboard(psbtHex, 'PSBT hex')}>📋 Copy</button>
                <button className="btn-small" onClick={() => {
                  const blob = new Blob([psbtHex], { type: 'text/plain' });
                  const url = URL.createObjectURL(blob);
                  const a = document.createElement('a');
                  a.href = url;
                  a.download = `${wallet.name}_unsigned_psbt.txt`;
                  a.click();
                  URL.revokeObjectURL(url);
                  showToast('PSBT exported');
                }}>💾 Export</button>
              </div>
              <button className="btn-primary" onClick={handleSign} disabled={loading}>
                {loading ? 'Signing…' : '✍️ Sign My Inputs'}
              </button>
            </div>
          )}

          {(flow === 'signing' || flow === 'psbt_signed') && (
            <div className="psbt-output">
              {flow === 'signing' && <p className="mono">Signing…</p>}
              {flow === 'psbt_signed' && (
                <>
                  <h4>✓ Signed ({signaturesCollected} local signature{signaturesCollected > 1 ? 's' : ''})</h4>
                  <div className="psbt-hex" onClick={() => copyToClipboard(psbtHex, 'Signed PSBT')}>{shortenHex(psbtHex)}</div>
                  <div className="psbt-actions">
                    <button className="btn-small" onClick={() => copyToClipboard(psbtHex, 'Signed PSBT')}>📋 Copy Signed PSBT</button>
                  </div>
                  {signaturesCollected < wallet.m && (
                    <>
                      <textarea className="input" value={externalPsbt} onChange={e => setExternalPsbt(e.target.value)} placeholder="Paste PSBT from other signer (one per line)" rows={4} />
                      <button className="btn-secondary" onClick={handleCombine} disabled={loading || !externalPsbt.trim()}>
                        {loading ? 'Combining…' : '🔗 Combine PSBTs'}
                      </button>
                    </>
                  )}
                </>
              )}
            </div>
          )}

          {/* Progress bar */}
          {flow !== 'created' && flow !== 'create' && (
            <div className="sig-progress">
              <div className="sig-progress-bar">
                <div className="sig-progress-fill" style={{ width: `${Math.min((signaturesCollected / wallet.m) * 100, 100)}%` }}></div>
              </div>
              <span className="mono">{signaturesCollected}/{wallet.m} signatures</span>
              {signaturesCollected >= wallet.m && (
                <button className="btn-primary" onClick={handleFinalize} disabled={loading}>
                  {loading ? 'Finalizing…' : '⚡ Finalize & Prepare for Broadcast'}
                </button>
              )}
            </div>
          )}

          {flow === 'broadcasting' && (
            <div className="send-preview">
              <h4>Ready to Broadcast</h4>
              <div className="preview-row"><span>Raw TX</span><span className="mono">{shortenHex(rawTxHex)}</span></div>
              <button className="btn-primary btn-danger" onClick={handleBroadcast} disabled={loading}>
                {loading ? 'Broadcasting…' : '🚀 Broadcast'}
              </button>
            </div>
          )}

          {flow === 'broadcast_done' && (
            <div className="send-done">
              <div className="success-icon">✓</div>
              <h3>Broadcasted!</h3>
              <div className="tx-status">
                <div className="status-row"><span className="status-label">TXID</span><span className="mono" title={broadcastTxid}>{shortenHex(broadcastTxid, 10, 8)}</span></div>
              </div>
              <button className="btn-primary" onClick={handleReset}>Create Another</button>
            </div>
          )}

          {flow === 'error' && (
            <div className="send-error">
              <div className="error-icon">✕</div>
              <h3>Error</h3>
              <p className="mono">{error}</p>
              <button className="btn-primary" onClick={() => { setError(''); setFlow('created'); }}>Back</button>
            </div>
          )}
        </div>
      </div>
    );
  }

  return null;
}