// Sidebar — primary navigation with workflow ordering.

const NAV = [
  { key: 'dashboard', label: 'Dashboard',       icon: 'home',     stepNum: null },
  // Pipeline board hidden for now — not fully developed; re-add when ready.
  { key: 'intake',    label: 'News Intake',     icon: 'inbox',    stepNum: 1 },
  { key: 'research',  label: 'Brand Research',  icon: 'beaker',   stepNum: 2 },
  { key: 'match',     label: 'Property Match',  icon: 'link',     stepNum: 3 },
  { key: 'contacts',  label: 'Contacts',        icon: 'users',    stepNum: 4 },
  { key: 'draft',     label: 'Draft Review',    icon: 'mail',     stepNum: 5 },
];

const NAV_WORKSPACE = [
  { key: 'notifications', label: 'Notifications',  icon: 'bell' },
  { key: 'notes',         label: 'Notes & Actions', icon: 'edit' },
];

const NAV_LIBRARY = [
  { key: 'properties', label: 'Properties',       icon: 'trophy' },
  { key: 'deals',      label: 'Sponsorship Data', icon: 'trend' },
  { key: 'howto',      label: 'How To',           icon: 'info' },
];

function Sidebar({ active, onNavigate, counts, onLogout, user, onUpdateProfile, theme, onToggleTheme }) {
  const [editing, setEditing] = React.useState(false);
  const [schedule, setSchedule] = React.useState(null);
  const [build, setBuild] = React.useState(null);

  // Fetched once — the running build only changes on redeploy, which reloads the page.
  React.useEffect(() => {
    window.IPSEM_API.getVersion().then(setBuild).catch(() => {});
  }, []);

  // Load the auto-scan schedule and refresh it every 5 minutes so the
  // "next run" label never goes stale during a long session.
  React.useEffect(() => {
    const load = () => window.IPSEM_API.getSchedule().then(setSchedule).catch(() => {});
    load();
    const interval = setInterval(load, 300000);
    return () => clearInterval(interval);
  }, []);

  const hasName  = !!(user && user.name);
  const hasTitle = !!(user && user.title);
  // -1 = the reader's calendar day is behind IPSEM's operating day, +1 = ahead.
  const dayDrift = viewerOffsetFromIpsemDay();
  const displayInitials = hasName ? initialsFor(user.name) : 'AS';
  const ThemeIcon = window.I[theme === 'dark' ? 'sun' : 'moon'];

  return (
    <>
      <aside className="sidebar">
        <div className="brandmark">
          <div className="logo">i</div>
          <div className="col" style={{ gap: 0 }}>
            <span className="name">IPSEM</span>
            <span className="sub">Prospecting OS</span>
          </div>
        </div>

        <div className="col gap-1">
          <div className="eyebrow" style={{ padding: '6px 10px 2px' }}>Workflow</div>
          {NAV.map((n) => {
            const Ico = window.I[n.icon];
            return (
              <div
                key={n.key}
                className={`nav-item ${active === n.key ? 'is-active' : ''}`}
                onClick={() => onNavigate(n.key)}
              >
                <Ico className="nav-icon" />
                <span>{n.label}</span>
                {/* A count and a step number are different things and must not
                    look alike. With no count, Brand Research rendered its step
                    number "02" in the same badge and it read as "2 brands". The
                    count is now an accent pill; the step number is dimmed. */}
                {counts && counts[n.key] != null ? (
                  <span className="num num-badge" title={`${counts[n.key]} waiting on you here`}>
                    {counts[n.key]}
                  </span>
                ) : n.stepNum ? (
                  <span className="num" style={{ opacity: 0.4, fontWeight: 400 }} title={`Step ${n.stepNum} of the flow — nothing waiting here`}>
                    0{n.stepNum}
                  </span>
                ) : null}
              </div>
            );
          })}
        </div>

        {counts && counts.total ? (
          <div className="text-xs text-3" style={{ padding: '4px 10px 0' }}>
            {counts.total} tracked · {counts.held || 0} held/closed
          </div>
        ) : null}

        <div className="col gap-1">
          <div className="eyebrow" style={{ padding: '6px 10px 2px' }}>Workspace</div>
          {NAV_WORKSPACE.map((n) => {
            const Ico = window.I[n.icon];
            const count = counts && counts[n.key];
            return (
              <div
                key={n.key}
                className={`nav-item ${active === n.key ? 'is-active' : ''}`}
                onClick={() => onNavigate(n.key)}
              >
                <Ico className="nav-icon" />
                <span>{n.label}</span>
                {count ? (
                  <span className="num num-badge" title={`${count} waiting on you here`}>{count}</span>
                ) : null}
              </div>
            );
          })}
        </div>

        <div className="col gap-1">
          <div className="eyebrow" style={{ padding: '6px 10px 2px' }}>Library</div>
          {NAV_LIBRARY.map((n) => {
            const Ico = window.I[n.icon];
            return (
              <div
                key={n.key}
                className={`nav-item ${active === n.key ? 'is-active' : ''}`}
                onClick={() => onNavigate(n.key)}
              >
                <Ico className="nav-icon" />
                <span>{n.label}</span>
                {counts && counts[n.key] != null ? (
                  <span className="num">{counts[n.key]}</span>
                ) : null}
              </div>
            );
          })}
        </div>

        <div style={{ marginTop: 'auto' }}>
          <div
            style={{
              padding: '12px 12px',
              background: 'var(--card)',
              border: '1px solid var(--hairline)',
              borderRadius: 10,
              fontSize: 12.5,
              lineHeight: 1.5,
              color: 'var(--ink-2)',
            }}
          >
            {/* Scanning is manual. This card used to advertise a 09:30 daily scan
                and a "next run" time, which on the current hosting does not
                reliably fire — so brands appeared to be arriving on their own
                when nothing was coming in. Say what is actually true, and point
                at the button that does the work. */}
            <div className="row gap-2" style={{ marginBottom: 6 }}>
              <window.I.refresh size={14} stroke="var(--pending)" />
              <span style={{ fontWeight: 600, fontSize: 12 }}>Scanning is manual</span>
            </div>
            <div className="text-3 text-xs" style={{ lineHeight: 1.45 }}>
              New brands arrive only when someone runs a scan. Use <strong style={{ color: 'var(--ink-2)' }}>Re-run scan</strong> in
              the top bar — it is on every page.
            </div>
            {schedule && schedule.enabled && schedule.nextRun ? (
              <div className="text-3 text-xs mono" style={{ marginTop: 6, color: 'var(--ink-4)' }}>
                Scheduled {formatNextRun(schedule.nextRun)} · not guaranteed on this hosting
              </div>
            ) : null}
            {/* Which build you are looking at. Hover for when it deployed — after
                a push this is the quickest way to tell "the fix is live" from
                "Render is still deploying the old one". */}
            {build ? (
              <div
                className="text-3 text-xs mono"
                style={{ marginTop: 8, paddingTop: 8, borderTop: '1px solid var(--hairline)', color: 'var(--ink-4)' }}
                title={`Backend started ${build.startedAt ? formatInstant(build.startedAt, viewerTimeZone()) : 'unknown'}${build.branch ? ` · branch ${build.branch}` : ''}`}
              >
                build {build.commit}
              </div>
            ) : null}
            {/* Your zone, and a warning when the office day is not your day. */}
            <div className="text-3 text-xs" style={{ marginTop: 8, paddingTop: 8, borderTop: '1px solid var(--hairline)' }}>
              <div className="row gap-1" style={{ alignItems: 'center' }}>
                <window.I.globe size={11} stroke="var(--ink-3)" />
                <span className="mono">{tzOffsetLabel(viewerTimeZone())}</span>
                <span>· your time</span>
              </div>
              {dayDrift !== 0 ? (
                <div style={{ marginTop: 4, color: 'var(--attention)', lineHeight: 1.45 }}>
                  The IPSEM office day is {dayDrift < 0 ? 'already tomorrow' : 'still yesterday'} where the
                  app counts it. Review and follow-up dates use the office day (GMT+8).
                </div>
              ) : null}
            </div>
          </div>

          <div style={{ paddingTop: 14, borderTop: '1px solid var(--hairline)', marginTop: 14 }}>
            <div
              className="row gap-2"
              style={{ cursor: 'pointer', minWidth: 0, padding: '0 8px' }}
              onClick={() => setEditing(true)}
              title="Edit profile"
            >
              <Avatar initials={displayInitials} />
              <div className="col grow" style={{ gap: 0, lineHeight: 1.2, minWidth: 0 }}>
                <span
                  className="text-sm truncate"
                  style={{ fontWeight: 500, color: hasName ? 'var(--ink)' : 'var(--ink-3)' }}
                >
                  {hasName ? user.name : 'Adrian Smith'}
                </span>
                <span className="text-xs text-3" style={{ whiteSpace: 'normal', lineHeight: 1.35 }}>
                  {hasTitle ? user.title : 'Commercial Advisor'}
                </span>
              </div>
            </div>

            <div className="row gap-2" style={{ marginTop: 12, padding: '0 8px' }}>
              {onToggleTheme ? (
                <button
                  className="btn btn-sm btn-icon"
                  onClick={onToggleTheme}
                  title={theme === 'dark' ? 'Switch to light mode' : 'Switch to dark mode'}
                >
                  {ThemeIcon ? <ThemeIcon size={15} /> : null}
                </button>
              ) : null}
              {onLogout ? (
                <button className="btn btn-sm grow" onClick={onLogout} title="Sign out">
                  Sign out
                </button>
              ) : null}
            </div>
          </div>
        </div>
      </aside>

      {editing ? (
        <ProfileModal
          user={user}
          onSave={onUpdateProfile}
          onClose={() => setEditing(false)}
        />
      ) : null}
    </>
  );
}

