/**
 * Schedules — Cron Job Management Surface (v0.1.0)
 *
 * Wraps the kernel /api/v1/schedules API. No Starlark backend —
 * this surface talks directly to the core scheduled-tasks endpoints.
 *
 * SDK usage:
 *   sw.shell.Topbar  — standard navigation bar
 *   sw.ui.*          — primitive components
 *   sw.api.*         — raw REST calls to /api/v1/schedules
 */
(async function () {
  'use strict';

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

  var base = window.__BASE__ || '';
  var ver  = window.__VERSION__ || '0';

  // ── 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 } = hooks;
  var { render } = preact;
  var { Button, FormField, Dialog, Spinner, Banner } = sw.ui;
  var Topbar = sw.shell?.Topbar;

  // ── API helpers (core kernel endpoints) ────
  var API = '/api/v1/schedules';

  function apiList()        { return sw.api.get(API); }
  function apiCreate(data)  { return sw.api.post(API, data); }
  function apiUpdate(id, d) { return sw.api.put(API + '/' + id, d); }
  function apiDelete(id)    { return sw.api.del(API + '/' + id); }
  function apiRun(id)       { return sw.api.post(API + '/' + id + '/run', {}); }
  function apiLogs(id)      { return sw.api.get(API + '/' + id + '/logs'); }


  // ═══════════════════════════════════════════
  //  Cron description helper
  // ═══════════════════════════════════════════

  var DAYS = ['Sunday','Monday','Tuesday','Wednesday','Thursday','Friday','Saturday'];

  function describeCron(expr) {
    if (!expr) return '';
    var parts = expr.trim().split(/\s+/);
    if (parts.length !== 5) return expr;

    var min = parts[0], hr = parts[1], dom = parts[2], mon = parts[3], dow = parts[4];

    // Format time
    var timeStr = '';
    if (min !== '*' && hr !== '*') {
      var h = parseInt(hr, 10);
      var m = parseInt(min, 10);
      var ampm = h >= 12 ? 'PM' : 'AM';
      var h12 = h === 0 ? 12 : h > 12 ? h - 12 : h;
      timeStr = h12 + ':' + String(m).padStart(2, '0') + ' ' + ampm;
    }

    // Every N minutes
    if (min.startsWith('*/') && hr === '*' && dom === '*' && mon === '*' && dow === '*') {
      return 'Every ' + min.slice(2) + ' minutes';
    }

    // Every hour at :MM
    if (min !== '*' && hr === '*' && dom === '*' && mon === '*' && dow === '*') {
      return 'Every hour at :' + String(parseInt(min, 10)).padStart(2, '0');
    }

    // Daily
    if (timeStr && dom === '*' && mon === '*' && dow === '*') {
      return 'Daily at ' + timeStr;
    }

    // Weekdays
    if (timeStr && dom === '*' && mon === '*' && dow === '1-5') {
      return 'Weekdays at ' + timeStr;
    }

    // Specific days
    if (timeStr && dom === '*' && mon === '*' && dow !== '*') {
      var dayNames = dow.split(',').map(function(d) {
        var n = parseInt(d, 10);
        return DAYS[n] || d;
      });
      return dayNames.join(', ') + ' at ' + timeStr;
    }

    return expr;
  }


  // ═══════════════════════════════════════════
  //  ScheduleForm — create / edit dialog
  // ═══════════════════════════════════════════

  function ScheduleForm({ schedule, onSave, onClose }) {
    var [name, setName]       = useState(schedule ? schedule.name : '');
    var [desc, setDesc]       = useState(schedule ? schedule.description : '');
    var [cron, setCron]       = useState(schedule ? schedule.cron_expr : '');
    var [script, setScript]   = useState(schedule ? schedule.script : '');
    var [enabled, setEnabled] = useState(schedule ? schedule.enabled : true);
    var [saving, setSaving]   = useState(false);
    var [error, setError]     = useState('');

    var preview = describeCron(cron);

    async function handleSubmit(e) {
      e.preventDefault();
      if (!name.trim()) { setError('Name is required'); return; }
      if (!cron.trim()) { setError('Cron expression is required'); return; }
      setSaving(true);
      setError('');
      try {
        var data = { name: name.trim(), description: desc, cron_expr: cron.trim(), script: script, enabled: enabled };
        if (schedule) {
          await apiUpdate(schedule.id, data);
        } else {
          await apiCreate(data);
        }
        onSave();
      } catch (err) {
        var msg = err.message || 'Save failed';
        if (err.body?.error) msg = err.body.error;
        setError(msg);
      } finally {
        setSaving(false);
      }
    }

    return html`
      <${Dialog} open onClose=${onClose} title=${schedule ? 'Edit Schedule' : 'New Schedule'}>
        <form onSubmit=${handleSubmit} class="sched-form">
          ${error && html`<${Banner} variant="danger" text=${error} />`}
          <${FormField} label="Name" required>
            <input type="text" value=${name} onInput=${e => setName(e.target.value)}
                   placeholder="e.g. Daily cleanup" autofocus />
          <//>
          <${FormField} label="Description">
            <input type="text" value=${desc} onInput=${e => setDesc(e.target.value)}
                   placeholder="What does this job do?" />
          <//>
          <${FormField} label="Cron Expression" required>
            <input type="text" value=${cron} onInput=${e => setCron(e.target.value)}
                   placeholder="e.g. 0 9 * * 1-5" class="sched-cron-input" />
            ${preview && preview !== cron && html`
              <div class="sched-cron-preview">${preview}</div>
            `}
          <//>
          <${FormField} label="Script">
            <textarea rows="6" value=${script} onInput=${e => setScript(e.target.value)}
                      placeholder="Starlark script (optional)" class="sched-script" />
          <//>
          <div class="sched-form__row">
            <label class="sched-toggle">
              <input type="checkbox" checked=${enabled} onChange=${e => setEnabled(e.target.checked)} />
              <span>Enabled</span>
            </label>
          </div>
          <div class="sched-form__actions">
            <${Button} variant="ghost" type="button" onClick=${onClose}>Cancel<//>
            <${Button} variant="primary" type="submit" disabled=${saving}>
              ${saving ? 'Saving…' : (schedule ? 'Update' : 'Create')}
            <//>
          </div>
        </form>
      <//>
    `;
  }


  // ═══════════════════════════════════════════
  //  ScheduleLogsPanel — execution history
  // ═══════════════════════════════════════════

  function ScheduleLogsPanel({ scheduleId, onClose }) {
    var [logs, setLogs]       = useState([]);
    var [loading, setLoading] = useState(true);

    useEffect(function () {
      if (!scheduleId) return;
      setLoading(true);
      apiLogs(scheduleId).then(function (res) {
        setLogs(res.logs || []);
      }).catch(function () {
        setLogs([]);
      }).finally(function () {
        setLoading(false);
      });
    }, [scheduleId]);

    return html`
      <div class="sched-logs">
        <div class="sched-logs__header">
          <span>Execution History</span>
          <button class="sched-btn sched-btn--sm" onClick=${onClose}>Close</button>
        </div>
        ${loading && html`<div class="sched-logs__loading"><${Spinner} size="sm" /></div>`}
        ${!loading && logs.length === 0 && html`
          <div class="sched-logs__empty">No executions yet</div>
        `}
        ${!loading && logs.map(function (log) {
          var success = log.status === 'success' || log.status === 'ok';
          return html`
            <div class="sched-log-entry" key=${log.id || log.started_at}>
              <span class="sched-log-entry__status sched-log-entry__status--${success ? 'ok' : 'fail'}">
                ${success ? '✓' : '✗'}
              </span>
              <span class="sched-log-entry__time">${_formatTime(log.started_at)}</span>
              <span class="sched-log-entry__duration">${_formatDuration(log.duration_ms)}</span>
              ${log.error && html`<span class="sched-log-entry__error" title=${log.error}>${log.error}</span>`}
            </div>
          `;
        })}
      </div>
    `;
  }

  function _formatTime(ts) {
    if (!ts) return '—';
    try {
      return new Date(ts).toLocaleString(undefined, {
        month: 'short', day: 'numeric', hour: '2-digit', minute: '2-digit'
      });
    } catch (_) { return ts; }
  }

  function _formatDuration(ms) {
    if (ms == null) return '';
    if (ms < 1000) return ms + 'ms';
    return (ms / 1000).toFixed(1) + 's';
  }


  // ═══════════════════════════════════════════
  //  ScheduleList — main table
  // ═══════════════════════════════════════════

  function ScheduleList({ items, loading, onEdit, onShowLogs, onRefresh }) {

    async function handleToggle(item) {
      try {
        await apiUpdate(item.id, { enabled: !item.enabled });
        onRefresh();
      } catch (err) {
        sw.toast(err.message || 'Failed to toggle', 'danger');
      }
    }

    async function handleRun(item) {
      try {
        await apiRun(item.id);
        sw.toast('Schedule queued for execution', 'success');
      } catch (err) {
        sw.toast(err.message || 'Run failed', 'danger');
      }
    }

    async function handleDelete(item) {
      if (!confirm('Delete schedule "' + item.name + '"?')) return;
      try {
        await apiDelete(item.id);
        sw.toast('Schedule deleted', 'success');
        onRefresh();
      } catch (err) {
        sw.toast(err.message || 'Delete failed', 'danger');
      }
    }

    return html`
      <div class="sched-list">
        ${loading && html`<div class="sched-list__loading"><${Spinner} size="md" /></div>`}
        ${!loading && items.length === 0 && html`
          <div class="sched-list__empty">No schedules yet. Create one to get started.</div>
        `}
        ${!loading && items.length > 0 && html`
          <table class="sched-table">
            <thead>
              <tr>
                <th>Name</th>
                <th>Schedule</th>
                <th>Next Run</th>
                <th>Enabled</th>
                <th>Actions</th>
              </tr>
            </thead>
            <tbody>
              ${items.map(function (s) {
                return html`
                  <tr key=${s.id} class="sched-row">
                    <td class="sched-row__name">
                      <button class="sched-link" onClick=${() => onEdit(s)}>${s.name}</button>
                      ${s.description && html`<div class="sched-row__desc">${s.description}</div>`}
                    </td>
                    <td class="sched-row__cron">
                      <span class="sched-cron-badge">${s.cron_expr}</span>
                      <div class="sched-cron-human">${describeCron(s.cron_expr)}</div>
                    </td>
                    <td class="sched-row__next">${s.next_fire_at ? _formatTime(s.next_fire_at) : '—'}</td>
                    <td>
                      <button class="sched-toggle-btn sched-toggle-btn--${s.enabled ? 'on' : 'off'}"
                              onClick=${() => handleToggle(s)}
                              title=${s.enabled ? 'Disable' : 'Enable'}>
                        ${s.enabled ? 'On' : 'Off'}
                      </button>
                    </td>
                    <td class="sched-row__actions">
                      <button class="sched-btn sched-btn--sm" onClick=${() => handleRun(s)} title="Run now">▶</button>
                      <button class="sched-btn sched-btn--sm" onClick=${() => onShowLogs(s.id)} title="View logs">📋</button>
                      <button class="sched-btn sched-btn--sm sched-btn--danger" onClick=${() => handleDelete(s)}
                              title="Delete">×</button>
                    </td>
                  </tr>
                `;
              })}
            </tbody>
          </table>
        `}
      </div>
    `;
  }


  // ═══════════════════════════════════════════
  //  ScheduleApp — root component
  // ═══════════════════════════════════════════

  function ScheduleApp() {
    var [items, setItems]       = useState([]);
    var [loading, setLoading]   = useState(true);
    var [error, setError]       = useState('');
    var [editing, setEditing]   = useState(null);   // null=closed, {}=new, {id}=edit
    var [logsFor, setLogsFor]   = useState(null);   // schedule id or null

    var loadItems = useCallback(async function () {
      setLoading(true);
      try {
        var res = await apiList();
        setItems(res.schedules || []);
        setError('');
      } catch (err) {
        setError(err.message || 'Failed to load schedules');
      } finally {
        setLoading(false);
      }
    }, []);

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

    function handleSave() {
      setEditing(null);
      loadItems();
    }

    return html`
      <div class="sched-app">
        ${Topbar ? html`
          <${Topbar} title="Schedules">
            <span class="sched-count">${items.length} schedule${items.length !== 1 ? 's' : ''}</span>
            <${Button} variant="primary" size="sm" onClick=${() => setEditing({})}>+ New Schedule<//>
          <//>
        ` : html`
          <div class="sched-header">
            <h1>Schedules</h1>
            <${Button} variant="primary" size="sm" onClick=${() => setEditing({})}>+ New Schedule<//>
          </div>
        `}

        ${error && html`<${Banner} variant="danger" text=${error} />`}

        <div class="sched-body">
          <${ScheduleList}
            items=${items}
            loading=${loading}
            onEdit=${setEditing}
            onShowLogs=${setLogsFor}
            onRefresh=${loadItems}
          />

          ${logsFor && html`
            <${ScheduleLogsPanel} scheduleId=${logsFor} onClose=${() => setLogsFor(null)} />
          `}
        </div>

        ${editing !== null && html`
          <${ScheduleForm}
            schedule=${editing.id ? editing : null}
            onSave=${handleSave}
            onClose=${() => setEditing(null)}
          />
        `}
      </div>
    `;
  }


  // ── Mount ──────────────────────────────────
  render(html`<${ScheduleApp} />`, mount);

})();
