(function (root, factory) {
  const api = factory();
  if (typeof module === 'object' && module.exports) module.exports = api;
  else root.createTodayReadiness = api;
})(typeof globalThis !== 'undefined' ? globalThis : this, function () {
  'use strict';

  return function createTodayReadiness({ inspect, onOpen = () => {}, onGate = () => {}, onPreview = () => {} }) {
    let pending = null;
    let generation = 0;

    async function classify(item) {
      if (item?.kind !== 'issue') return { status:'ready', dependencies:[] };
      try {
        const detail = await inspect(item);
        if (detail?.available !== true) return { status:'unknown', dependencies:[] };
        const dependencies = Array.isArray(detail.dependencies)
          ? detail.dependencies.filter(dependency => dependency?.state === 'open')
          : [];
        return { status:dependencies.length ? 'blocked' : 'ready', dependencies };
      } catch (_error) {
        return { status:'unknown', dependencies:[] };
      }
    }

    async function run(action, items, target = null) {
      const request = ++generation;
      const ordered = Array.isArray(items) ? items.slice() : [];
      const preferred = target || ordered[0] || null;
      if (!preferred) return 'empty';
      const preferredIndex = ordered.indexOf(preferred);
      const candidates = preferredIndex >= 0
        ? ordered.slice(preferredIndex).concat(ordered.slice(0, preferredIndex))
        : [preferred].concat(ordered);
      const targetState = { item:preferred, ...(await classify(preferred)) };
      if (request !== generation) return 'superseded';
      if (targetState.status === 'ready') {
        pending = null;
        onOpen(action, preferred);
        return 'opened';
      }
      const fallbackStates = await Promise.all(candidates.slice(1).map(async item => ({
        item,
        ...(await classify(item)),
      })));
      const states = [targetState, ...fallbackStates];
      if (request !== generation) return 'superseded';
      const nextReadyState = states.slice(1).find(state => state.status === 'ready');
      pending = {
        action,
        items:ordered,
        target:preferred,
        status:targetState.status,
        dependencies:targetState.dependencies,
        nextReady:nextReadyState?.item || null,
      };
      onGate({ ...pending, items:pending.items.slice() });
      return 'gated';
    }

    function open(item) {
      if (!pending || !item) return false;
      const action = pending.action;
      pending = null;
      generation += 1;
      onOpen(action, item);
      return true;
    }

    function previewBlocker(blocker) {
      if (!pending || !blocker) return false;
      const current = pending.dependencies.find(dependency =>
        dependency?.repository === blocker.repository && Number(dependency?.number) === Number(blocker.number)
      );
      if (!current) return false;
      onPreview(current);
      return true;
    }

    return {
      run,
      retry: () => pending ? run(pending.action, pending.items, pending.target) : Promise.resolve('closed'),
      previewBlocker,
      startNextReady: () => open(pending?.nextReady),
      workAnyway: () => open(pending?.target),
      cancel() {
        generation += 1;
        pending = null;
      },
      snapshot: () => pending ? { ...pending, items:pending.items.slice() } : { open:false },
    };
  };
});
