// Main app — composes sections
const { useEffect, useRef, useState } = React;

function StatusBar() {
  const [time, setTime] = useState(new Date());
  useEffect(() => {
    const id = setInterval(() => setTime(new Date()), 1000);
    return () => clearInterval(id);
  }, []);
  const t = time.toISOString().replace('T', ' ').slice(0, 19);
  return (
    <div className="status-bar">
      <div style={{display:'flex', gap:'18px', alignItems:'center'}}>
        <div className="dots">
          <div className="dot live"></div>
          <div className="dot warn"></div>
          <div className="dot err"></div>
        </div>
        <span>varad.sh / portfolio / v4.0.7</span>
      </div>
      <div className="right">
        <span>UTC {t}</span>
        <span className="glitch">SYSTEM ONLINE</span>
        <span>MEM 4.2G / 16G</span>
      </div>
    </div>
  );
}

function Hero({ ascii }) {
  const D = window.DATA;
  return (
    <div className="hero">
      <div>
        <div className="hero-title glitch" data-text={D.name.toUpperCase()}>
          {D.name.toUpperCase().split(' ').map((w, i) => <div key={i}>{w}</div>)}
        </div>
        <div className="hero-sub">
          <span className="accent">$</span> backend engineer · open-source contributor · startup builder.
          <br/>i build the stuff you forgot was running.
        </div>
        <div className="hero-meta">
          <span className="k">role</span><span className="v">{D.title}</span>
          <span className="k">loc</span><span className="v">{D.location}</span>
          <span className="k">status</span><span className="v">● {D.status}</span>
          <span className="k">email</span><span className="v"><a href={`mailto:${D.email}`}>{D.email}</a></span>
          <span className="k">github</span><span className="v"><a href={D.github} target="_blank" rel="noopener">@Varadraj75</a></span>
          <span className="k">linkedin</span><span className="v"><a href={D.linkedin} target="_blank" rel="noopener">/in/varadrajagrawal</a></span>
        </div>
        <div className="hint">
          <kbd>/</kbd> to focus terminal · <kbd>T</kbd> toggle tweaks · try <kbd>help</kbd> below
        </div>
      </div>
      <div>
        <pre className="hero-ascii">{ascii}</pre>
        <div style={{fontSize:'10px', color:'var(--fg-dim)', letterSpacing:'0.1em', textAlign:'center', marginTop:'8px', textTransform:'uppercase'}}>
          ./varad.jpg — rendered in shell
        </div>
      </div>
    </div>
  );
}

function SectionHeader({ cmd }) {
  return (
    <div className="sec-header">
      <span className="prompt">$</span>
      <span className="cmd">{cmd}</span>
      <span className="rule"></span>
    </div>
  );
}

function About() {
  const D = window.DATA;
  return (
    <div className="sec">
      <SectionHeader cmd="cat /home/varad/about.md" />
      <div style={{fontSize:'16px', lineHeight:'1.7', color:'var(--fg)', maxWidth:'72ch'}}>
        {D.about.map((l, i) => <p key={i} style={{marginBottom:'14px'}}>{l}</p>)}
        <p style={{marginTop:'20px', fontSize:'13px', color:'var(--fg-dim)'}}>
          <span className="glitch" style={{color:'var(--accent)'}}># manifesto</span><br/>
          ship small. ship fast. ship often. read code you didn't write. break things with intent. leave docs better than you found them.
        </p>
      </div>
    </div>
  );
}

