import browser from 'webextension-polyfill';
import { autoResumeLabel, attemptSummary, policyLabel, workerSecondaryName } from './presentation.js';
import { UI_MESSAGE_KIND, type ContinuityUiSnapshot, type ContinuityWorkerView, type UiAction } from './ui-model.js';

function byId<T extends HTMLElement>(id: string): T {
  const element = document.getElementById(id);
  if (!element) throw new Error(`Missing popup element #${id}.`);
  return element as T;
}

async function performAction(action: UiAction, worker: ContinuityWorkerView, enabled?: boolean): Promise<void> {
  if (action === 'stop' && !window.confirm(`Stop ${worker.label}? This interrupts the logical worker. Pause only disables continuation.`)) return;
  const response = await browser.runtime.sendMessage({
    kind: UI_MESSAGE_KIND,
    action,
    workerId: worker.workerId,
    ...(action === 'set-auto-resume' ? { enabled: Boolean(enabled) } : {}),
  }) as { ok?: boolean; error?: string };
  const status = byId<HTMLElement>('action-status');
  status.textContent = response?.ok ? 'Control updated by the orchestrator backend.' : response?.error ?? 'The control could not be applied.';
  if (response?.ok) await render();
}

function actionButton(label: string, action: UiAction, worker: ContinuityWorkerView, enabled?: boolean): HTMLButtonElement {
  const button = document.createElement('button');
  button.type = 'button';
  button.textContent = label;
  button.className = action === 'stop' ? 'secondary destructive' : 'secondary';
  button.disabled = !worker.controlAvailable || (action === 'set-auto-resume' && worker.policyMode === null);
  if (button.disabled) button.title = 'Backend continuity controls are unavailable for this worker.';
  button.addEventListener('click', () => { void performAction(action, worker, enabled); });
  return button;
}

function workerRow(worker: ContinuityWorkerView): HTMLLIElement {
  const item = document.createElement('li');
  item.className = 'worker-row';

  const heading = document.createElement('div');
  heading.className = 'worker-heading';
  const names = document.createElement('div');
  names.className = 'worker-names';
  const name = document.createElement('strong');
  name.textContent = worker.label;
  names.append(name);
  const secondaryName = workerSecondaryName(worker);
  if (secondaryName) {
    const hierarchy = document.createElement('span');
    hierarchy.className = 'hierarchy';
    hierarchy.textContent = secondaryName;
    names.append(hierarchy);
  }
  const state = document.createElement('span');
  state.className = 'status-label';
  state.textContent = worker.statusLabel;
  heading.append(names, state);

  const meta = document.createElement('p');
  meta.textContent = attemptSummary(worker);
  const policy = document.createElement('p');
  policy.className = 'policy-line';
  policy.textContent = policyLabel(worker);

  const actions = document.createElement('div');
  actions.className = 'row-actions';
  actions.append(actionButton('Pause', 'pause', worker));

  item.append(heading, meta, policy, actions);
  return item;
}

function renderCurrent(worker: ContinuityWorkerView | null): void {
  const section = byId<HTMLElement>('current-worker');
  const empty = byId<HTMLElement>('current-empty');
  const content = byId<HTMLElement>('current-content');
  if (!worker) {
    empty.hidden = false;
    content.hidden = true;
    section.setAttribute('data-controllable', 'false');
    return;
  }
  empty.hidden = true;
  content.hidden = false;
  byId<HTMLElement>('current-name').textContent = worker.label;
  const hierarchy = workerSecondaryName(worker);
  byId<HTMLElement>('current-hierarchy').textContent = hierarchy ?? '';
  byId<HTMLElement>('current-hierarchy').hidden = hierarchy === null;
  byId<HTMLElement>('current-status').textContent = worker.statusLabel;
  byId<HTMLElement>('current-attempt').textContent = attemptSummary(worker);
  byId<HTMLElement>('current-policy').textContent = policyLabel(worker);
  const actions = byId<HTMLElement>('current-actions');
  actions.replaceChildren(
    actionButton('Pause', 'pause', worker),
    actionButton('Continue now', 'continue-now', worker),
    actionButton(worker.policyMode === 'auto' ? 'Disable Auto Resume' : 'Enable Auto Resume', 'set-auto-resume', worker, worker.policyMode !== 'auto'),
    actionButton('Stop worker', 'stop', worker),
  );
  section.setAttribute('data-controllable', String(worker.controlAvailable));
}

async function snapshot(): Promise<ContinuityUiSnapshot> {
  const tabs = await browser.tabs.query({ active: true, currentWindow: true });
  const tabId = tabs[0]?.id;
  return browser.runtime.sendMessage({ kind: UI_MESSAGE_KIND, action: 'snapshot', ...(tabId === undefined ? {} : { tabId }) }) as Promise<ContinuityUiSnapshot>;
}

async function render(): Promise<void> {
  const view = await snapshot();
  const connection = byId<HTMLElement>('connection');
  connection.textContent = view.connection?.state === 'connected' ? 'Live' : view.connection?.state ?? 'Offline';
  connection.dataset.state = view.connection?.state ?? 'unknown';
  byId<HTMLElement>('auto-resume-state').textContent = autoResumeLabel(view.autoResume);
  byId<HTMLElement>('active-count').textContent = String(view.counts.active);
  byId<HTMLElement>('working-count').textContent = String(view.counts.working);
  byId<HTMLElement>('resuming-count').textContent = String(view.counts.resuming);
  byId<HTMLElement>('needs-you-count').textContent = String(view.counts.needsUser);

  const list = byId<HTMLUListElement>('worker-list');
  list.replaceChildren();
  if (view.workers.length === 0) {
    const empty = document.createElement('li');
    empty.className = 'empty';
    empty.textContent = 'No managed workers in this browser.';
    list.append(empty);
  } else {
    for (const worker of view.workers) list.append(workerRow(worker));
  }
  renderCurrent(view.currentWorker);
}

byId<HTMLButtonElement>('dashboard').addEventListener('click', () => {
  void browser.tabs.create({ url: browser.runtime.getURL('dashboard.html') });
});
byId<HTMLButtonElement>('settings').addEventListener('click', () => { void browser.runtime.openOptionsPage(); });
browser.storage.onChanged.addListener(() => { void render(); });
void render().catch((error) => {
  byId<HTMLElement>('action-status').textContent = error instanceof Error ? error.message : 'Execution Continuity state could not be loaded.';
});
