import { useState, useEffect } from 'react'
import { useWallet } from '@lazorkit/wallet'
import { Connection, PublicKey } from '@solana/web3.js'

const TOKENS = [
  { symbol: 'SOL', mint: 'So11111111111111111111111111111111111111112', decimals: 9 },
  { symbol: 'USDC', mint: 'EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v', decimals: 6 },
  { symbol: 'USDT', mint: 'Es9vMFrzaCERmJfrF4H2FYD4KCoNkY11McCe8BenwNYB', decimals: 6 },
  { symbol: 'BONK', mint: 'DezXAZ8z7PnrnRJjz3wXBoRgixCa6xjnB7YaB1pPB263', decimals: 5 },
  { symbol: 'JUP', mint: 'JUPyiwrYJFskUPiHa7hkeR8VUtAeFoSYbKedZNsDvCN', decimals: 6 },
]

const SLIPPAGE_OPTIONS = [50, 100, 300]

const JUPITER_API = 'https://api.jup.ag/swap/v1'
const JUP_API_KEY = import.meta.env.VITE_JUPITER_API_KEY || ''

function useBalances(walletAddress: string | undefined) {
  const [balances, setBalances] = useState<Record<string, number>>({})
  useEffect(() => {
    if (!walletAddress) return
    const rpc = import.meta.env.VITE_SOLANA_RPC || 'https://api.devnet.solana.com'
    const conn = new Connection(rpc)
    const pk = new PublicKey(walletAddress)
    conn.getBalance(pk).then((bal) => setBalances((b) => ({ ...b, SOL: bal / 1e9 }))).catch(() => {})
    conn.getParsedTokenAccountsByOwner(pk, { programId: new PublicKey('TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA') })
      .then((res) => {
        const tokenBals: Record<string, number> = {}
        res.value.forEach((acc) => {
          const info = acc.account.data.parsed.info
          const token = TOKENS.find((t) => t.mint === info.mint)
          if (token) tokenBals[token.symbol] = info.tokenAmount.uiAmount || 0
        })
        setBalances((b) => ({ ...b, ...tokenBals }))
      }).catch(() => {})
  }, [walletAddress])
  return balances
}
<% if (styling !== 'tailwind') { %>
const styles: Record<string, React.CSSProperties> = {
  container: { width: '100%', maxWidth: 360, background: '#0a0a0a', borderRadius: 16, padding: 24, color: '#fafafa' },
  header: { display: 'flex', alignItems: 'center', justifyContent: 'space-between', marginBottom: 24 },
  title: { fontSize: 18, fontWeight: 600, margin: 0, color: '#fafafa' },
  address: { fontSize: 12, color: '#737373', background: 'none', border: 'none', cursor: 'pointer' },
  card: { border: '1px solid #262626', borderRadius: 12, padding: 16, background: '#171717' },
  label: { fontSize: 12, color: '#737373', marginBottom: 8, display: 'flex', justifyContent: 'space-between' },
  inputRow: { display: 'flex', alignItems: 'center', gap: 12 },
  input: { flex: 1, fontSize: 24, fontWeight: 500, border: 'none', background: 'transparent', width: '100%', color: '#fafafa' },
  arrow: { display: 'flex', justifyContent: 'center', margin: '8px 0' },
  arrowBox: { width: 32, height: 32, border: '1px solid #262626', borderRadius: 8, display: 'flex', alignItems: 'center', justifyContent: 'center', color: '#737373', background: '#171717' },
  button: { marginTop: 16, width: '100%', backgroundColor: '#fafafa', color: '#0a0a0a', padding: '14px 16px', borderRadius: 12, border: 'none', fontSize: 14, fontWeight: 500, cursor: 'pointer' },
  buttonDisabled: { opacity: 0.5, cursor: 'not-allowed' },
  buttonSecondary: { marginTop: 8, width: '100%', backgroundColor: 'transparent', color: '#fafafa', padding: '12px 16px', borderRadius: 12, border: '1px solid #262626', fontSize: 13, fontWeight: 500, cursor: 'pointer' },
  result: { marginTop: 12, fontSize: 14, textAlign: 'center' },
  footer: { marginTop: 16, fontSize: 12, color: '#737373', textAlign: 'center' },
  tokenBtn: { display: 'flex', alignItems: 'center', gap: 8, padding: '8px 12px', background: '#262626', borderRadius: 8, border: 'none', fontSize: 14, fontWeight: 500, cursor: 'pointer', color: '#fafafa' },
  dropdown: { position: 'absolute', right: 0, marginTop: 4, background: '#171717', border: '1px solid #262626', borderRadius: 8, boxShadow: '0 4px 12px rgba(0,0,0,0.3)', zIndex: 10 },
  dropdownItem: { display: 'block', width: '100%', padding: '8px 16px', textAlign: 'left', border: 'none', background: 'none', fontSize: 14, cursor: 'pointer', color: '#fafafa' },
  quote: { fontSize: 12, color: '#737373', marginTop: 4 },
}
<% } %>
export function Swap() {
  const { disconnect, wallet, smartWalletPubkey, signAndSendTransaction, signMessage } = useWallet()
  const balances = useBalances(wallet?.smartWallet)
  const [fromToken, setFromToken] = useState(TOKENS[0])
  const [toToken, setToToken] = useState(TOKENS[1])
  const [amount, setAmount] = useState('')
  const [slippage, setSlippage] = useState(SLIPPAGE_OPTIONS[0])
  const [quote, setQuote] = useState<any>(null)
  const [loading, setLoading] = useState(false)
  const [signing, setSigning] = useState(false)
  const [result, setResult] = useState<{ success: boolean; message: string } | null>(null)

  const switchTokens = () => { setFromToken(toToken); setToToken(fromToken); setAmount(''); setQuote(null) }

  useEffect(() => {
    if (!amount || parseFloat(amount) <= 0) { setQuote(null); return }
    const timeout = setTimeout(async () => {
      try {
        const inputAmount = Math.floor(parseFloat(amount) * 10 ** fromToken.decimals)
        const headers: Record<string, string> = {}
        if (JUP_API_KEY) headers['x-api-key'] = JUP_API_KEY
        const res = await fetch(`${JUPITER_API}/quote?inputMint=${fromToken.mint}&outputMint=${toToken.mint}&amount=${inputAmount}&slippageBps=${slippage}&restrictIntermediateTokens=true`, { headers })
        const data = await res.json()
        if (data.outAmount) setQuote(data)
        else setQuote(null)
      } catch (e) { console.error('Quote error:', e); setQuote(null) }
    }, 500)
    return () => clearTimeout(timeout)
  }, [amount, fromToken, toToken, slippage])

  const outputAmount = quote ? (parseInt(quote.outAmount) / 10 ** toToken.decimals).toFixed(toToken.decimals === 6 ? 2 : 4) : '0.00'

  const handleSwap = async () => {
    if (!smartWalletPubkey || !quote) return
    setLoading(true); setResult(null)
    try {
      const headers: Record<string, string> = { 'Content-Type': 'application/json' }
      if (JUP_API_KEY) headers['x-api-key'] = JUP_API_KEY
      const swapRes = await fetch(`${JUPITER_API}/swap-instructions`, {
        method: 'POST', headers,
        body: JSON.stringify({ quoteResponse: quote, userPublicKey: smartWalletPubkey.toBase58(), wrapAndUnwrapSol: true, dynamicComputeUnitLimit: true }),
      })
      if (!swapRes.ok) throw new Error(`Jupiter API error: ${await swapRes.text()}`)
      const { setupInstructions = [], swapInstruction, cleanupInstruction, addressLookupTableAddresses = [] } = await swapRes.json()
      if (!swapInstruction) throw new Error('No swap instruction returned')

      const toInstruction = (ix: any) => ({
        programId: new PublicKey(ix.programId),
        keys: ix.accounts.map((acc: any) => ({ pubkey: new PublicKey(acc.pubkey), isSigner: acc.isSigner, isWritable: acc.isWritable })),
        data: Buffer.from(ix.data, 'base64'),
      })
      const instructions = [...setupInstructions.map(toInstruction), toInstruction(swapInstruction), ...(cleanupInstruction ? [toInstruction(cleanupInstruction)] : [])]

      let addressLookupTableAccounts: any[] = []
      if (addressLookupTableAddresses.length > 0) {
        const rpc = import.meta.env.VITE_SOLANA_RPC || 'https://api.devnet.solana.com'
        const conn = new Connection(rpc)
        const alts = await Promise.all(addressLookupTableAddresses.map(async (addr: string) => (await conn.getAddressLookupTable(new PublicKey(addr))).value))
        addressLookupTableAccounts = alts.filter(Boolean)
      }

      const signature = await signAndSendTransaction({ instructions, transactionOptions: { feeToken: 'USDC', addressLookupTableAccounts } })
      setResult({ success: true, message: `Swapped! ${signature.slice(0, 8)}...` })
      setAmount(''); setQuote(null)
    } catch (e) { console.error('Swap error:', e); setResult({ success: false, message: e instanceof Error ? e.message : 'Swap failed' }) }
    finally { setLoading(false) }
  }

  const handleSignMessage = async () => {
    setSigning(true); setResult(null)
    try {
      const message = `Verify wallet ownership\nTimestamp: ${Date.now()}`
      const { signature } = await signMessage(message)
      setResult({ success: true, message: `Signed: ${signature.slice(0, 16)}...` })
    } catch (e) { console.error('Sign error:', e); setResult({ success: false, message: e instanceof Error ? e.message : 'Sign failed' }) }
    finally { setSigning(false) }
  }

  const addr = wallet?.smartWallet || ''

  return (
<% if (styling === 'tailwind') { %>
    <div className="w-full max-w-sm bg-neutral-900 rounded-2xl p-6 text-white">
      <div className="flex items-center justify-between mb-6"><h1 className="text-lg font-semibold">Swap</h1><button onClick={() => disconnect()} className="text-xs text-neutral-500 hover:text-neutral-300">{addr.slice(0, 6)}...{addr.slice(-4)}</button></div>
      <div className="space-y-2">
        <div className="border border-neutral-700 rounded-xl p-4 bg-neutral-800">
          <div className="flex items-center justify-between mb-2"><span className="text-xs text-neutral-500">From</span><span className="text-xs text-neutral-500">Balance: {(balances[fromToken.symbol] ?? 0).toFixed(4)}</span></div>
          <div className="flex items-center gap-3"><input type="number" placeholder="0.00" value={amount} onChange={(e) => setAmount(e.target.value)} className="flex-1 text-2xl font-medium bg-transparent w-full focus:outline-none text-white placeholder-neutral-600" /><TokenSelect token={fromToken} tokens={TOKENS} onChange={setFromToken} exclude={toToken.symbol} /></div>
          <button onClick={() => setAmount(String(balances[fromToken.symbol] ?? 0))} className="text-xs text-neutral-500 hover:text-white mt-1">Max</button>
        </div>
        <div className="flex justify-center"><button onClick={switchTokens} className="w-8 h-8 border border-neutral-700 rounded-lg flex items-center justify-center text-neutral-500 hover:bg-neutral-800 bg-neutral-800">↓</button></div>
        <div className="border border-neutral-700 rounded-xl p-4 bg-neutral-800">
          <div className="flex items-center justify-between mb-2"><span className="text-xs text-neutral-500">To</span><span className="text-xs text-neutral-500">Balance: {(balances[toToken.symbol] ?? 0).toFixed(4)}</span></div>
          <div className="flex items-center gap-3"><span className="flex-1 text-2xl font-medium text-neutral-500">{outputAmount}</span><TokenSelect token={toToken} tokens={TOKENS} onChange={setToToken} exclude={fromToken.symbol} /></div>
          {quote && <p className="text-xs text-neutral-500 mt-2">via Jupiter · {quote.routePlan?.[0]?.swapInfo?.label || 'Best route'}</p>}
        </div>
      </div>
      <div className="flex items-center justify-between mt-3 text-xs"><span className="text-neutral-500">Slippage</span><div className="flex gap-1">{SLIPPAGE_OPTIONS.map((s) => (<button key={s} onClick={() => setSlippage(s)} className={`px-2 py-1 rounded ${slippage === s ? 'bg-white text-black' : 'bg-neutral-700 text-neutral-300 hover:bg-neutral-600'}`}>{s / 100}%</button>))}</div></div>
      <button onClick={handleSwap} disabled={loading || !quote} className="mt-4 w-full py-3 bg-white text-black text-sm font-medium rounded-xl hover:opacity-90 disabled:opacity-50">{loading ? 'Swapping...' : 'Swap'}</button>
      <button onClick={handleSignMessage} disabled={signing} className="mt-2 w-full py-3 bg-transparent text-white text-sm font-medium rounded-xl border border-neutral-700 hover:bg-neutral-800 disabled:opacity-50">{signing ? 'Signing...' : 'Sign Message'}</button>
      {result && <p className={`mt-3 text-sm text-center ${result.success ? 'text-neutral-400' : 'text-red-400'}`}>{result.message}</p>}
      <p className="mt-4 text-xs text-center text-neutral-500">Gas sponsored · Powered by LazorKit + Jupiter</p>
    </div>
<% } else { %>
    <div style={styles.container}>
      <div style={styles.header}><h1 style={styles.title}>Swap</h1><button onClick={() => disconnect()} style={styles.address}>{addr.slice(0, 6)}...{addr.slice(-4)}</button></div>
      <div style={styles.card}>
        <div style={styles.label}><span>From</span><span>Balance: {(balances[fromToken.symbol] ?? 0).toFixed(4)}</span></div>
        <div style={styles.inputRow}><input type="number" placeholder="0.00" value={amount} onChange={(e) => setAmount(e.target.value)} style={styles.input} /><TokenSelect token={fromToken} tokens={TOKENS} onChange={setFromToken} exclude={toToken.symbol} /></div>
        <button onClick={() => setAmount(String(balances[fromToken.symbol] ?? 0))} style={{ ...styles.address, fontSize: 12, marginTop: 4 }}>Max</button>
      </div>
      <div style={styles.arrow}><button onClick={switchTokens} style={{ ...styles.arrowBox, cursor: 'pointer' }}>↓</button></div>
      <div style={styles.card}>
        <div style={styles.label}><span>To</span><span>Balance: {(balances[toToken.symbol] ?? 0).toFixed(4)}</span></div>
        <div style={styles.inputRow}><span style={{ ...styles.input, color: '#737373' }}>{outputAmount}</span><TokenSelect token={toToken} tokens={TOKENS} onChange={setToToken} exclude={fromToken.symbol} /></div>
        {quote && <p style={styles.quote}>via Jupiter · {quote.routePlan?.[0]?.swapInfo?.label || 'Best route'}</p>}
      </div>
      <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', marginTop: 12, fontSize: 12 }}><span style={{ color: '#737373' }}>Slippage</span><div style={{ display: 'flex', gap: 4 }}>{SLIPPAGE_OPTIONS.map((s) => (<button key={s} onClick={() => setSlippage(s)} style={{ padding: '4px 8px', borderRadius: 4, border: 'none', cursor: 'pointer', background: slippage === s ? '#fafafa' : '#262626', color: slippage === s ? '#0a0a0a' : '#a3a3a3' }}>{s / 100}%</button>))}</div></div>
      <button onClick={handleSwap} disabled={loading || !quote} style={{ ...styles.button, ...(loading || !quote ? styles.buttonDisabled : {}) }}>{loading ? 'Swapping...' : 'Swap'}</button>
      <button onClick={handleSignMessage} disabled={signing} style={{ ...styles.buttonSecondary, ...(signing ? styles.buttonDisabled : {}) }}>{signing ? 'Signing...' : 'Sign Message'}</button>
      {result && <p style={{ ...styles.result, color: result.success ? '#737373' : '#ef4444' }}>{result.message}</p>}
      <p style={styles.footer}>Gas sponsored · Powered by LazorKit + Jupiter</p>
    </div>
<% } %>
  )
}

