/**
 * Git Board — Surface Entry Point
 *
 * Kanban board for Gitea/GitHub issues and PRs.
 * Calls Starlark backend via /s/git-board/api/*.
 * Per-user API token via extension settings.
 */
(async function () {
  'use strict';

  var mount = document.getElementById('extension-mount');
  if (!mount) return;

  var base = window.__BASE__ || '';
  var ver  = window.__VERSION__ || '0';
  var slug = 'git-board';

  // ── Boot SDK ───────────────────────────────
  try {
    if (!window.preact) {
      var { h, render } = await import(base + '/js/sw/vendor/preact.module.js');
      var hooksModule   = await import(base + '/js/sw/vendor/hooks.module.js');
      var htmModule     = await import(base + '/js/sw/vendor/htm.module.js');
      window.preact = { h, render };
      window.hooks  = hooksModule;
      window.html   = htmModule.default.bind(h);
    }
    var sdk = await import(base + '/js/sw/sdk/index.js?v=' + ver);
    await sdk.boot();
  } catch (e) {
    mount.innerHTML = '<p style="color:var(--danger);padding:24px;">SDK boot failed: ' + e.message + '</p>';
    return;
  }

  var { html } = window;
  var { useState, useEffect, useCallback, useRef } = hooks;
  var { render } = preact;

  var API = base + '/s/' + slug + '/api';

  async function api(path) {
    var token = sw.auth._getToken();
    var resp = await fetch(API + path, {
      headers: { 'Authorization': 'Bearer ' + token }
    });
    var text = await resp.text();
    try { return JSON.parse(text); } catch (_) { return { error: text }; }
  }

  // ── App ────────────────────────────────────

  function App() {
    var [owner, setOwner]   = useState('');
    var [repo, setRepo]     = useState('');
    var [repos, setRepos]   = useState([]);
    var [board, setBoard]   = useState(null);
    var [loading, setLoading] = useState(false);
    var [needsToken, setNeedsToken] = useState(false);
    var menuRef = useRef(null);

    // Mount user menu
    useEffect(function () {
      if (menuRef.current && sw.userMenu) {
        sw.userMenu(menuRef.current, { placement: 'down-right' });
      }
    }, []);

    // Load repos on mount
    useEffect(function () {
      api('/repos').then(function (d) {
        if (d.error && d.error.indexOf('failed') !== -1) {
          setNeedsToken(true);
          return;
        }
        setRepos(d.data || []);
        if (d.data && d.data.length > 0 && !owner) {
          setOwner(d.data[0].owner);
          setRepo(d.data[0].name);
        }
      });
    }, []);

    var loadBoard = useCallback(function () {
      if (!owner || !repo) return;
      setLoading(true);
      api('/board?owner=' + encodeURIComponent(owner) + '&repo=' + encodeURIComponent(repo))
        .then(function (d) {
          if (d.error) {
            sw.toast(d.error, 'error');
            if (d.error.indexOf('failed') !== -1) setNeedsToken(true);
          } else {
            setBoard(d);
            setNeedsToken(false);
          }
          setLoading(false);
        });
    }, [owner, repo]);

    useEffect(function () { loadBoard(); }, [loadBoard]);

    if (needsToken) return html`
      <${TokenSetup} menuRef=${menuRef} />
    `;

    return html`
      <div class="gb-shell">
        <header class="gb-header">
          <div class="gb-header__left">
            <h1 class="gb-title">Git Board</h1>
            <${RepoPicker} repos=${repos} owner=${owner} repo=${repo}
                           onSelect=${function (o, r) { setOwner(o); setRepo(r); }} />
          </div>
          <div class="gb-header__right">
            <button class="btn-small" onClick=${loadBoard} disabled=${loading}>
              ${loading ? '↻' : 'Refresh'}
            </button>
            <div ref=${menuRef}></div>
          </div>
        </header>

        ${board ? html`<${Board} data=${board} />` : html`
          <div class="gb-empty">${loading ? 'Loading…' : 'Select a repository'}</div>
        `}
      </div>
    `;
  }

  // ── Token Setup ────────────────────────────

  function TokenSetup({ menuRef }) {
    var [token, setToken] = useState('');
    var [saving, setSaving] = useState(false);

    async function save() {
      if (!token.trim()) return;
      setSaving(true);
      try {
        await sw.api.extensions.updateUserSettings('git-board', { api_token: token.trim() });
        sw.toast('Token saved — reloading', 'success');
        setTimeout(function () { location.reload(); }, 500);
      } catch (e) {
        sw.toast(e.message || 'Failed to save', 'error');
        setSaving(false);
      }
    }

    return html`
      <div class="gb-shell">
        <header class="gb-header">
          <div class="gb-header__left"><h1 class="gb-title">Git Board</h1></div>
          <div class="gb-header__right"><div ref=${menuRef}></div></div>
        </header>
        <div class="gb-setup">
          <h2>Connect Your Account</h2>
          <p>Enter your personal access token for Gitea or GitHub.<br/>
             The admin configures the platform URL. You provide your own token.</p>
          <div class="gb-setup__form">
            <input type="password" class="gb-setup__input"
                   placeholder="ghp_... or gitea token"
                   value=${token} onInput=${function (e) { setToken(e.target.value); }} />
            <button class="btn-small btn-primary" onClick=${save} disabled=${saving || !token.trim()}>
              ${saving ? 'Saving…' : 'Save Token'}
            </button>
          </div>
          <p class="gb-setup__hint">Token is stored in your personal extension settings — not shared with other users.</p>
        </div>
      </div>
    `;
  }

  // ── Repo Picker ────────────────────────────

  function RepoPicker({ repos, owner, repo, onSelect }) {
    var current = owner + '/' + repo;
    return html`
      <select class="gb-repo-picker" value=${current}
              onChange=${function (e) {
                var parts = e.target.value.split('/');
                onSelect(parts[0], parts.slice(1).join('/'));
              }}>
        ${repos.map(function (r) {
          return html`<option key=${r.full_name} value=${r.full_name}>${r.full_name}</option>`;
        })}
      </select>
    `;
  }

  // ── Kanban Board ───────────────────────────

  var COLUMNS = [
    { key: 'open',        title: 'Open',        filter: function (i) { return i.state === 'open'; } },
    { key: 'in_progress', title: 'In Progress',  filter: function (i) { return i.assignee && i.state === 'open'; } },
    { key: 'prs',         title: 'Pull Requests', isPR: true },
    { key: 'closed',      title: 'Done',         filter: function (i) { return i.state === 'closed'; } },
  ];

  function Board({ data }) {
    var issues = data.issues || [];
    var prs    = data.pull_requests || [];

    // Split issues: unassigned open vs assigned open
    var openUnassigned = issues.filter(function (i) { return i.state === 'open' && !i.assignee; });
    var inProgress     = issues.filter(function (i) { return i.state === 'open' && !!i.assignee; });

    return html`
      <div class="gb-board">
        <${Column} title="Open" count=${openUnassigned.length}>
          ${openUnassigned.map(function (i) { return html`<${IssueCard} key=${i.number} issue=${i} />`; })}
        <//>
        <${Column} title="In Progress" count=${inProgress.length}>
          ${inProgress.map(function (i) { return html`<${IssueCard} key=${i.number} issue=${i} />`; })}
        <//>
        <${Column} title="Pull Requests" count=${prs.length}>
          ${prs.map(function (p) { return html`<${PRCard} key=${p.number} pr=${p} />`; })}
        <//>
      </div>
    `;
  }

  function Column({ title, count, children }) {
    return html`
      <div class="gb-column">
        <div class="gb-column__header">
          <span class="gb-column__title">${title}</span>
          <span class="gb-column__count">${count || 0}</span>
        </div>
        <div class="gb-column__cards">${children}</div>
      </div>
    `;
  }

  function IssueCard({ issue }) {
    return html`
      <a class="gb-card" href=${issue.html_url} target="_blank" rel="noopener">
        <div class="gb-card__header">
          <span class="gb-card__number">#${issue.number}</span>
          ${issue.assignee && html`<span class="gb-card__assignee">@${esc(issue.assignee)}</span>`}
        </div>
        <div class="gb-card__title">${esc(issue.title)}</div>
        <div class="gb-card__labels">
          ${(issue.labels || []).map(function (l) {
            return html`<span key=${l} class="badge">${esc(l)}</span>`;
          })}
        </div>
      </a>
    `;
  }

  function PRCard({ pr }) {
    return html`
      <a class="gb-card gb-card--pr" href=${pr.html_url} target="_blank" rel="noopener">
        <div class="gb-card__header">
          <span class="gb-card__number">#${pr.number}</span>
          <span class="gb-card__branch">${esc(pr.head)} → ${esc(pr.base)}</span>
        </div>
        <div class="gb-card__title">${esc(pr.title)}</div>
        <div class="gb-card__meta">
          <span>@${esc(pr.user)}</span>
          <span>${timeAgo(pr.created_at)}</span>
        </div>
      </a>
    `;
  }

  // ── Utilities ──────────────────────────────

  function esc(s) {
    var el = document.createElement('span');
    el.textContent = String(s || '');
    return el.innerHTML;
  }

  function timeAgo(iso) {
    if (!iso) return '';
    var sec = Math.floor((Date.now() - new Date(iso).getTime()) / 1000);
    if (sec < 60) return 'now';
    var min = Math.floor(sec / 60);
    if (min < 60) return min + 'm';
    var hr = Math.floor(min / 60);
    if (hr < 24) return hr + 'h';
    return Math.floor(hr / 24) + 'd';
  }

  // ── Mount ──────────────────────────────────
  render(html`<${App} />`, mount);
  console.log('[git-board] Surface mounted');
})();
