import React, { useCallback, useEffect, useState } from 'react';
import { api } from './api.js';
import { copyToast } from './toast.js';
import Netdisk from './Netdisk.jsx';

// amerc Mansion — a hall of amerc services. First live service: Showcase (reverse proxy).
export default function Mansion({ auth, setRoute }) {
  if (!auth.ready) return <div className="ap"><p>Loading…</p></div>;
  const loggedIn = !!auth.user;
  const handle = loggedIn ? auth.user.handle.toLowerCase().replace(/[^a-z0-9]/g, '') : 'you';
  return (
    <div className="ap mn">
      <header className="mn-villa">
        <div className="mn-villa-scene" aria-hidden="true">
          <span className="mn-villa-moon" />
          <span className="mn-villa-star" style={{ left: '18%', top: '22%' }} />
          <span className="mn-villa-star" style={{ left: '40%', top: '12%' }} />
          <span className="mn-villa-star" style={{ left: '70%', top: '30%' }} />
          <div className="mn-villa-flag"><i /></div>
          <div className="mn-villa-roof" />
          <div className="mn-villa-house">
            <div className="mn-villa-windows">
              {Array.from({ length: 6 }).map((_, i) => <span key={i} className={`mn-win${i === 4 ? ' dark' : ''}`} style={{ animationDelay: `${i * 0.4}s` }} />)}
            </div>
            <div className="mn-villa-door" />
          </div>
          <div className="mn-villa-hedge" />
        </div>
        <div className="mn-villa-body">
          <span className="mn-villa-tag">🏰 THE ESTATE</span>
          <h2>My Mansion</h2>
          <p>Your estate on the open internet — a villa of amerc services, each room brought to life by your own broker. No servers to rent, no ports to forward.</p>
          {loggedIn
            ? <span className="mn-hero-you"><i className="mn-live-dot" /> {auth.user.handle}'s estate — the gates are open</span>
            : <button className="px-action" onClick={() => setRoute('signin')}>Log in to open the gates →</button>}
        </div>
      </header>

      <h3 className="mn-wing-title">⚜ Chambers of the estate</h3>
      <div className="mn-rooms">
        <ShowcaseRoom loggedIn={loggedIn} handle={handle} setRoute={setRoute} />
        <FileMapperRoom loggedIn={loggedIn} setRoute={setRoute} />
        <NetdiskRoom loggedIn={loggedIn} setRoute={setRoute} />
        <SoonRoom
          ico="🤖" name="Hosted webagent" tag="runtime"
          desc="Let amerc host the broker for you — keep an agent class always-on without leaving your own machine running."
          feats={['always-on instances', 'managed runtime', 'one-click from My Legion']}
        />
      </div>
    </div>
  );
}

function RoomShell({ ico, name, tag, status, desc, feats, children }) {
  return (
    <section className={`mn-room${status === 'live' ? ' live' : ' soon'}`}>
      <div className="mn-room-head">
        <span className="mn-room-ico" aria-hidden="true">{ico}</span>
        <div className="mn-room-titles">
          <strong>{name}</strong>
          <span className="mn-room-tag">{tag}</span>
        </div>
        <span className={`mn-badge ${status}`}>{status === 'live' ? '● LIVE' : 'SOON'}</span>
      </div>
      <p className="mn-room-desc">{desc}</p>
      {feats && <ul className="mn-feats">{feats.map((f) => <li key={f}>{f}</li>)}</ul>}
      {children}
    </section>
  );
}

function SoonRoom(props) {
  return (
    <RoomShell {...props} status="soon">
      <div className="mn-room-foot"><span className="mn-soon-bar"><i /></span>in development</div>
    </RoomShell>
  );
}

// File-mapper: agents publish named files; each download is fetched live from
// the broker and piped through — nothing is ever stored on amerc.
function FileMapperRoom({ loggedIn, setRoute }) {
  const [maps, setMaps] = useState(null);
  const [err, setErr] = useState('');
  useEffect(() => {
    if (!loggedIn) return;
    api('/fm').then((d) => setMaps(d.maps || [])).catch((e) => { setErr(e.message); setMaps([]); });
  }, [loggedIn]);
  return (
    <RoomShell
      ico="🗺️" name="File-mapper" tag="live file links" status="live"
      desc="Your agent maps a file to a stable link; every download streams live through your broker — the server keeps no copy. Perfect for big or fast-changing artifacts."
      feats={['stable public URLs', 'zero server storage', 'served by your own broker']}
    >
      {!loggedIn ? (
        <div className="mn-room-cta"><button className="px-action" onClick={() => setRoute('signin')}>Log in to see your mapped files →</button></div>
      ) : (
        <>
          {err && <p className="px-auth-err">{err}</p>}
          <div className="mn-mine">
            <h4 className="ap-h4">My mapped files</h4>
            {maps === null ? <p className="ap-hint">loading…</p> : maps.length ? maps.map((f) => (
              <div key={f.id} className="mn-row">
                <span className={`ch-dot ${f.inst_status}`} title={`instance ${f.inst_status}`} />
                <a href={f.url} target="_blank" rel="noreferrer">{f.name}</a>
                <span className="mn-fm-meta">{f.class_name || `instance #${f.instance_id}`}</span>
                <button className="px-action" onClick={() => copyToast(f.url, 'Link copied')}>copy link</button>
              </div>
            )) : <p className="ap-hint">No mapped files yet. Your broker registers one with <code>POST /api/agents/instances/&lt;id&gt;/fm</code> {'{accesskey, name, fileName, size, mime}'} — it becomes a stable link instantly.</p>}
          </div>
        </>
      )}
    </RoomShell>
  );
}

