function createSearchWeekPlan({week,claim,accept=item=>item,identity,maxItems=5}={}) {
  let running=null;
  const eligible=detail=>Boolean(detail&&detail.kind==='issue'&&detail.state==='open'&&
    (detail.claimable||detail.assigned_to_me));
  const loadDay=date=>{
    const value=week.day(date),estimates=value.estimates||{};
    return {...value,planned_minutes:(value.ids||[]).reduce((total,id)=>total+(Number(estimates[id])||0),0)};
  };
  async function preview(detail) {
    if(!eligible(detail))return {eligible:false,days:[]};
    await week.load();
    const id=identity(detail),existing=week.placement(id);
    return {eligible:true,existing,days:week.dates().map(item=>({...item,...loadDay(item.date)}))};
  }
  function plan(detail,options={}) {
    if(running)return running;
    const perform=async()=>{
      if(!eligible(detail))return {status:'ineligible'};
      const estimate=Number(options.estimate);
      if(!Number.isFinite(estimate)||estimate<=0)return {status:'estimate-required'};
      await week.load();
      if(!week.dates().some(item=>item.date===options.date))return {status:'date-required'};
      const originalId=identity(detail),existing=week.placement(originalId);
      if(existing&&existing.date!==options.date&&!options.move)
        return {status:'already-planned',date:existing.date,estimate:existing.estimate};
      const destination=loadDay(options.date);
      const alreadyThere=(destination.ids||[]).includes(originalId);
      if(!alreadyThere&&(destination.ids||[]).length>=maxItems)return {status:'day-full',limit:maxItems};
      const previous=alreadyThere?(Number(destination.estimates?.[originalId])||0):0;
      const plannedMinutes=destination.planned_minutes-previous+estimate;
      if(Number(destination.capacity_minutes)>0&&plannedMinutes>Number(destination.capacity_minutes)&&!options.confirmOverload)
        return {status:'overload-confirmation-required',planned_minutes:plannedMinutes,
          capacity_minutes:Number(destination.capacity_minutes)};
      let item=detail,assigned=false;
      if(detail.claimable){item=await claim(detail);assigned=true;}
      item=accept(item)||item;
      const id=identity(item);
      if(!week.place(id,options.date,estimate,{move:Boolean(options.move)}))
        return {status:assigned?'assigned-not-planned':'not-planned',item};
      week.rememberPendingItem?.(id,item);
      try {
        await week.flush();
        return {status:'planned',date:options.date,estimate,item};
      } catch(_error) {
        return {status:'planned-pending',date:options.date,estimate};
      }
    };
    running=perform().finally(()=>{running=null;});
    return running;
  }
  return {eligible,preview,plan,pending:()=>Boolean(running)};
}
function createSearchWeekPlanUI({planner,document,window,getDetail,onPlanned=()=>{},announce=()=>{},escapeHtml,escapeAttribute}={}) {
  const qs=selector=>document.querySelector(selector);
  let trigger=null,detail=null,preview=null,overload=false;
  function close(navigate=false) {
    if(navigate&&window.history.state?.searchWeekPlan){window.history.back();return;}
    qs('#search-week-plan-sheet').hidden=true;
    detail=null;preview=null;overload=false;trigger?.focus?.();trigger=null;
  }
  function selectDate(date) {
    qs('#search-week-plan-days').querySelectorAll('[data-search-week-date]').forEach(button=>
      button.setAttribute('aria-pressed',String(button.dataset.searchWeekDate===date)));
    qs('#search-week-plan-days').dataset.selected=date;
    overload=false;qs('#confirm-search-week-plan').textContent='Plan';
  }
  async function open(button) {
    const selected=getDetail();
    if(!selected||planner.pending())return false;
    trigger=button;detail=selected;overload=false;
    const sheet=qs('#search-week-plan-sheet'),status=qs('#search-week-plan-status');
    sheet.hidden=false;status.textContent='Loading Week Ahead…';qs('#confirm-search-week-plan').disabled=true;
    window.history.pushState({...window.history.state,searchWeekPlan:true},'',window.location.href);
    qs('#search-week-plan-copy').textContent=detail.title||'Untitled issue';
    try {
      preview=await planner.preview(detail);
      const existing=preview.existing;
      qs('#search-week-plan-days').innerHTML=preview.days.map((day,index)=>
        '<button type="button" data-search-week-date="'+escapeAttribute(day.date)+'" aria-pressed="'+String(index===0)+'"><strong>'+escapeHtml(day.label)+
        '</strong><small>'+escapeHtml(day.planned_minutes+(day.capacity_minutes?' of '+day.capacity_minutes:'')+' min · '+day.ids.length+' planned')+'</small></button>').join('');
      qs('#search-week-plan-days').querySelectorAll('[data-search-week-date]').forEach(dayButton=>
        dayButton.addEventListener('click',()=>selectDate(dayButton.dataset.searchWeekDate)));
      selectDate(existing?.date||preview.days[0].date);
      qs('#search-week-plan-estimate').value=existing?.estimate||'';
      status.textContent=existing?'Already planned for '+existing.date+'. Choose another day to move it.':'Choose a day and add an estimate.';
      qs('#confirm-search-week-plan').disabled=false;qs('#search-week-plan-estimate').focus();return true;
    } catch(error) {status.textContent=(error.message||'Week Ahead is unavailable.')+' Retry when connected.';return false;}
  }
  async function confirm() {
    if(!detail||planner.pending())return;
    const date=qs('#search-week-plan-days').dataset.selected,estimate=Number(qs('#search-week-plan-estimate').value);
    const existing=preview?.existing,move=Boolean(existing&&existing.date!==date);
    const button=qs('#confirm-search-week-plan'),status=qs('#search-week-plan-status');button.disabled=true;
    const outcome=await planner.plan(detail,{date,estimate,move,confirmOverload:overload});
    if(outcome.status==='overload-confirmation-required'){
      overload=true;button.textContent='Confirm over capacity';
      status.textContent=outcome.planned_minutes+' min exceeds '+outcome.capacity_minutes+' min capacity. Confirm to plan anyway.';
    } else if(outcome.status==='estimate-required')status.textContent='Enter an estimate in minutes.';
    else if(outcome.status==='day-full')status.textContent='That day already has '+outcome.limit+' items. Choose another day.';
    else if(outcome.status==='already-planned')status.textContent='Already planned for '+outcome.date+'. Choose Move to change the day.';
    else if(outcome.status==='assigned-not-planned')status.textContent='Assigned, not planned. Find it in My Work and retry.';
    else if(outcome.status==='planned-pending'){announce('Planned for '+date+' · sync pending.');onPlanned(detail,true);close(true);}
    else if(outcome.status==='planned'){announce('Planned for '+date+'.');onPlanned(detail,false);close(true);}
    else status.textContent='Could not plan this issue. Retry.';
    button.disabled=false;
  }
  qs('#plan-search-result').addEventListener('click',event=>open(event.currentTarget));
  qs('#cancel-search-week-plan').addEventListener('click',()=>close(true));
  qs('#confirm-search-week-plan').addEventListener('click',confirm);
  window.addEventListener('popstate',()=>{if(!qs('#search-week-plan-sheet').hidden)close();});
  document.addEventListener('keydown',event=>{
    if(event.key==='Escape'&&!qs('#search-week-plan-sheet').hidden){event.preventDefault();close(true);}
  });
  return {open,close,confirm};
}
if(typeof module!=='undefined'&&module.exports){module.exports=createSearchWeekPlan;module.exports.UI=createSearchWeekPlanUI;}