const BACKEND = (window.location.protocol === 'file:' || window.location.hostname === 'localhost' || window.location.hostname === '127.0.0.1')
  ? 'http://localhost:3001'
  : '';

const TYPE_LABELS = { cripto: 'Cripto', accion: 'Acción', etf: 'ETF' };
const TYPE_COLORS = {
  cripto: { bg: '#f7931a',       color: '#ffffff' },
  accion: { bg: 'var(--purple)', color: '#ffffff' },
  etf:    { bg: 'var(--green)',  color: '#ffffff' },
};

function TypeBadge({ type }) {
  const s = TYPE_COLORS[type] ?? TYPE_COLORS.accion;
  return (
    <span style={{
      fontSize: 10, fontWeight: 700, padding: '2px 7px', borderRadius: 5,
      background: s.bg, color: s.color, letterSpacing: 0.4, whiteSpace: 'nowrap',
    }}>
      {TYPE_LABELS[type] ?? type}
    </span>
  );
}

function AddAssetModal({ open, editing, cedearMap, onClose, onSave }) {
  const { useState, useEffect, useRef } = React;
  const isEdit = !!editing;

  const emptyForm = () => ({
    ticker: '', name: '', type: 'cripto',
    qty: '', buyPrice: '',
    buyDate: new Date().toISOString().slice(0, 10),
  });

  const [form, setForm] = useState(emptyForm);
  const [errors, setErrors] = useState({});

  // Search state
  const [query, setQuery] = useState('');
  const [results, setResults] = useState([]);
  const [searching, setSearching] = useState(false);
  const [showDropdown, setShowDropdown] = useState(false);

  // Live price state
  const [livePrice, setLivePrice] = useState(null);
  const [fetchingPrice, setFetchingPrice] = useState(false);

  // Moneda del precio de compra (USD por defecto). En ARS la tasa depende del activo:
  // cripto→Dólar Cripto, todo lo demás (acciones, ETFs, CEDEARs)→CCL.
  // No usamos MEP: la app trackea activos foráneos (Yahoo, CoinGecko) que requieren
  // sacar la plata del país, lo cual implica CCL por definición.
  const [priceCurrency, setPriceCurrency] = useState('USD');
  const [ccl, setCcl] = useState(null);
  const [cclLoading, setCclLoading] = useState(false);
  const [cripto, setCripto] = useState(null);
  const [criptoLoading, setCriptoLoading] = useState(false);

  // Monto total invertido (opcional). Si está, calcula qty = monto/precio.
  const [amount, setAmount] = useState('');
  const [amountCurrency, setAmountCurrency] = useState('USD');

  const searchTimer = useRef(null);
  const priceTimer = useRef(null);
  const wrapperRef = useRef(null);

  // Reset on open/close
  useEffect(() => {
    if (editing) {
      setForm({
        ticker: editing.ticker,
        name: editing.name,
        type: editing.type,
        qty: String(editing.qty),
        buyPrice: String(editing.buyPrice),
        // El input type="date" solo acepta YYYY-MM-DD. Si viene un ISO completo, recortamos.
        buyDate: (editing.buyDate || new Date().toISOString()).slice(0, 10),
      });
      setQuery(editing.ticker);
      setLivePrice({ currentPrice: editing.currentPrice, change24: editing.change24 });
    } else {
      setForm(emptyForm());
      setQuery('');
      setLivePrice(null);
    }
    setPriceCurrency('USD');
    setAmount('');
    setAmountCurrency('USD');
    setResults([]);
    setErrors({});
    setShowDropdown(false);
  }, [editing, open]);

  // Tasa de conversión ARS↔USD: cripto → Dólar Cripto, cualquier otra cosa → CCL.
  // El flag isCedear se conserva como dato informativo / por si en el futuro
  // queremos diferenciar el label, pero hoy CEDEARs y stocks foráneos comparten CCL.
  const isCrypto = form.type === 'cripto';
  const fxKind = isCrypto ? 'cripto' : 'ccl';

  // Fetch de la cotización correspondiente cuando algún toggle está en ARS.
  useEffect(() => {
    if (priceCurrency !== 'ARS' && amountCurrency !== 'ARS') return;
    if (fxKind === 'cripto') {
      if (cripto) return;
      setCriptoLoading(true);
      fetch(`${BACKEND}/api/dolar-cripto`)
        .then(r => r.ok ? r.json() : Promise.reject())
        .then(setCripto)
        .catch(() => setCripto(null))
        .finally(() => setCriptoLoading(false));
    } else {
      if (ccl) return;
      setCclLoading(true);
      fetch(`${BACKEND}/api/ccl`)
        .then(r => r.ok ? r.json() : Promise.reject())
        .then(setCcl)
        .catch(() => setCcl(null))
        .finally(() => setCclLoading(false));
    }
  }, [priceCurrency, amountCurrency, fxKind]);

  const fxRate    = fxKind === 'cripto' ? cripto        : ccl;
  const fxLabel   = fxKind === 'cripto' ? 'Dólar Cripto' : 'CCL';
  const fxLoading = fxKind === 'cripto' ? criptoLoading  : cclLoading;

  // Close dropdown on outside click
  useEffect(() => {
    const handler = (e) => {
      if (wrapperRef.current && !wrapperRef.current.contains(e.target)) {
        setShowDropdown(false);
      }
    };
    document.addEventListener('mousedown', handler);
    return () => document.removeEventListener('mousedown', handler);
  }, []);

  // Debounced search
  useEffect(() => {
    clearTimeout(searchTimer.current);
    if (!query || query.length < 1 || (form.ticker && query === form.ticker)) {
      setResults([]);
      setShowDropdown(false);
      return;
    }
    setSearching(true);
    searchTimer.current = setTimeout(async () => {
      try {
        const res = await fetch(`${BACKEND}/api/search?q=${encodeURIComponent(query)}`);
        const data = await res.json();
        setResults(data);
        setShowDropdown(data.length > 0);
      } catch {
        setResults([]);
      } finally {
        setSearching(false);
      }
    }, 320);
    return () => clearTimeout(searchTimer.current);
  }, [query]);

  // Fetch live price when ticker is set. Pasamos `types=TICKER:tipo` como hint
  // para que el backend sepa rutar criptos fuera del map directo a Binance.
  useEffect(() => {
    clearTimeout(priceTimer.current);
    if (!form.ticker) { setLivePrice(null); return; }
    setFetchingPrice(true);
    priceTimer.current = setTimeout(async () => {
      try {
        const url = `${BACKEND}/api/prices?tickers=${form.ticker}&types=${form.ticker}:${form.type}`;
        const res = await fetch(url);
        const data = await res.json();
        if (data[form.ticker]) setLivePrice(data[form.ticker]);
        else setLivePrice(null);
      } catch {
        setLivePrice(null);
      } finally {
        setFetchingPrice(false);
      }
    }, 200);
    return () => clearTimeout(priceTimer.current);
  }, [form.ticker, form.type]);

  // Conversiones de moneda. Si el usuario eligió ARS, dividir por la tasa correspondiente
  // (CCL para CEDEARs, MEP para el resto). La DB siempre persiste USD.
  const buyPriceUsd = priceCurrency === 'USD'
    ? +form.buyPrice
    : (fxRate?.venta && +form.buyPrice ? +form.buyPrice / fxRate.venta : null);

  const amountUsd = amount && +amount > 0
    ? (amountCurrency === 'USD' ? +amount : (fxRate?.venta ? +amount / fxRate.venta : null))
    : null;

  // Sincronizar: cuando hay monto y precio, auto-calcular qty.
  // IMPORTANTE: este hook va antes del early return para no violar las reglas de hooks.
  useEffect(() => {
    if (!amountUsd || !buyPriceUsd || buyPriceUsd <= 0) return;
    const newQty = +(amountUsd / buyPriceUsd).toFixed(8);
    setForm(f => f.qty === String(newQty) ? f : ({ ...f, qty: String(newQty) }));
  }, [amountUsd, buyPriceUsd]);

  if (!open) return null;

  const set = (k, v) => setForm(f => ({ ...f, [k]: v }));

  const handleSelect = (result) => {
    setForm(f => ({ ...f, ticker: result.ticker, name: result.name, type: result.type }));
    setQuery(result.ticker);
    setShowDropdown(false);
    setResults([]);
  };

  const handleQueryChange = (val) => {
    setQuery(val);
    // Clear ticker if user edits away from the selected value
    if (form.ticker && val !== form.ticker) {
      setForm(f => ({ ...f, ticker: '', name: '', type: 'cripto' }));
      setLivePrice(null);
    }
  };

  // Redondea a la cantidad de decimales adecuada según la magnitud del precio.
  // Necesario porque las APIs de cripto devuelven precisión completa (ej. BTC
  // a 12 decimales), que vista en el input queda como ruido.
  const roundForInput = (n) => {
    const abs = Math.abs(n);
    if (abs >= 1) return +n.toFixed(2);
    if (abs >= 0.01) return +n.toFixed(4);
    if (abs >= 0.0001) return +n.toFixed(6);
    return +n.toFixed(8);
  };

  const fillBuyPrice = () => {
    if (!livePrice?.currentPrice) return;
    if (priceCurrency === 'USD') {
      set('buyPrice', String(roundForInput(livePrice.currentPrice)));
    } else if (fxRate?.venta) {
      // Convertir USD → ARS para mostrar el equivalente en pesos (CCL/Dólar Cripto)
      set('buyPrice', String(roundForInput(livePrice.currentPrice * fxRate.venta)));
    }
  };

  const validate = () => {
    const e = {};
    if (!form.ticker.trim()) e.ticker = 'Seleccioná un ticker';
    if (!form.qty || +form.qty <= 0) e.qty = 'Debe ser > 0';
    if (!form.buyPrice || +form.buyPrice <= 0) e.buyPrice = 'Debe ser > 0';
    if (priceCurrency === 'ARS' && !fxRate?.venta) e.buyPrice = `No se pudo cargar el ${fxLabel}`;
    setErrors(e);
    return Object.keys(e).length === 0;
  };

  const submit = (e) => {
    e.preventDefault();
    if (!validate()) return;

    // Si la fecha elegida es hoy, guardamos timestamp preciso para que el gráfico distinga
    // múltiples compras del mismo día como eventos separados (step ups).
    // Si es una fecha pasada (back-date), usamos mediodía UTC de ese día.
    const todayStr = new Date().toISOString().slice(0, 10);
    const buyDateStored = isEdit && editing.buyDate
      ? editing.buyDate
      : (form.buyDate === todayStr
          ? new Date().toISOString()
          : `${form.buyDate}T12:00:00.000Z`);

    onSave({
      ...editing,
      ticker: form.ticker.toUpperCase().trim(),
      name: form.name.trim(),
      type: form.type,
      qty: +form.qty,
      buyPrice: +buyPriceUsd.toFixed(8),
      buyDate: buyDateStored,
      currentPrice: livePrice?.currentPrice ?? buyPriceUsd,
      change24: livePrice?.change24 ?? 0,
      // iconUrl viene del fetch live (CryptoCompare para cripto). Para acciones/ETFs
      // queda undefined y se cae al fallback del TickerBadge (círculo con iniciales).
      iconUrl: livePrice?.iconUrl ?? editing?.iconUrl,
      id: isEdit ? editing.id : `a${Date.now()}`,
    });
  };

  const pnl = form.qty && buyPriceUsd && livePrice
    ? (livePrice.currentPrice - buyPriceUsd) * +form.qty
    : null;

  return (
    <div
      onClick={onClose}
      style={{
        position: 'fixed', inset: 0, background: 'rgba(0,0,0,0.6)',
        display: 'grid', placeItems: 'center', zIndex: 50,
      }}>
      <form
        ref={wrapperRef}
        onClick={e => e.stopPropagation()}
        onSubmit={submit}
        style={{
          width: 'calc(100% - 28px)', maxWidth: 480,
          maxHeight: 'calc(100vh - 28px)', overflowY: 'auto',
          background: 'var(--panel)', border: '1px solid var(--border)', borderRadius: 18,
          padding: '24px 24px 20px', boxShadow: '0 28px 70px rgba(0,0,0,0.55)',
          boxSizing: 'border-box',
        }}>

        {/* Header */}
        <div style={{ display: 'flex', alignItems: 'center', marginBottom: 20 }}>
          <h2 style={{ margin: 0, fontSize: 17, fontWeight: 700, letterSpacing: -0.3 }}>
            {isEdit ? 'Editar posición' : 'Agregar posición'}
          </h2>
          <button type="button" onClick={onClose}
            style={{ marginLeft: 'auto', width: 30, height: 30, borderRadius: 8, color: 'var(--text-dim)' }}>
            <svg width="13" height="13" viewBox="0 0 14 14" fill="none" style={{ display: 'block', margin: 'auto' }}>
              <path d="M2 2l10 10M12 2L2 12" stroke="currentColor" strokeWidth="1.7" strokeLinecap="round"/>
            </svg>
          </button>
        </div>

        {/* Search input */}
        <div style={{ position: 'relative', marginBottom: 16 }}>
          <div style={{
            display: 'flex', alignItems: 'center', gap: 10,
            background: 'var(--panel-2)', border: `1px solid ${errors.ticker ? 'var(--red)' : form.ticker ? 'var(--accent)' : 'var(--border)'}`,
            borderRadius: 10, padding: '0 12px', transition: 'border-color 0.15s',
          }}>
            {/* Search icon or spinner */}
            <div style={{ color: 'var(--text-faint)', flexShrink: 0, display: 'flex', alignItems: 'center' }}>
              {searching ? (
                <svg width="16" height="16" viewBox="0 0 24 24" fill="none" style={{ animation: 'spin 0.8s linear infinite' }}>
                  <circle cx="12" cy="12" r="9" stroke="currentColor" strokeWidth="2" strokeDasharray="28" strokeDashoffset="10"/>
                </svg>
              ) : (
                <svg width="15" height="15" viewBox="0 0 20 20" fill="none">
                  <circle cx="8.5" cy="8.5" r="5.5" stroke="currentColor" strokeWidth="1.6"/>
                  <path d="M13 13l4 4" stroke="currentColor" strokeWidth="1.6" strokeLinecap="round"/>
                </svg>
              )}
            </div>

            <input
              value={query}
              onChange={e => handleQueryChange(e.target.value)}
              onFocus={() => results.length > 0 && setShowDropdown(true)}
              placeholder="Buscar por ticker o nombre…"
              autoFocus={!isEdit}
              style={{
                // minWidth: 0 deja que el flex realmente achique este input cuando
                // hay un badge "Cripto BTC" al lado. Sin esto el input mantiene su
                // tamaño natural y empuja el badge fuera del contenedor en mobile.
                flex: 1, minWidth: 0,
                padding: '11px 0', background: 'none', border: 'none',
                color: 'var(--text)', fontSize: 14, outline: 'none',
              }}
            />

            {/* Selected badge */}
            {form.ticker && (
              <div style={{ display: 'flex', alignItems: 'center', gap: 6, flexShrink: 0 }}>
                <TypeBadge type={form.type} />
                <span style={{ fontSize: 13, fontWeight: 700, color: 'var(--text)' }}>{form.ticker}</span>
              </div>
            )}
          </div>

          {errors.ticker && (
            <div style={{ fontSize: 11.5, color: 'var(--red)', marginTop: 4, paddingLeft: 2 }}>{errors.ticker}</div>
          )}

          {/* Dropdown */}
          {showDropdown && results.length > 0 && (
            <div style={{
              position: 'absolute', top: 'calc(100% + 6px)', left: 0, right: 0, zIndex: 10,
              background: 'var(--panel)', border: '1px solid var(--border-strong)', borderRadius: 12,
              boxShadow: '0 12px 36px rgba(0,0,0,0.4)', overflow: 'hidden',
            }}>
              {results.map((r, i) => (
                <button
                  key={r.ticker + i}
                  type="button"
                  onMouseDown={e => { e.preventDefault(); handleSelect(r); }}
                  style={{
                    width: '100%', display: 'flex', alignItems: 'center', gap: 10,
                    padding: '10px 14px', textAlign: 'left', color: 'var(--text)',
                    borderBottom: i < results.length - 1 ? '1px solid var(--border)' : 'none',
                    transition: 'background 0.1s',
                  }}
                  onMouseEnter={e => e.currentTarget.style.background = 'var(--panel-2)'}
                  onMouseLeave={e => e.currentTarget.style.background = 'transparent'}
                >
                  <TypeBadge type={r.type} />
                  <span style={{ fontWeight: 700, fontSize: 13.5, minWidth: 52 }}>{r.ticker}</span>
                  <span style={{ fontSize: 12.5, color: 'var(--text-dim)', flex: 1, overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>
                    {r.name}
                  </span>
                </button>
              ))}
            </div>
          )}
        </div>

        {/* Live price banner */}
        {(fetchingPrice || livePrice) && (
          <div style={{
            display: 'flex', alignItems: 'center', gap: 12, padding: '10px 14px',
            background: 'var(--panel-2)', border: '1px solid var(--border)', borderRadius: 10,
            marginBottom: 16,
            // En mobile, si el botón "← usar como precio compra" no entra al lado
            // del price + badge, deja que envuelva a la siguiente línea en lugar
            // de cortarse a la derecha del modal.
            flexWrap: 'wrap', rowGap: 8,
          }}>
            {fetchingPrice ? (
              <span style={{ fontSize: 12.5, color: 'var(--text-dim)' }}>Cargando precio actual…</span>
            ) : livePrice ? (
              <>
                <div>
                  <div style={{ fontSize: 11, color: 'var(--text-dim)', marginBottom: 1 }}>Precio actual</div>
                  <div style={{ fontSize: 16, fontWeight: 700, fontVariantNumeric: 'tabular-nums', letterSpacing: -0.5 }}>
                    {window.formatPrice(livePrice.currentPrice)}
                  </div>
                </div>
                <div style={{
                  fontSize: 12, fontWeight: 600, padding: '3px 8px', borderRadius: 6,
                  background: livePrice.change24 >= 0 ? 'rgba(85,217,138,0.12)' : 'rgba(239,104,104,0.12)',
                  color: livePrice.change24 >= 0 ? 'var(--green)' : 'var(--red)',
                }}>
                  {window.formatPct(livePrice.change24)}
                </div>
                <button
                  type="button"
                  onClick={fillBuyPrice}
                  title="Usar como precio de compra"
                  style={{
                    // marginInline: auto centra el botón cuando wrapea a su propia línea
                    // (caso mobile, banner wrap-eado). En desktop sigue compartiendo fila
                    // con el price+%; con auto a ambos lados queda centrado en el espacio
                    // restante, cosa visualmente OK.
                    marginInline: 'auto',
                    fontSize: 11.5, fontWeight: 600, padding: '5px 10px',
                    borderRadius: 7, border: '1px solid var(--border)', color: 'var(--text-dim)',
                    cursor: 'pointer', whiteSpace: 'nowrap', background: 'var(--panel)',
                    display: 'inline-flex', alignItems: 'center', gap: 6,
                  }}
                  onMouseEnter={e => { e.currentTarget.style.color = 'var(--text)'; e.currentTarget.style.borderColor = 'var(--border-strong)'; }}
                  onMouseLeave={e => { e.currentTarget.style.color = 'var(--text-dim)'; e.currentTarget.style.borderColor = 'var(--border)'; }}
                >
                  <svg width="11" height="11" viewBox="0 0 12 12" fill="none" aria-hidden>
                    <path d="M6 10 L6 2 M2.5 5.5 L6 2 L9.5 5.5" stroke="currentColor" strokeWidth="1.6" strokeLinecap="round" strokeLinejoin="round"/>
                  </svg>
                  usar como precio compra
                </button>
              </>
            ) : null}
          </div>
        )}

        {/* Form fields */}
        <div className="modal-form-grid">
          <Field label="Tipo de activo">
            <select value={form.type} onChange={e => set('type', e.target.value)} style={inputStyle(false)}>
              <option value="cripto">Criptomoneda</option>
              <option value="accion">Acción</option>
              <option value="etf">ETF</option>
            </select>
          </Field>

          <Field label="Fecha de compra">
            <input
              type="date"
              value={form.buyDate}
              onChange={e => set('buyDate', e.target.value)}
              style={{
                ...inputStyle(false),
                // iOS Safari renderiza el value del date input con una alineación
                // distinta a la de los otros inputs (queda centrado o algo desplazado),
                // lo que hace que el rectángulo se vea descolocado al lado de Cantidad/
                // Precio. Forzamos appearance:none + text-align:left para alinearlo.
                WebkitAppearance: 'none',
                appearance: 'none',
                textAlign: 'left',
                minHeight: 38,
              }}
            />
          </Field>

          <Field label="Cantidad" error={errors.qty}>
            <input
              type="number" step="any" min="0"
              value={form.qty}
              onChange={e => { set('qty', e.target.value); setAmount(''); }}
              placeholder="0.5"
              style={inputStyle(!!errors.qty)}
            />
          </Field>

          <Field
            label={
              <>
                Precio de compra
                <CurrencyToggle value={priceCurrency} onChange={setPriceCurrency} />
              </>
            }
            error={errors.buyPrice}
          >
            <input
              type="number" step="any" min="0"
              value={form.buyPrice}
              onChange={e => set('buyPrice', e.target.value)}
              placeholder={priceCurrency === 'USD' ? '58200' : '8400000'}
              style={inputStyle(!!errors.buyPrice)}
            />
            {priceCurrency === 'ARS' && (
              <div style={{ fontSize: 11, color: 'var(--text-faint)', marginTop: 4, lineHeight: 1.3 }}>
                {fxLoading
                  ? `Cargando cotización ${fxLabel}…`
                  : fxRate?.venta
                    ? <>
                        ≈ <span style={{ color: 'var(--text-dim)', fontWeight: 600, fontVariantNumeric: 'tabular-nums' }}>
                          {buyPriceUsd ? window.formatUSD(buyPriceUsd, 4) : '$0.00'}
                        </span> · {fxLabel} <span style={{ fontVariantNumeric: 'tabular-nums' }}>${fxRate.venta.toLocaleString('es-AR', { maximumFractionDigits: 2 })}</span>
                      </>
                    : <span style={{ color: 'var(--red)' }}>No se pudo obtener el {fxLabel} — probá USD</span>
                }
              </div>
            )}
          </Field>
        </div>

        {/* Monto invertido — opcional, calcula qty automáticamente */}
        <div style={{ marginTop: 12 }}>
          <Field
            label={
              <>
                <span style={{ color: 'var(--text-dim)' }}>O ingresá el monto total invertido</span>
                <CurrencyToggle value={amountCurrency} onChange={setAmountCurrency} />
              </>
            }
          >
            <input
              type="number" step="any" min="0"
              value={amount}
              onChange={e => setAmount(e.target.value)}
              placeholder={amountCurrency === 'USD' ? '100.00' : '144000'}
              style={inputStyle(false)}
            />
            {amount && +amount > 0 && (
              <AmountPreview
                amountUsd={amountUsd}
                buyPriceUsd={buyPriceUsd}
                ticker={form.ticker}
                amountCurrency={amountCurrency}
                fxRate={fxRate}
                fxLabel={fxLabel}
              />
            )}
          </Field>
        </div>

        {/* PnL preview */}
        {pnl !== null && form.qty && (
          <div style={{
            marginTop: 12, padding: '9px 14px', borderRadius: 9,
            background: pnl >= 0 ? 'rgba(85,217,138,0.07)' : 'rgba(239,104,104,0.07)',
            border: `1px solid ${pnl >= 0 ? 'rgba(85,217,138,0.2)' : 'rgba(239,104,104,0.2)'}`,
            display: 'flex', alignItems: 'center', gap: 8,
          }}>
            <span style={{ fontSize: 12, color: 'var(--text-dim)' }}>P&L estimado:</span>
            <span style={{
              fontSize: 13.5, fontWeight: 700, fontVariantNumeric: 'tabular-nums',
              color: pnl >= 0 ? 'var(--green)' : 'var(--red)',
            }}>
              {pnl >= 0 ? '+' : ''}{window.formatUSD(pnl)}
            </span>
            {form.buyPrice && livePrice && (
              <span style={{ fontSize: 12, color: 'var(--text-faint)', marginLeft: 2 }}>
                ({window.formatPct((livePrice.currentPrice / +form.buyPrice - 1) * 100)})
              </span>
            )}
          </div>
        )}

        {/* Actions */}
        <div style={{ display: 'flex', gap: 10, marginTop: 18, justifyContent: 'flex-end' }}>
          <button type="button" onClick={onClose}
            style={{ padding: '10px 16px', borderRadius: 10, color: 'var(--text-dim)', fontWeight: 500, fontSize: 14 }}>
            Cancelar
          </button>
          <button type="submit"
            style={{
              padding: '10px 20px', borderRadius: 10, fontSize: 14, fontWeight: 700,
              background: 'var(--accent)', color: '#1a0f05',
              opacity: form.ticker ? 1 : 0.6,
            }}>
            {isEdit ? 'Guardar cambios' : 'Agregar al portafolio'}
          </button>
        </div>
      </form>

      <style>{`
        @keyframes spin { to { transform: rotate(360deg); } }
      `}</style>
    </div>
  );
}

const inputStyle = (hasError) => ({
  width: '100%', padding: '9px 11px',
  background: 'var(--panel-2)',
  border: `1px solid ${hasError ? 'var(--red)' : 'var(--border)'}`,
  borderRadius: 8, color: 'var(--text)', fontSize: 13.5, outline: 'none',
  transition: 'border-color 0.15s',
});

function AmountPreview({ amountUsd, buyPriceUsd, ticker, amountCurrency, fxRate, fxLabel }) {
  if (amountCurrency === 'ARS' && !fxRate?.venta) {
    return (
      <div style={{ fontSize: 11, color: 'var(--red)', marginTop: 4 }}>
        Cargando {fxLabel}…
      </div>
    );
  }
  if (!amountUsd || !buyPriceUsd || buyPriceUsd <= 0 || !ticker) {
    return (
      <div style={{ fontSize: 11, color: 'var(--text-faint)', marginTop: 4 }}>
        Seleccioná un activo y precio para ver la cantidad calculada.
      </div>
    );
  }
  const qty = amountUsd / buyPriceUsd;
  const wholeUnits = Math.floor(qty);
  const fractional = qty - wholeUnits;
  const pctOfShare = fractional * 100;

  return (
    <div style={{ fontSize: 11.5, color: 'var(--text-faint)', marginTop: 6, lineHeight: 1.4 }}>
      <div>
        ≈ <span style={{ color: 'var(--accent)', fontWeight: 700, fontVariantNumeric: 'tabular-nums' }}>
          {qty.toLocaleString('en-US', { maximumFractionDigits: 6 })} {ticker}
        </span>
        {amountCurrency === 'ARS' && (
          <> · ${amountUsd.toLocaleString('en-US', { maximumFractionDigits: 2 })} USD a {fxLabel} ${fxRate.venta.toLocaleString('es-AR', { maximumFractionDigits: 2 })}</>
        )}
      </div>
      <div style={{ color: 'var(--text-dim)', marginTop: 2 }}>
        {wholeUnits >= 1
          ? <>{wholeUnits} entera{wholeUnits === 1 ? '' : 's'}{fractional > 0 && <> · {pctOfShare.toFixed(2)}% de la siguiente</>}</>
          : <>{pctOfShare.toFixed(2)}% de 1 {ticker}</>
        }
      </div>
    </div>
  );
}

function CurrencyToggle({ value, onChange }) {
  return (
    <span style={{
      display: 'inline-flex', marginLeft: 8, padding: 2, borderRadius: 6,
      background: 'var(--panel-2)', border: '1px solid var(--border)',
      verticalAlign: 'middle',
    }}>
      {['USD', 'ARS'].map(c => {
        const active = c === value;
        return (
          <button
            key={c} type="button"
            onClick={() => onChange(c)}
            style={{
              padding: '1px 7px', borderRadius: 4, fontSize: 10, fontWeight: 700,
              letterSpacing: 0.3, color: active ? 'var(--text)' : 'var(--text-faint)',
              background: active ? 'var(--panel)' : 'transparent',
              transition: 'all 0.12s',
            }}>
            {c}
          </button>
        );
      })}
    </span>
  );
}

function Field({ label, children, error, span = 1 }) {
  return (
    <label style={{ display: 'flex', flexDirection: 'column', gap: 5, gridColumn: `span ${span}` }}>
      <span style={{ fontSize: 11.5, color: 'var(--text-dim)', fontWeight: 600, letterSpacing: 0.2 }}>
        {label}{error && <span style={{ color: 'var(--red)', fontWeight: 400 }}> · {error}</span>}
      </span>
      {children}
    </label>
  );
}

Object.assign(window, { AddAssetModal });