// Net-disk: real storage on amerc, 100 MB per account.
function NetdiskRoom({ loggedIn, setRoute }) {
  const [usage, setUsage] = useState(null);
  const [open, setOpen] = useState(false);
  useEffect(() => { if (loggedIn) api('/files/usage').then(setUsage).catch(() => {}); }, [loggedIn, open]);
  const pct = usage ? Math.min(100, Math.round((usage.used / usage.quota) * 100)) : 0;
  return (
    <RoomShell
      ico="🗄️" name="Net-disk" tag="storage" status="live"
      desc="Safe keeping on amerc itself — upload files and notes, edit text in place, share by link. Each account gets 100 MB."
      feats={['100 MB per account', 'stored on amerc (the safe option)', 'agents read/write it via API key']}
    >
      {!loggedIn ? (
        <div className="mn-room-cta"><button className="px-action" onClick={() => setRoute('signin')}>Log in to open your net-disk →</button></div>
      ) : (
        <>
          {usage && (
            <div className="mn-quota" title={`${(usage.used / 1048576).toFixed(1)} MB of 100 MB used`}>
              <span className="mn-quota-bar"><i style={{ width: `${pct}%`, background: pct > 90 ? '#ff7a8c' : undefined }} /></span>
              <span className="mn-quota-label">{(usage.used / 1048576).toFixed(1)} / 100 MB</span>
            </div>
          )}
          <button className="px-action" onClick={() => setOpen((v) => !v)}>{open ? 'Close net-disk' : 'Open net-disk'}</button>
          {open && <div className="mn-nd"><Netdisk /></div>}
        </>
      )}
    </RoomShell>
  );
}

function ShowcaseRoom({ loggedIn, handle, setRoute }) {
  const [list, setList] = useState([]);
  const [name, setName] = useState('');
  const [created, setCreated] = useState(null);
  const [err, setErr] = useState('');
  const [loaded, setLoaded] = useState(false);
  const load = useCallback(async () => {
    if (!loggedIn) return;
    try { const d = await api('/showcase'); setList(d.showcases || []); } catch (e) { setErr(e.message); } finally { setLoaded(true); }
  }, [loggedIn]);
  useEffect(() => { load(); }, [load]);
  const register = async (e) => {
    e.preventDefault(); setErr('');
    try { const r = await api('/showcase', { method: 'POST', body: { name } }); setCreated(r); setName(''); load(); }
    catch (e2) { setErr(e2.message); }
  };
  const del = async (id) => { if (!window.confirm('Delete this showcase?')) return; try { await api(`/showcase/${id}`, { method: 'DELETE' }); load(); } catch (e2) { setErr(e2.message); } };

  return (
    <RoomShell
      ico="🌐" name="Showcase" tag="reverse proxy" status="live"
      desc="Publish a web service from a local port to a public subdomain. Register a name, then map your local port in kebab's delivery center (交付中心) — requests to the public URL tunnel through your broker, TLS included."
      feats={['your own *.amerc.ai subdomain', 'automatic HTTPS', 'HTTP + WebSocket tunneling']}
    >
      {!loggedIn ? (
        <div className="mn-room-cta">
          <div className="mn-url-preview"><span>show1</span>.{handle}.amerc.ai</div>
          <button className="px-action" onClick={() => setRoute('signin')}>Log in to claim a subdomain →</button>
        </div>
      ) : (
        <>
          <form className="mn-reg" onSubmit={register}>
            <span className="mn-prefix">register</span>
            <input placeholder="show1" value={name} onChange={(e) => setName(e.target.value.toLowerCase().replace(/[^a-z0-9-]/g, ''))} required />
            <span className="mn-suffix">.{handle}.amerc.ai</span>
            <button className="px-action px-auth-submit" type="submit">Register</button>
          </form>
          {err && <p className="px-auth-err">{err}</p>}
          {created && (
            <div className="mn-created">
              <p>✅ <b>{created.host}</b> reserved · DNS {created.dns}</p>
              {created.tls && <p className="ap-hint">🔒 {created.tls}</p>}
              <label className="ap-field">public URL<code className="ap-token" onClick={() => copyToast(created.url)}>{created.url} ⧉</code></label>
              <label className="ap-field">broker WS (kebab connects here)<code className="ap-token" onClick={() => copyToast(created.edgeWs)}>{created.edgeWs} ⧉</code></label>
              <label className="ap-field">edge token (bind {created.host})<code className="ap-token" onClick={() => copyToast(created.edgeToken)}>{created.edgeToken.slice(0, 28)}… ⧉</code></label>
              <p className="ap-hint">In the kebab delivery center: connect a broker to the WS with this token, send <code>{`{type:"bind",host:"${created.host}",port:<localPort>}`}</code>, and your local service is live at the public URL.</p>
            </div>
          )}
          <div className="mn-mine">
            <h4 className="ap-h4">My showcases</h4>
            {!loaded ? (
              <div className="mn-skel" aria-hidden="true">
                <div className="ap-skel-row"><span className="sk-p" style={{ flex: 1 }} /></div>
                <div className="ap-skel-row"><span className="sk-p" style={{ flex: 1 }} /></div>
              </div>
            ) : (
              <>
                {list.map((s) => (
                  <div key={s.id} className="mn-row">
                    <a href={`https://${s.host}/`} target="_blank" rel="noreferrer">{s.host}</a>
                    <span>registered {new Date(s.created_at).toLocaleDateString()}</span>
                    <button className="px-action" onClick={() => del(s.id)}>delete</button>
                  </div>
                ))}
                {!list.length && <p className="ap-hint">No showcases yet — register one above.</p>}
              </>
            )}
          </div>
        </>
      )}
    </RoomShell>
  );
}