function DraggableCard({ project, index, initial }) {
  const ref = useRef(null);
  const [pos, setPos] = useState(initial);
  const [rot, setRot] = useState(initial.rot);
  const [dragging, setDragging] = useState(false);
  const [isMobile, setIsMobile] = useState(() => typeof window !== 'undefined' && window.matchMedia('(max-width: 860px)').matches);
  useEffect(() => {
    const mq = window.matchMedia('(max-width: 860px)');
    const on = () => setIsMobile(mq.matches);
    mq.addEventListener ? mq.addEventListener('change', on) : mq.addListener(on);
    return () => { mq.removeEventListener ? mq.removeEventListener('change', on) : mq.removeListener(on); };
  }, []);
  const drag = useRef({ startX: 0, startY: 0, ox: 0, oy: 0 });
  const vel = useRef({ vx: 0, vy: 0, lastX: 0, lastY: 0, lastT: 0 });
  const animating = useRef(false);

  const onDown = (e) => {
    if (isMobile) return;
    e.preventDefault();
    const p = 'touches' in e ? e.touches[0] : e;
    drag.current = { startX: p.clientX, startY: p.clientY, ox: pos.x, oy: pos.y };
    vel.current = { vx: 0, vy: 0, lastX: p.clientX, lastY: p.clientY, lastT: Date.now() };
    setDragging(true);
    window.addEventListener('mousemove', onMove);
    window.addEventListener('mouseup', onUp);
    window.addEventListener('touchmove', onMove, { passive: false });
    window.addEventListener('touchend', onUp);
  };
  const onMove = (e) => {
    const p = 'touches' in e ? e.touches[0] : e;
    if ('preventDefault' in e && e.cancelable) e.preventDefault();
    const dx = p.clientX - drag.current.startX;
    const dy = p.clientY - drag.current.startY;
    setPos({ x: drag.current.ox + dx, y: drag.current.oy + dy });
    const now = Date.now();
    const dt = Math.max(1, now - vel.current.lastT);
    vel.current.vx = (p.clientX - vel.current.lastX) / dt * 16;
    vel.current.vy = (p.clientY - vel.current.lastY) / dt * 16;
    vel.current.lastX = p.clientX; vel.current.lastY = p.clientY; vel.current.lastT = now;
  };
  const onUp = () => {
    setDragging(false);
    window.removeEventListener('mousemove', onMove);
    window.removeEventListener('mouseup', onUp);
    window.removeEventListener('touchmove', onMove);
    window.removeEventListener('touchend', onUp);
    animating.current = true;
    let { vx, vy } = vel.current;
    const step = () => {
      if (!animating.current) return;
      setPos(p => {
        let nx = p.x + vx;
        let ny = p.y + vy;
        const parent = ref.current && ref.current.parentElement;
        if (parent) {
          const w = parent.clientWidth - 280;
          const h = parent.clientHeight - 180;
          if (nx < 0) { nx = 0; vx = Math.abs(vx) * 0.55; }
          if (nx > w) { nx = w; vx = -Math.abs(vx) * 0.55; }
          if (ny < 0) { ny = 0; vy = Math.abs(vy) * 0.55; }
          if (ny > h) { ny = h; vy = -Math.abs(vy) * 0.55; }
        }
        return { x: nx, y: ny };
      });
      vx *= 0.93; vy *= 0.93;
      setRot(r => r + vx * 0.05);
      if (Math.abs(vx) + Math.abs(vy) < 0.4) { animating.current = false; return; }
      requestAnimationFrame(step);
    };
    step();
  };

  useEffect(() => () => { animating.current = false; }, []);

  return (
    <div
      ref={ref}
      className={`card c-${project.color} ${dragging ? 'dragging' : ''}`}
      style={isMobile ? {} : {
        transform: `translate(${pos.x}px, ${pos.y}px) rotate(${rot}deg)`,
      }}
      onMouseDown={onDown}
      onTouchStart={onDown}
    >
      <div className="card-head">
        <span>PROJ_{String(index+1).padStart(3,'0')}</span>
        <span>{project.tags[0]}</span>
      </div>
      <div className="card-title glitch">{project.name}</div>
      <div className="card-desc">{project.desc}</div>
      <div className="card-tags">
        {project.tags.map(t => <span key={t} className="tag">{t}</span>)}
      </div>
      <div style={{display:'flex', gap:'14px'}}>
        {project.url && project.url !== project.repo && (
          <a className="card-link" href={project.url} target="_blank" rel="noopener" onMouseDown={(e)=>e.stopPropagation()} onClick={(e)=>e.stopPropagation()}>live</a>
        )}
        {project.repo && (
          <a className="card-link" href={project.repo} target="_blank" rel="noopener" onMouseDown={(e)=>e.stopPropagation()} onClick={(e)=>e.stopPropagation()}>repo</a>
        )}
      </div>
    </div>
  );
}

