const { useState, useEffect, useMemo, useRef } = React;

// En dev (file:// o localhost) apuntamos al backend en :3001.
// En producción usamos el mismo origen (string vacío) — el backend sirve el frontend.
const BACKEND = (window.location.protocol === 'file:' || window.location.hostname === 'localhost' || window.location.hostname === '127.0.0.1')
  ? 'http://localhost:3001'
  : '';

// Color verde brand para todos los portafolios. Si en el futuro querés variedad, volvé a un array.
const PORTFOLIO_COLOR = 'linear-gradient(135deg, #26d989, #00c275)';

const DEFAULT_PORTFOLIOS = [
  { id: 'p1', name: 'Portfolio Jubilación', color: PORTFOLIO_COLOR },
];

function App() {
  const tweakDefaults = JSON.parse(document.getElementById('tweak-defaults').textContent.replace(/\/\*EDITMODE-(BEGIN|END)\*\//g, ''));
  const [tweaks, setTweaks] = useState(tweakDefaults);
  const [tweaksVisible, setTweaksVisible] = useState(false);

  // --- Auth ---
  const [token, setToken] = useState(() => localStorage.getItem('finanzas_token'));
  const [user, setUser] = useState(null);
  const [authChecking, setAuthChecking] = useState(!!token);
  const [dataLoaded, setDataLoaded] = useState(false);
  // 'hidden' = mostrar landing público; 'login'/'register' = mostrar AuthScreen con ese modo inicial
  const [authView, setAuthView] = useState('hidden');
  // 'dashboard' (default) o 'admin'. Solo cambia para usuarios admin.
  const [view, setView] = useState('dashboard');
  // Contador de feedbacks nuevos (para el badge rojo en el sidebar)
  const [adminNewCount, setAdminNewCount] = useState(0);

  // Title dinámico de la pestaña: "TrackerPro" en páginas públicas,
  // "TrackerPro - Panel" (o "Admin") cuando el usuario está adentro autenticado.
  useEffect(() => {
    if (token && user) {
      document.title = view === 'admin' && user.isAdmin
        ? 'TrackerPro - Admin'
        : 'TrackerPro - Panel';
    } else {
      document.title = 'TrackerPro';
    }
  }, [token, user, view]);

  const refreshAdminCount = () => {
    if (!user?.isAdmin || !token) return;
    fetch(`${BACKEND}/api/admin/feedback/count`, {
      headers: { Authorization: `Bearer ${token}` },
    })
      .then(r => r.ok ? r.json() : null)
      .then(d => { if (d?.counts) setAdminNewCount(d.counts.new || 0); })
      .catch(() => {});
  };

  // Polling cada 60s del contador de feedback nuevos (solo si es admin)
  useEffect(() => {
    if (!user?.isAdmin || !token) return;
    refreshAdminCount();
    const t = setInterval(refreshAdminCount, 60000);
    return () => clearInterval(t);
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [user, token]);

  const authFetch = (url, opts = {}) => fetch(url, {
    ...opts,
    headers: {
      ...(opts.headers || {}),
      Authorization: `Bearer ${token}`,
    },
  });

  const [collapsed, setCollapsed] = useState(false);
  const [mobileOpen, setMobileOpen] = useState(false);
  const [isMobile, setIsMobile] = useState(false);

  useEffect(() => {
    const check = () => setIsMobile(window.innerWidth <= 780);
    check();
    window.addEventListener('resize', check);
    return () => window.removeEventListener('resize', check);
  }, []);

  const [portfolios, setPortfolios] = useState(DEFAULT_PORTFOLIOS);
  const [activePortfolio, setActivePortfolio] = useState('p1');
  const [assets, setAssets] = useState([]);

  const [balanceHidden, setBalanceHidden] = useState(false);
  const [period, setPeriod] = useState('30D');
  const [filter, setFilter] = useState('todo');
  const [historyData, setHistoryData] = useState({});
  const [pricesLoading, setPricesLoading] = useState(false);
  const [confirmDelete, setConfirmDelete] = useState(null);
  const [lastUpdated, setLastUpdated] = useState(null);
  const [portfolioModal, setPortfolioModal] = useState(null);
  const [portfolioModalName, setPortfolioModalName] = useState('');
  const assetsRef = useRef(assets);

  const [modalOpen, setModalOpen] = useState(false);
  const [editingAsset, setEditingAsset] = useState(null);
  const [cedearMap, setCedearMap] = useState({});
  // Estado de la celebración (símbolo/color del activo recién comprado).
  // Lo dispara handleSave si es una compra nueva y el ticker está en POPULAR_ASSETS.
  const [celebration, setCelebration] = useState(null);

  // Cargar tabla de CEDEARs (ratio + subyacente) una vez
  useEffect(() => {
    fetch(`${BACKEND}/api/cedears`)
      .then(r => r.ok ? r.json() : {})
      .then(setCedearMap)
      .catch(() => {});
  }, []);

  // Tweaks protocol
  useEffect(() => {
    const handler = (e) => {
      if (!e.data || typeof e.data !== 'object') return;
      if (e.data.type === '__activate_edit_mode') setTweaksVisible(true);
      if (e.data.type === '__deactivate_edit_mode') setTweaksVisible(false);
    };
    window.addEventListener('message', handler);
    window.parent.postMessage({ type: '__edit_mode_available' }, '*');
    return () => window.removeEventListener('message', handler);
  }, []);

  useEffect(() => {
    document.documentElement.setAttribute('data-theme', tweaks.theme);
  }, [tweaks.theme]);

  // Verificar token al montar
  useEffect(() => {
    if (!token) { setAuthChecking(false); return; }
    fetch(`${BACKEND}/api/auth/me`, { headers: { Authorization: `Bearer ${token}` } })
      .then(r => r.ok ? r.json() : Promise.reject())
      .then(data => setUser(data.user))
      .catch(() => {
        localStorage.removeItem('finanzas_token');
        setToken(null);
        setUser(null);
      })
      .finally(() => setAuthChecking(false));
  }, [token]);

  // Cargar datos del usuario desde el backend
  const [loadError, setLoadError] = useState(null);
  useEffect(() => {
    if (!user || !token) return;
    setLoadError(null);
    fetch(`${BACKEND}/api/user-data`, { headers: { Authorization: `Bearer ${token}` } })
      .then(r => r.ok ? r.json() : Promise.reject(new Error('No se pudieron cargar tus datos')))
      .then(data => {
        if (Array.isArray(data.portfolios) && data.portfolios.length) setPortfolios(data.portfolios);
        if (Array.isArray(data.assets)) setAssets(data.assets);
        if (data.activePortfolio) setActivePortfolio(data.activePortfolio);
        setDataLoaded(true);
      })
      .catch(err => setLoadError(err.message || 'Error de conexión'));
  }, [user, token]);

  // Persistir cambios en el backend (debounce 600ms)
  const saveTimeoutRef = useRef(null);
  useEffect(() => {
    if (!dataLoaded || !token) return;
    clearTimeout(saveTimeoutRef.current);
    saveTimeoutRef.current = setTimeout(() => {
      fetch(`${BACKEND}/api/user-data`, {
        method: 'PUT',
        headers: { 'Content-Type': 'application/json', Authorization: `Bearer ${token}` },
        body: JSON.stringify({ portfolios, assets, activePortfolio }),
      }).catch(() => {});
    }, 600);
    return () => clearTimeout(saveTimeoutRef.current);
  }, [portfolios, assets, activePortfolio, dataLoaded, token]);

  // Keep ref in sync so price polling always has latest assets
  useEffect(() => { assetsRef.current = assets; }, [assets]);

  // Ticker para refrescar el "actualizado Xs atrás"
  const [, forceTickUpdate] = useState(0);
  useEffect(() => {
    const t = setInterval(() => forceTickUpdate(n => n + 1), 1000);
    return () => clearInterval(t);
  }, []);

  // Fetch prices cada 30s (arranca cuando data está cargada)
  useEffect(() => {
    if (!dataLoaded) return;
    const fetchPrices = () => {
      const list = assetsRef.current;
      const tickers = list.map(a => a.ticker).join(',');
      if (!tickers) { setPricesLoading(false); setLastUpdated(new Date()); return; }
      // Mandamos el type per-ticker como hint: el backend usa eso para rutar
      // criptos fuera del map hardcoded directo a Binance (si no, caerian a Yahoo).
      const types = list.map(a => `${a.ticker}:${a.type}`).join(',');
      setPricesLoading(true);
      fetch(`${BACKEND}/api/prices?tickers=${tickers}&types=${encodeURIComponent(types)}`)
        .then(r => r.json())
        .then(data => {
          setAssets(prev => prev.map(a =>
            data[a.ticker]
              ? {
                  ...a,
                  currentPrice: data[a.ticker].currentPrice,
                  change24: data[a.ticker].change24,
                  // iconUrl solo viene para cripto. Si no llega lo dejamos como estaba.
                  iconUrl: data[a.ticker].iconUrl ?? a.iconUrl,
                }
              : a
          ));
        })
        .catch(() => {})
        .finally(() => { setPricesLoading(false); setLastUpdated(new Date()); });
    };

    fetchPrices();
    const interval = setInterval(fetchPrices, 30000);
    return () => clearInterval(interval);
  }, [dataLoaded]);

  // Firma estable de los activos del portafolio activo (ticker:qty).
  // Cambia cuando agregás/sacás un activo o editás cantidades, pero NO cuando solo se actualizan precios.
  const assetSignature = useMemo(() =>
    assets
      .filter(a => (a.portfolioId || 'p1') === activePortfolio)
      .map(a => `${a.ticker}:${a.qty}:${a.buyDate || ''}`)
      .sort()
      .join(','),
    [assets, activePortfolio]
  );

  // Fetch history para portafolio + período activo (re-fetchea si cambia la composición)
  useEffect(() => {
    if (!dataLoaded || !assetSignature) return;
    const portfolioAssets = assetsRef.current.filter(a => (a.portfolioId || 'p1') === activePortfolio);
    if (!portfolioAssets.length) return;
    fetch(`${BACKEND}/api/history`, {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({
        assets: portfolioAssets.map(a => ({
          ticker: a.ticker,
          qty: a.qty,
          type: a.type,
          buyPrice: a.buyPrice,
          buyDate: a.buyDate,
        })),
        period,
      }),
    })
      .then(r => r.json())
      .then(data => {
        if (Array.isArray(data) && data.length > 0) {
          setHistoryData(prev => ({
            ...prev,
            [`${activePortfolio}:${period}`]: data.map(p => ({ ...p, date: new Date(p.date) })),
          }));
        }
      })
      .catch(() => {});
  }, [period, activePortfolio, dataLoaded, assetSignature]);

  const updateTweaks = (edits) => {
    setTweaks(t => ({ ...t, ...edits }));
    window.parent.postMessage({ type: '__edit_mode_set_keys', edits }, '*');
  };

  const filteredAssets = useMemo(() =>
    assets.filter(a => (a.portfolioId || 'p1') === activePortfolio),
    [assets, activePortfolio]
  );

  const portfolioTotals = useMemo(() => {
    const map = {};
    assets.forEach(a => {
      const pid = a.portfolioId || 'p1';
      map[pid] = (map[pid] || 0) + a.qty * a.currentPrice;
    });
    return map;
  }, [assets]);

  // Cambio del día — usa el change24 (% últimas 24h) de cada activo para calcular el cambio en USD
  const dailyChange = useMemo(() => {
    let dollar = 0;
    let prevValue = 0;
    for (const a of filteredAssets) {
      const currentValue = a.qty * a.currentPrice;
      const factor = 1 + (a.change24 || 0) / 100;
      const prev = factor > 0 ? currentValue / factor : currentValue;
      dollar += currentValue - prev;
      prevValue += prev;
    }
    const pct = prevValue > 0 ? (dollar / prevValue) * 100 : 0;
    return { dollar, pct };
  }, [filteredAssets]);

  const totals = useMemo(() => {
    const value = filteredAssets.reduce((s, a) => s + a.qty * a.currentPrice, 0);
    const cost = filteredAssets.reduce((s, a) => s + a.qty * a.buyPrice, 0);
    const pnl = value - cost;
    const pnlPct = cost > 0 ? (pnl / cost) * 100 : 0;
    return { value, cost, pnl, pnlPct };
  }, [filteredAssets]);

  const handleAdd = () => { setEditingAsset(null); setModalOpen(true); };
  const handleEdit = (a) => { setEditingAsset(a); setModalOpen(true); };
  const handleDelete = (id) => {
    const asset = assets.find(a => a.id === id);
    setConfirmDelete({ id, ticker: asset?.ticker ?? '' });
  };

  const handleSave = (asset) => {
    const isEditing = !!editingAsset;
    setAssets(prev => {
      const editIdx = prev.findIndex(x => x.id === asset.id);
      if (editIdx >= 0) { const next = [...prev]; next[editIdx] = asset; return next; }

      const sameIdx = prev.findIndex(x => x.ticker === asset.ticker && (x.portfolioId || 'p1') === activePortfolio);
      if (sameIdx >= 0) {
        const existing = prev[sameIdx];
        const totalQty = existing.qty + asset.qty;
        const avgBuyPrice = (existing.qty * existing.buyPrice + asset.qty * asset.buyPrice) / totalQty;
        const merged = {
          ...existing,
          qty: totalQty,
          buyPrice: +avgBuyPrice.toFixed(8),
          currentPrice: asset.currentPrice ?? existing.currentPrice,
          change24: asset.change24 ?? existing.change24,
        };
        const next = [...prev]; next[sameIdx] = merged; return next;
      }

      return [...prev, { ...asset, portfolioId: activePortfolio }];
    });
    setModalOpen(false);

    // Celebración solo en compras (alta nueva o adición a posición existente),
    // nunca al editar datos pasados. Si hay iconUrl (cripto), explota con el logo real.
    // Si no, cae al símbolo del POPULAR_ASSETS (BTC ₿, NVDA ◣, etc.).
    if (!isEditing) {
      const conf = window.getCelebrationFor?.(asset.ticker, asset.iconUrl);
      if (conf) setCelebration(conf);
    }
  };

  const handleOpenCreatePortfolio = () => {
    setPortfolioModalName('');
    setPortfolioModal({ mode: 'create' });
  };

  const handleOpenEditPortfolio = (p) => {
    setPortfolioModalName(p.name);
    setPortfolioModal({ mode: 'edit', id: p.id });
  };

  const handleSavePortfolio = () => {
    const name = portfolioModalName.trim();
    if (!name) return;
    if (portfolioModal.mode === 'create') {
      const id = `p${Date.now()}`;
      setPortfolios(p => [...p, { id, name, color: PORTFOLIO_COLOR }]);
      setActivePortfolio(id);
    } else {
      setPortfolios(p => p.map(x => x.id === portfolioModal.id ? { ...x, name } : x));
    }
    setPortfolioModal(null);
  };

  const handleDeletePortfolio = (id) => {
    if (portfolios.length <= 1) return;
    const remaining = portfolios.find(p => p.id !== id);
    setPortfolios(p => p.filter(x => x.id !== id));
    setAssets(a => a.filter(x => (x.portfolioId || 'p1') !== id));
    if (activePortfolio === id && remaining) setActivePortfolio(remaining.id);
    setPortfolioModal(null);
  };

  const handleLogout = () => {
    localStorage.removeItem('finanzas_token');
    setToken(null);
    setUser(null);
    setDataLoaded(false);
    setAssets([]);
    setPortfolios(DEFAULT_PORTFOLIOS);
    setActivePortfolio('p1');
    setHistoryData({});
    setLastUpdated(null);
  };

  const handleAuthenticated = (newToken, newUser) => {
    localStorage.setItem('finanzas_token', newToken);
    setToken(newToken);
    setUser(newUser);
  };

  const historyForPeriod = historyData[`${activePortfolio}:${period}`];
  const activePortfolioName = portfolios.find(p => p.id === activePortfolio)?.name ?? 'Panel de control';
  const display = (n, digits = 2) => balanceHidden ? '••••••' : window.formatUSD(n, digits);

  // --- Render según estado de auth ---
  if (authChecking) {
    return (
      <div style={{ minHeight: '100vh', display: 'grid', placeItems: 'center', background: 'var(--bg)', color: 'var(--text-dim)', fontSize: 13 }}>
        <div style={{ display: 'flex', alignItems: 'center', gap: 10 }}>
          <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="var(--accent)" strokeWidth="2.5" strokeDasharray="28" strokeDashoffset="10"/>
          </svg>
          Verificando sesión…
        </div>
      </div>
    );
  }

  if (!token || !user) {
    if (authView === 'hidden') {
      return (
        <LandingPage
          onLogin={() => setAuthView('login')}
          onSignup={() => setAuthView('register')}
        />
      );
    }
    return (
      <AuthScreen
        backend={BACKEND}
        onAuthenticated={handleAuthenticated}
        initialMode={authView}
        onBack={() => setAuthView('hidden')}
      />
    );
  }

  if (!dataLoaded) {
    return (
      <div style={{ minHeight: '100vh', display: 'grid', placeItems: 'center', background: 'var(--bg)', padding: 20 }}>
        <div style={{ textAlign: 'center', display: 'flex', flexDirection: 'column', alignItems: 'center', gap: 14 }}>
          {loadError ? (
            <>
              <div style={{ fontSize: 15, fontWeight: 600, color: 'var(--red)' }}>{loadError}</div>
              <div style={{ fontSize: 13, color: 'var(--text-dim)' }}>Verificá que el backend esté corriendo en {BACKEND}.</div>
              <div style={{ display: 'flex', gap: 8 }}>
                <button onClick={() => { setLoadError(null); setUser({ ...user }); }}
                  style={{ padding: '9px 16px', borderRadius: 10, fontSize: 13, fontWeight: 600, background: 'var(--accent)', color: '#1a0f05' }}>
                  Reintentar
                </button>
                <button onClick={handleLogout}
                  style={{ padding: '9px 16px', borderRadius: 10, fontSize: 13, fontWeight: 500, background: 'var(--panel-2)', border: '1px solid var(--border)', color: 'var(--text-dim)' }}>
                  Cerrar sesión
                </button>
              </div>
            </>
          ) : (
            <div style={{ display: 'flex', alignItems: 'center', gap: 10, color: 'var(--text-dim)', fontSize: 13 }}>
              <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="var(--accent)" strokeWidth="2.5" strokeDasharray="28" strokeDashoffset="10"/>
              </svg>
              Cargando tu portafolio…
            </div>
          )}
        </div>
      </div>
    );
  }

  return (
    <div className="layout" data-screen-label="Dashboard">
      {/* Mobile top bar */}
      <div className="mobile-topbar">
        <button onClick={() => setMobileOpen(true)}
          style={{ width: 36, height: 36, borderRadius: 8, color: 'var(--text)', display: 'grid', placeItems: 'center', position: 'relative', zIndex: 1 }}>
          <svg width="20" height="20" viewBox="0 0 20 20" fill="none"><path d="M3 5h14M3 10h14M3 15h14" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round"/></svg>
        </button>
        <div
          onClick={() => window.scrollTo({ top: 0, behavior: 'smooth' })}
          title="Ir al inicio"
          style={{
            position: 'absolute', left: '50%', top: '50%',
            transform: 'translate(-50%, -50%)',
            display: 'flex', alignItems: 'center', gap: 8,
            cursor: 'pointer', userSelect: 'none',
          }}
        >
          <svg width="22" height="22" viewBox="0 0 70 70" aria-hidden>
            <circle cx="35" cy="35" r="27" fill="none" stroke="#00c275" strokeWidth="3" />
            <path d="M23 43 L35 27 L47 35" stroke="#00c275" strokeWidth="3" fill="none" strokeLinecap="round" strokeLinejoin="round" />
            <path d="M41 27 L47 27 L47 33" stroke="#00c275" strokeWidth="3" fill="none" strokeLinecap="round" strokeLinejoin="round" />
          </svg>
          <div style={{ fontFamily: 'Space Grotesk, Inter, sans-serif', fontWeight: 700, fontSize: 16, letterSpacing: -0.5 }}>
            tracker<span style={{ color: '#00c275' }}>pro</span>
          </div>
        </div>
      </div>

      <div className={`sidebar-backdrop ${mobileOpen ? 'open' : ''}`} onClick={() => setMobileOpen(false)} />

      <div className={`sidebar-wrap ${mobileOpen ? 'open' : ''}`}>
        <Sidebar
          collapsed={collapsed && !isMobile}
          onToggle={() => isMobile ? setMobileOpen(false) : setCollapsed(c => !c)}
          isMobile={isMobile}
          portfolios={portfolios}
          activePortfolioId={activePortfolio}
          onSelectPortfolio={(id) => { setActivePortfolio(id); setMobileOpen(false); }}
          onCreatePortfolio={handleOpenCreatePortfolio}
          onEditPortfolio={handleOpenEditPortfolio}
          onAddToPortfolio={(id) => { setActivePortfolio(id); setMobileOpen(false); setEditingAsset(null); setModalOpen(true); }}
          portfolioTotals={portfolioTotals}
          balanceHidden={balanceHidden}
          userEmail={user.email}
          onLogout={handleLogout}
          isAdmin={!!user.isAdmin}
          onOpenAdmin={() => { setView('admin'); setMobileOpen(false); }}
          adminNewCount={adminNewCount}
        />
      </div>

      {view === 'admin' && user.isAdmin ? (
        <AdminPanel
          backend={BACKEND}
          token={token}
          isMobile={isMobile}
          onBack={() => setView('dashboard')}
          onCountChange={refreshAdminCount}
        />
      ) : (

      <main className="main-pane">
        <div className="header-row">
          <div className="header-main">
            {/* Barra de actualización (arriba de todo) */}
            <div className="header-progress" style={{ marginBottom: 6, display: 'flex', alignItems: 'center', gap: 8, minHeight: 14 }}>
              {pricesLoading ? (
                <span style={{ fontSize: 11, color: 'var(--accent)', fontWeight: 600, display: 'flex', alignItems: 'center', gap: 4 }}>
                  <svg width="11" height="11" 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.5" strokeDasharray="28" strokeDashoffset="10"/>
                  </svg>
                  actualizando…
                </span>
              ) : lastUpdated ? (
                <div
                  title={`Próxima actualización en ${Math.max(0, 30 - Math.round((Date.now() - lastUpdated) / 1000))}s`}
                  style={{
                    width: 90, height: 3, background: 'var(--panel-2)',
                    borderRadius: 2, overflow: 'hidden', flexShrink: 0,
                  }}>
                  <div
                    key={lastUpdated.getTime()}
                    style={{
                      height: '100%',
                      background: 'linear-gradient(90deg, var(--accent), var(--accent-soft))',
                      borderRadius: 2,
                      animation: 'fillProgress 30s linear forwards',
                    }}
                  />
                </div>
              ) : null}
            </div>
            <div className="header-top" style={{ fontSize: 13, color: 'var(--text-dim)', marginBottom: 4, display: 'flex', alignItems: 'center', gap: 8 }}>
              <span>Total: <span style={{ color: 'var(--text)', fontWeight: 600 }}>{activePortfolioName}</span></span>
            </div>
            <div className="header-balance" style={{ display: 'flex', alignItems: 'center', gap: 10, minWidth: 0, maxWidth: '100%' }}>
              <div className="balance-num" style={{
                fontFamily: 'Space Grotesk, Inter, sans-serif', fontWeight: 700,
                color: 'var(--accent)', letterSpacing: -1, lineHeight: 1,
                fontVariantNumeric: 'tabular-nums',
                whiteSpace: 'nowrap',
                overflow: 'hidden',
                textOverflow: 'ellipsis',
                minWidth: 0,
              }}>
                {display(totals.value)}
              </div>
              <button
                title={balanceHidden ? 'Mostrar' : 'Ocultar'}
                onClick={() => setBalanceHidden(b => !b)}
                style={{ color: 'var(--text-dim)', padding: 6, borderRadius: 6 }}
              >
                {balanceHidden ? (
                  <svg width="22" height="22" viewBox="0 0 24 24" fill="none"><path d="M3 12s3-7 9-7 9 7 9 7-3 7-9 7-9-7-9-7z" stroke="currentColor" strokeWidth="1.5"/><circle cx="12" cy="12" r="3" stroke="currentColor" strokeWidth="1.5"/><path d="M4 4l16 16" stroke="currentColor" strokeWidth="1.5"/></svg>
                ) : (
                  <svg width="22" height="22" viewBox="0 0 24 24" fill="none"><path d="M3 12s3-7 9-7 9 7 9 7-3 7-9 7-9-7-9-7z" stroke="currentColor" strokeWidth="1.5"/><circle cx="12" cy="12" r="3" stroke="currentColor" strokeWidth="1.5"/></svg>
                )}
              </button>
            </div>

            {/* Cambio del día */}
            <div className="header-daily" style={{
              display: 'flex', alignItems: 'center', gap: 6, marginTop: 8, fontSize: 13, fontWeight: 600,
              color: dailyChange.dollar >= 0 ? 'var(--green)' : 'var(--red)',
              fontVariantNumeric: 'tabular-nums',
            }}>
              <svg width="14" height="14" viewBox="0 0 14 14" fill="none">
                {dailyChange.dollar >= 0
                  ? <path d="M3 10 L7 4 L11 10" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round"/>
                  : <path d="M3 4 L7 10 L11 4" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round"/>
                }
              </svg>
              <span>
                {dailyChange.dollar >= 0 ? '+' : ''}{display(dailyChange.dollar)}
              </span>
              <span style={{ color: 'var(--text-faint)', fontWeight: 400 }}>·</span>
              <span>{window.formatPct(dailyChange.pct)}</span>
              <span style={{ color: 'var(--text-faint)', fontWeight: 400, marginLeft: 2 }}>hoy</span>
            </div>
          </div>

          <div style={{ flex: 1 }} />

          <div className="benefit-card" style={{
            background: 'linear-gradient(135deg, rgba(167,139,250,0.25), rgba(124,58,237,0.1))',
            border: '1px solid rgba(167,139,250,0.3)',
            borderRadius: 14, padding: '14px 20px', display: 'flex', alignItems: 'center', gap: 14,
          }}>
            <div style={{
              width: 42, height: 42, borderRadius: '50%',
              background: 'linear-gradient(135deg, #a78bfa, #7c3aed)',
              display: 'grid', placeItems: 'center',
            }}>
              <svg width="22" height="22" viewBox="0 0 24 24" fill="none"><path d="M12 2v20M7 6h8a3 3 0 0 1 0 6H9a3 3 0 0 0 0 6h8" stroke="white" strokeWidth="1.8" strokeLinecap="round"/></svg>
            </div>
            <div className="benefit-text">
              <div style={{ fontSize: 12, color: 'var(--text-dim)' }}>Beneficio histórico</div>
              <div style={{ fontSize: 16, fontWeight: 700, color: totals.pnl >= 0 ? 'var(--green)' : 'var(--red)', fontVariantNumeric: 'tabular-nums' }}>
                {totals.pnl >= 0 ? '+' : ''}{display(totals.pnl)}
              </div>
              <div style={{ fontSize: 12, color: totals.pnl >= 0 ? 'var(--green)' : 'var(--red)' }}>
                {window.formatPct(totals.pnlPct)}
              </div>
            </div>
          </div>
        </div>

        <div style={{ height: 1, background: 'var(--border)', margin: '4px 0 22px' }} />

        <div className="charts-row">
          <HistoryChart period={period} onPeriodChange={setPeriod} data={historyForPeriod} balanceHidden={balanceHidden} />
          <AllocationDonut assets={filteredAssets} totalValue={totals.value} balanceHidden={balanceHidden} />
        </div>

        <AssetsTable
          assets={filteredAssets}
          filter={filter}
          onFilterChange={setFilter}
          onAdd={handleAdd}
          onEdit={handleEdit}
          onDelete={handleDelete}
          balanceHidden={balanceHidden}
          cedearMap={cedearMap}
          isMobile={isMobile}
        />
      </main>
      )}

      <AddAssetModal
        open={modalOpen}
        editing={editingAsset}
        cedearMap={cedearMap}
        onClose={() => setModalOpen(false)}
        onSave={handleSave}
      />

      <TweaksPanel values={tweaks} onChange={updateTweaks} visible={tweaksVisible} />

      {/* Celebración al confirmar la compra de un activo popular */}
      <AssetCelebration celebration={celebration} onDone={() => setCelebration(null)} />

      {/* Botón flotante de feedback (solo cuando el usuario está autenticado).
          Lo escondemos cuando hay un modal abierto (agregar/editar activo o
          confirmar borrado) para que no tape nada del contenido del modal. */}
      {!modalOpen && !confirmDelete && (
        <FeedbackButton backend={BACKEND} token={token} />
      )}

      {/* Modal confirmación eliminar activo */}
      {confirmDelete && (
        <div onClick={() => setConfirmDelete(null)}
          style={{ position: 'fixed', inset: 0, background: 'rgba(0,0,0,0.6)', display: 'grid', placeItems: 'center', zIndex: 60 }}>
          <div onClick={e => e.stopPropagation()}
            style={{
              width: 380, maxWidth: 'calc(100% - 32px)',
              background: 'var(--panel)', border: '1px solid var(--border)',
              borderRadius: 18, padding: '28px 24px 22px',
              boxShadow: '0 28px 70px rgba(0,0,0,0.55)',
              display: 'flex', flexDirection: 'column', alignItems: 'center', gap: 8, textAlign: 'center',
            }}>
            <div style={{
              width: 52, height: 52, borderRadius: '50%',
              background: 'rgba(239,104,104,0.12)', border: '1px solid rgba(239,104,104,0.25)',
              display: 'grid', placeItems: 'center', marginBottom: 4,
            }}>
              <svg width="22" height="22" viewBox="0 0 24 24" fill="none">
                <path d="M4 7h16M6 7l1 13h10L18 7M9 7V4.5h6V7" stroke="var(--red)" strokeWidth="1.6" strokeLinecap="round" strokeLinejoin="round"/>
              </svg>
            </div>
            <div style={{ fontSize: 17, fontWeight: 700, letterSpacing: -0.3 }}>Eliminar posición</div>
            <div style={{ fontSize: 13.5, color: 'var(--text-dim)', lineHeight: 1.5 }}>
              ¿Seguro que querés eliminar{' '}
              <span style={{ color: 'var(--text)', fontWeight: 600 }}>{confirmDelete.ticker}</span>
              {' '}de tu portafolio?<br/>Esta acción no se puede deshacer.
            </div>
            <div style={{ display: 'flex', gap: 10, marginTop: 14, width: '100%' }}>
              <button onClick={() => setConfirmDelete(null)}
                style={{ flex: 1, padding: '11px 0', borderRadius: 11, fontWeight: 600, fontSize: 14, background: 'var(--panel-2)', border: '1px solid var(--border)', color: 'var(--text)' }}>
                Cancelar
              </button>
              <button
                onClick={() => { setAssets(a => a.filter(x => x.id !== confirmDelete.id)); setConfirmDelete(null); }}
                style={{ flex: 1, padding: '11px 0', borderRadius: 11, fontWeight: 700, fontSize: 14, background: 'var(--red)', color: '#fff', border: 'none' }}>
                Eliminar
              </button>
            </div>
          </div>
        </div>
      )}

      {/* Modal crear / editar portafolio */}
      {portfolioModal && (
        <div onClick={() => setPortfolioModal(null)}
          style={{ position: 'fixed', inset: 0, background: 'rgba(0,0,0,0.6)', display: 'grid', placeItems: 'center', zIndex: 60 }}>
          <div onClick={e => e.stopPropagation()}
            style={{
              width: 400, maxWidth: 'calc(100% - 32px)',
              background: 'var(--panel)', border: '1px solid var(--border)',
              borderRadius: 18, padding: '28px 24px 22px',
              boxShadow: '0 28px 70px rgba(0,0,0,0.55)',
              display: 'flex', flexDirection: 'column', gap: 16,
            }}>
            <div style={{ fontSize: 17, fontWeight: 700, letterSpacing: -0.3 }}>
              {portfolioModal.mode === 'create' ? 'Nuevo portafolio' : 'Editar portafolio'}
            </div>
            <div>
              <div style={{ fontSize: 12, color: 'var(--text-dim)', marginBottom: 6, fontWeight: 500 }}>Nombre</div>
              <input
                autoFocus
                value={portfolioModalName}
                onChange={e => setPortfolioModalName(e.target.value)}
                onKeyDown={e => { if (e.key === 'Enter') handleSavePortfolio(); if (e.key === 'Escape') setPortfolioModal(null); }}
                placeholder="Ej: Jubilación, Fondo de emergencia…"
                style={{
                  width: '100%', padding: '11px 14px', borderRadius: 10, fontSize: 14,
                  background: 'var(--panel-2)', border: '1px solid var(--border-strong)',
                  color: 'var(--text)', outline: 'none', boxSizing: 'border-box',
                }}
              />
            </div>
            <div style={{ display: 'flex', gap: 10 }}>
              <button onClick={() => setPortfolioModal(null)}
                style={{ flex: 1, padding: '11px 0', borderRadius: 11, fontWeight: 600, fontSize: 14, background: 'var(--panel-2)', border: '1px solid var(--border)', color: 'var(--text)' }}>
                Cancelar
              </button>
              <button onClick={handleSavePortfolio}
                style={{
                  flex: 1, padding: '11px 0', borderRadius: 11, fontWeight: 700, fontSize: 14,
                  background: 'var(--accent)', color: '#1a0f05', border: 'none',
                  opacity: portfolioModalName.trim() ? 1 : 0.45, cursor: portfolioModalName.trim() ? 'pointer' : 'default',
                }}>
                {portfolioModal.mode === 'create' ? 'Crear portafolio' : 'Guardar cambios'}
              </button>
            </div>
            {portfolioModal.mode === 'edit' && portfolios.length > 1 && (
              <button
                onClick={() => handleDeletePortfolio(portfolioModal.id)}
                style={{
                  padding: '10px 0', borderRadius: 10, fontSize: 13, fontWeight: 500,
                  color: 'var(--red)', background: 'rgba(239,104,104,0.08)',
                  border: '1px solid rgba(239,104,104,0.2)',
                }}>
                {(() => {
                  const count = assets.filter(a => (a.portfolioId || 'p1') === portfolioModal.id).length;
                  return count > 0 ? `Eliminar portafolio (borra ${count} activo${count !== 1 ? 's' : ''})` : 'Eliminar portafolio';
                })()}
              </button>
            )}
          </div>
        </div>
      )}
    </div>
  );
}

ReactDOM.createRoot(document.getElementById('root')).render(<App />);
