function createCreateAndStart({ todayWork, todaySync, refresh, warm, start, announce }) {
  const completed = new Set();

  function available() {
    return todayWork.read().length < todayWork.limit;
  }

  function capacity(value) {
    if (String(value ?? '').trim() === '') return { valid: false, reason: 'required' };
    const minutes = Number(value);
    if (!Number.isInteger(minutes) || minutes < 5 || minutes > 1440) {
      return { valid: false, reason: 'range' };
    }
    const plan = todayWork.planning();
    const capacityMinutes = plan.capacity_minutes;
    if (!Number.isInteger(capacityMinutes)) {
      return { valid: true, minutes, capacityMinutes: null, plannedMinutes: null,
        remainingMinutes: null, projectedMinutes: null, fits: true };
    }
    const plannedMinutes = todayWork.read().reduce(
      (total, identity) => total + (Number.isInteger(plan.estimates[identity]) ? plan.estimates[identity] : 0), 0
    );
    const remainingMinutes = capacityMinutes - plannedMinutes;
    const projectedMinutes = remainingMinutes - minutes;
    return { valid: true, minutes, capacityMinutes, plannedMinutes, remainingMinutes,
      projectedMinutes, fits: projectedMinutes >= 0 };
  }

  function capacityMessage(result) {
    if (!result.valid) return result.reason === 'required'
      ? 'Required only for Create & start.'
      : 'Use a whole number from 5 to 1440 minutes.';
    if (result.capacityMinutes === null) {
      return result.minutes + ' min · Set a Today budget to see remaining time.';
    }
    return result.fits
      ? result.minutes + ' min · ' + result.projectedMinutes + ' min will remain in Today.'
      : result.minutes + ' min · ' + Math.abs(result.projectedMinutes) + ' min over Today capacity.';
  }

  function complete(issue, estimateMinutes) {
    const identity = todayWork.identity(issue);
    if (!identity || completed.has(identity)) return 'exists';
    const added = todayWork.add(issue);
    if (added === 'full') {
      announce('Created, but Today changed—remove an item, then add this issue.');
      return 'full';
    }
    if (added !== 'added' && added !== 'exists') {
      announce('Created, but Today could not be saved on this device.');
      return 'unavailable';
    }
    let estimatedPlan = null;
    if (Number.isInteger(estimateMinutes)) {
      estimatedPlan = todayWork.planning();
      estimatedPlan.estimates[identity] = estimateMinutes;
      if (!todayWork.replacePlanning(estimatedPlan)) {
        announce('Created and added to Today, but its estimate could not be saved on this device.');
        return 'estimate-unavailable';
      }
    }
    if (!todaySync.enqueue('add', identity)) {
      announce('Created and saved to Today on this device, but account sync is unavailable.');
      return 'sync-unavailable';
    }
    if (estimatedPlan) {
      if (!todaySync.enqueueConfiguration(estimatedPlan.capacity_minutes, estimatedPlan.estimates)) {
        announce('Created and estimated on this device, but Today plan sync is unavailable.');
        return 'sync-unavailable';
      }
    }
    completed.add(identity);
    refresh();
    todaySync.flush();
    warm();
    start(issue);
    announce('Created, added to Today, and ready to work.');
    return 'started';
  }

  return { available, capacity, capacityMessage, complete };
}

if (typeof module !== 'undefined' && module.exports) module.exports = createCreateAndStart;