function Projects() {
  const D = window.DATA;
  const layouts = [
    { x: 30,  y: 40,  rot: -3 },
    { x: 340, y: 80,  rot: 2 },
    { x: 650, y: 40,  rot: -1.5 },
    { x: 260, y: 320, rot: 3 },
    { x: 580, y: 330, rot: -2.5 },
  ];
  return (
    <div className="sec">
      <SectionHeader cmd="ls -la ./projects" />
      <div className="cards-wrap">
        {D.projects.map((p, i) => (
          <DraggableCard key={i} project={p} index={i} initial={layouts[i % layouts.length]} />
        ))}
      </div>
    </div>
  );
}

function Skills() {
  const D = window.DATA;
  return (
    <div className="sec">
      <SectionHeader cmd="cat /etc/stack.conf" />
      <div className="skills">
        {D.skills.map((s, i) => (
          <div className="skill" key={i}>
            <div className="label"># {s.label}</div>
            <div className="items">
              {s.items.map((it, j) => (
                <span key={j}>
                  {it}{j < s.items.length - 1 ? '  ·  ' : ''}
                </span>
              ))}
            </div>
          </div>
        ))}
      </div>
    </div>
  );
}

function formatEventLine(ev) {
  const repo = ev.repo && ev.repo.name;
  const t = new Date(ev.created_at);
  const now = Date.now();
  const diff = (now - t.getTime()) / 1000;
  let rel;
  if (diff < 60) rel = `${Math.floor(diff)}s`;
  else if (diff < 3600) rel = `${Math.floor(diff/60)}m`;
  else if (diff < 86400) rel = `${Math.floor(diff/3600)}h`;
  else rel = `${Math.floor(diff/86400)}d`;

  let type = ev.type.replace('Event','');
  let detail = '';
  if (ev.type === 'PushEvent' && ev.payload && ev.payload.commits) {
    const n = ev.payload.commits.length;
    detail = `pushed ${n} commit${n>1?'s':''} to`;
  } else if (ev.type === 'CreateEvent') {
    detail = `created ${ev.payload.ref_type || 'branch'}`;
  } else if (ev.type === 'PullRequestEvent') {
    detail = `${ev.payload.action} PR on`;
  } else if (ev.type === 'IssuesEvent') {
    detail = `${ev.payload.action} issue on`;
  } else if (ev.type === 'WatchEvent') {
    detail = `starred`;
  } else if (ev.type === 'ForkEvent') {
    detail = `forked`;
  } else {
    detail = type.toLowerCase();
  }

  return { rel, detail, repo };
}