// ─── Edit profile modal ──────────────────────────────────────────────────
// Zones the team actually works in, plus the common travel destinations.
// 'auto' follows the browser, which is right for almost everyone almost always.
const TZ_CHOICES = [
  { value: '',                   label: 'Automatic — follow this device' },
  { value: 'Asia/Singapore',     label: 'Singapore / Malaysia (GMT+8) — IPSEM office day' },
  { value: 'Europe/London',      label: 'London (GMT+0, GMT+1 in summer)' },
  { value: 'Europe/Paris',       label: 'Paris / Amsterdam (GMT+1, GMT+2 in summer)' },
  { value: 'Asia/Dubai',         label: 'Dubai (GMT+4)' },
  { value: 'America/New_York',   label: 'New York (GMT-5, GMT-4 in summer)' },
  { value: 'Australia/Sydney',   label: 'Sydney (GMT+10, GMT+11 in summer)' },
  { value: 'UTC',                label: 'UTC' },
];

function ProfileModal({ user, onSave, onClose }) {
  const [name, setName]   = React.useState((user && user.name) || '');
  const [title, setTitle] = React.useState((user && user.title) || '');
  const [tz, setTz]       = React.useState((user && user.timezone) || '');
  const [saving, setSaving] = React.useState(false);
  const [error, setError]   = React.useState('');

  const effectiveTz = tz || browserTimeZone();
  const nowLabel = `${formatInstant(new Date().toISOString(), effectiveTz, { year: undefined })} ${tzOffsetLabel(effectiveTz)}`;

  const handleSave = async () => {
    if (!name.trim()) return;
    setSaving(true);
    setError('');
    try {
      await onSave({ full_name: name.trim(), title: title.trim(), timezone: tz });
      onClose();
    } catch (e) {
      setError('Could not save. Please try again.');
      setSaving(false);
    }
  };

  return (
    <div
      onClick={onClose}
      style={{
        position: 'fixed', inset: 0,
        background: 'rgba(0,0,0,0.35)',
        display: 'flex', alignItems: 'center', justifyContent: 'center',
        zIndex: 100,
      }}
    >
      <div className="card card-pad-lg" onClick={(e) => e.stopPropagation()} style={{ width: 380 }}>
        <div className="row" style={{ justifyContent: 'space-between', marginBottom: 18 }}>
          <h2 className="h2" style={{ margin: 0, fontSize: 18 }}>Edit profile</h2>
          <button className="btn btn-icon btn-ghost" onClick={onClose}>
            <window.I.x size={16} />
          </button>
        </div>

        <div className="col gap-3">
          <div>
            <div className="eyebrow" style={{ marginBottom: 6 }}>Full name</div>
            <div className="field" style={{ height: 40 }}>
              <input
                value={name}
                onChange={(e) => setName(e.target.value)}
                onKeyDown={(e) => { if (e.key === 'Enter') handleSave(); }}
                placeholder="Adrian Smith"
                autoFocus
              />
            </div>
          </div>

          <div>
            <div className="eyebrow" style={{ marginBottom: 6 }}>Title / position</div>
            <div className="field" style={{ height: 40 }}>
              <input
                value={title}
                onChange={(e) => setTitle(e.target.value)}
                onKeyDown={(e) => { if (e.key === 'Enter') handleSave(); }}
                placeholder="Commercial Advisor"
              />
            </div>
          </div>

          <div>
            <div className="eyebrow" style={{ marginBottom: 6 }}>Time zone</div>
            <select
              value={tz}
              onChange={(e) => setTz(e.target.value)}
              className="field"
              style={{ height: 40, padding: '0 10px', fontSize: 13 }}
            >
              {TZ_CHOICES.map((c) => <option key={c.value || 'auto'} value={c.value}>{c.label}</option>)}
            </select>
            <div className="text-xs text-3" style={{ marginTop: 6, lineHeight: 1.5 }}>
              Times on notes and notifications are shown in this zone. Right now that reads{' '}
              <strong>{nowLabel}</strong>.
              {effectiveTz !== IPSEM_TZ ? (
                <> Follow-up and review dates stay on the IPSEM office day (GMT+8).</>
              ) : null}
            </div>
          </div>

          {user && user.email ? (
            <div className="text-xs text-3">Signed in as {user.email}</div>
          ) : null}

          {error ? (
            <div style={{
              background: 'var(--negative-soft)', color: 'var(--negative)',
              padding: '8px 12px', borderRadius: 'var(--radius-sm)', fontSize: 13,
            }}>
              {error}
            </div>
          ) : null}
        </div>

        <div className="row gap-2" style={{ marginTop: 22, justifyContent: 'flex-end' }}>
          <button className="btn" onClick={onClose} disabled={saving}>Cancel</button>
          <button className="btn btn-primary" onClick={handleSave} disabled={saving || !name.trim()}>
            {saving ? 'Saving…' : 'Save'}
          </button>
        </div>
      </div>
    </div>
  );
}

// Format the next-run ISO timestamp as a short local label, e.g. "Mon 09:30".
function formatNextRun(iso) {
  const d = new Date(iso);
  if (isNaN(d.getTime())) return iso;
  return d.toLocaleString('en-GB', { weekday: 'short', hour: '2-digit', minute: '2-digit' });
}

window.Sidebar = Sidebar;