function TokenSelect({ token, tokens, onChange, exclude }: { token: typeof TOKENS[0]; tokens: typeof TOKENS; onChange: (t: typeof TOKENS[0]) => void; exclude: string }) {
  const [open, setOpen] = useState(false)
  return (
    <div style={{ position: 'relative' }}>
<% if (styling === 'tailwind') { %>
      <button onClick={() => setOpen(!open)} className="flex items-center gap-2 px-3 py-2 bg-neutral-700 rounded-lg text-sm font-medium text-white">{token.symbol}<span className="text-neutral-400">▼</span></button>
      {open && (<div className="absolute right-0 mt-1 bg-neutral-800 border border-neutral-700 rounded-lg shadow-lg z-10">{tokens.filter((t) => t.symbol !== exclude).map((t) => (<button key={t.symbol} onClick={() => { onChange(t); setOpen(false) }} className="block w-full px-4 py-2 text-left text-sm text-white hover:bg-neutral-700">{t.symbol}</button>))}</div>)}
<% } else { %>
      <button onClick={() => setOpen(!open)} style={styles.tokenBtn}>{token.symbol} <span style={{ color: '#a3a3a3' }}>▼</span></button>
      {open && (<div style={styles.dropdown as React.CSSProperties}>{tokens.filter((t) => t.symbol !== exclude).map((t) => (<button key={t.symbol} onClick={() => { onChange(t); setOpen(false) }} style={styles.dropdownItem}>{t.symbol}</button>))}</div>)}
<% } %>
    </div>
  )
}