function GitHub() {
  const [gh, setGh] = useState(null);
  const [err, setErr] = useState(false);
  useEffect(() => {
    window.loadGitHub().then(setGh).catch((e) => { console.error(e); setErr(true); });
  }, []);

  if (err) {
    return (
      <div className="sec">
        <SectionHeader cmd={`curl -s api.github.com/users/Varadraj75`} />
        <div className="gh-loading" style={{color:'var(--accent-2)'}}>github fetch failed — rate limited? try a refresh.</div>
      </div>
    );
  }
  if (!gh) {
    return (
      <div className="sec">
        <SectionHeader cmd={`curl -s api.github.com/users/Varadraj75`} />
        <div className="gh-loading">fetching live github data...</div>
      </div>
    );
  }

  const user = gh.user || {};
  const repoCount = user.public_repos || gh.repos.length || 0;
  const stars = gh.totalStars || 0;
  const followers = user.followers || 0;
  const following = user.following || 0;

  // Languages sorted
  const totalLang = Object.values(gh.languages).reduce((a,b)=>a+b, 0) || 1;
  const langsSorted = Object.entries(gh.languages).sort((a,b)=>b[1]-a[1]).slice(0, 6);

  // Contrib cells
  const contrib = gh.contributions;

  // Events
  const events = gh.events || [];

  // contribution color scale
  const contribColor = (lvl) => {
    const m = { 0:'rgba(0,255,156,0.06)', 1:'rgba(0,255,156,0.25)', 2:'rgba(0,255,156,0.5)', 3:'rgba(0,255,156,0.75)', 4:'rgba(0,255,156,1)' };
    return m[lvl] || m[0];
  };

  return (
    <div className="sec">
      <SectionHeader cmd={`curl -s api.github.com/users/Varadraj75`} />

      <div className="gh-stats-row" style={{marginBottom:'16px'}}>
        <div className="gh-stat"><div className="big">{repoCount}</div><div className="lbl">public repos</div></div>
        <div className="gh-stat"><div className="big">{stars}</div><div className="lbl">total stars</div></div>
        <div className="gh-stat"><div className="big">{followers}</div><div className="lbl">followers</div></div>
      </div>

      {contrib && (
        <div className="gh-card" style={{marginBottom:'16px'}}>
          <h4>
            <span>contributions · last year <span style={{color:'var(--accent)'}}>({contrib.total ? Object.values(contrib.total).reduce((a,b)=>a+b,0) : contrib.contributions.length})</span></span>
            <span className="live">live</span>
          </h4>
          <div className="gh-contrib">
            <div className="gh-contrib-grid">
              {contrib.contributions.map((c, i) => (
                <div key={i} className="gh-cell" style={{background: contribColor(c.level), boxShadow: c.level >= 3 ? '0 0 3px var(--accent)':'none'}} title={`${c.date}: ${c.count}`}></div>
              ))}
            </div>
          </div>
        </div>
      )}

      <div className="gh-grid">
        <div className="gh-card">
          <h4><span>top repositories</span><span style={{color:'var(--fg-dim)'}}>by stars · recent</span></h4>
          <div className="gh-repos">
            {gh.top.slice(0, 6).map(r => (
              <a key={r.id} className="gh-repo" href={r.html_url} target="_blank" rel="noopener">
                <div className="r-name">{r.name}</div>
                <div className="r-desc">{r.description || '// no description'}</div>
                <div className="r-meta">
                  {r.language && <span className="lang">● {r.language}</span>}
                  <span className="star">★ {r.stargazers_count}</span>
                  <span>⑂ {r.forks_count}</span>
                </div>
              </a>
            ))}
            {gh.top.length === 0 && <div className="gh-loading">no public repos found</div>}
          </div>
        </div>

        <div style={{display:'flex', flexDirection:'column', gap:'16px'}}>
          <div className="gh-card">
            <h4><span>most-used languages</span></h4>
            <div className="gh-langs">
              {langsSorted.map(([name, count]) => {
                const pct = (count/totalLang)*100;
                return (
                  <div key={name} className="gh-lang-row">
                    <span className="name">{name}</span>
                    <span className="bar-wrap"><span className="bar-fill" style={{width: pct + '%'}}></span></span>
                    <span className="pct">{pct.toFixed(0)}%</span>
                  </div>
                );
              })}
              {langsSorted.length === 0 && <div style={{color:'var(--fg-dim)',fontSize:'11px'}}>no language data</div>}
            </div>
          </div>

          <div className="gh-card">
            <h4><span>recent activity</span><span style={{color:'var(--fg-dim)'}}>@ {new Date().toLocaleTimeString()}</span></h4>
            <div className="gh-events">
              {events.map((ev, i) => {
                const f = formatEventLine(ev);
                return (
                  <div className="gh-event" key={i}>
                    <span className="t">{f.rel} ago</span>
                    <span className="d">
                      <span className="type">{f.detail}</span>{' '}
                      <a className="repo" href={`https://github.com/${f.repo}`} target="_blank" rel="noopener" style={{color:'var(--accent-3)',textDecoration:'none'}}>{f.repo}</a>
                    </span>
                  </div>
                );
              })}
              {events.length === 0 && <div style={{color:'var(--fg-dim)',fontSize:'11px'}}>no recent public events</div>}
            </div>
          </div>
        </div>
      </div>
    </div>
  );
}

function Tweaks() {
  const [open, setOpen] = useState(false);
  const [bg, setBg] = useState(() => localStorage.getItem('bg_mode') || 'matrix');
  const [color, setColor] = useState(() => localStorage.getItem('accent') || '#00ff9c');

  useEffect(() => {
    const onMsg = (e) => {
      if (e.data && e.data.type === '__activate_edit_mode') setOpen(true);
      if (e.data && e.data.type === '__deactivate_edit_mode') setOpen(false);
    };
    window.addEventListener('message', onMsg);
    try { window.parent.postMessage({type: '__edit_mode_available'}, '*'); } catch {}
    const onKey = (e) => {
      if (e.key === 't' && !/(INPUT|TEXTAREA)/.test(document.activeElement.tagName)) {
        setOpen(v => !v);
      }
      if (e.key === '/' && !/(INPUT|TEXTAREA)/.test(document.activeElement.tagName)) {
        e.preventDefault();
        const inp = document.querySelector('.terminal .cmd');
        if (inp) inp.focus();
      }
    };
    window.addEventListener('keydown', onKey);
    return () => { window.removeEventListener('message', onMsg); window.removeEventListener('keydown', onKey); };
  }, []);

  const setBgMode = (m) => {
    setBg(m);
    window.setBgMode(m);
    try { window.parent.postMessage({type:'__edit_mode_set_keys', edits:{bg: m}},'*'); } catch {}
  };
  const setAcc = (c) => {
    setColor(c);
    window.setAccentColor(c);
    try { window.parent.postMessage({type:'__edit_mode_set_keys', edits:{accent: c}},'*'); } catch {}
  };

  return (
    <div className={"tweaks " + (open ? 'active' : '')}>
      <div className="tweaks-head">
        <span># tweaks</span>
        <span style={{cursor:'none', color:'var(--fg-dim)'}} onClick={()=>setOpen(false)}>[x]</span>
      </div>
      <div className="tweaks-body">
        <div className="tw-row">
          <div className="lbl">background</div>
          <div className="tw-opts">
            {['matrix','particles','grid','off'].map(m => (
              <button key={m} className={"tw-opt " + (bg===m?'on':'')} onClick={()=>setBgMode(m)}>{m}</button>
            ))}
          </div>
        </div>
        <div className="tw-row">
          <div className="lbl">accent</div>
          <div className="tw-swatches">
            {['#00ff9c','#00e5ff','#ff3cac','#ffee00','#b388ff','#ff7e36'].map(c => (
              <div key={c} className={"tw-sw " + (color===c?'on':'')} style={{background:c, color:c}} onClick={()=>setAcc(c)}></div>
            ))}
          </div>
        </div>
        <div style={{fontSize:'10px', color:'var(--fg-dim)', letterSpacing:'0.08em'}}>
          also available via terminal: <span style={{color:'var(--accent)'}}>theme</span> · <span style={{color:'var(--accent)'}}>matrix</span>
        </div>
      </div>
    </div>
  );
}

function App({ ascii }) {
  return (
    <>
      <StatusBar />
      <Hero ascii={ascii} />
      <div className="sec">
        <SectionHeader cmd="./shell --interactive" />
        <Terminal />
      </div>
      <About />
      <Projects />
      <Skills />
      <GitHub />
      <div className="footer">
        <span>© 2026 varad raj agrawal · built with html, sweat & npm</span>
        <span>last_deploy: {new Date().toISOString().slice(0,10)} · status: alive</span>
      </div>
      <Tweaks />
    </>
  );
}

window.App = App;
