'use strict';

// SiteSight V1.99.6 field/access hardening.
// Load after mobile-v1996.js and the commercial compatibility layer.
(function fieldV1996Compatibility(){
  const esc=value=>typeof v1996Esc==='function'?v1996Esc(value):String(value??'').replace(/[&<>"']/g,char=>({'&':'&amp;','<':'&lt;','>':'&gt;','"':'&quot;',"'":'&#39;'}[char]));
  const permitted=()=>typeof v1996PermittedSiteIds==='function'?v1996PermittedSiteIds():[];
  const findMember=id=>typeof v183Member==='function'?v183Member(id):(db.gangs||[]).flatMap(group=>group.members||[]).find(member=>member.id===id);
  const currentItemActive=item=>!!item&&!item.signed&&!['Complete','Signed Off'].includes(typeof overall==='function'?overall(item):item.status);
  const companyWideAccess=(user=currentUser())=>!!user&&(user.role==='Director'||user.allSitesAccess===true);

  // Current Site designation is deliberately separate from historical records.
  function currentMemberSiteIds(member){
    if(!member)return[];
    const hasExplicit=Array.isArray(member.clockSiteIds)||Array.isArray(member.siteIds);
    const explicit=[...(member.clockSiteIds||[]),...(member.siteIds||[])].filter(Boolean);
    if(hasExplicit)return [...new Set(explicit)];
    const linked=(db.users||[]).find(user=>user.id===member.linkedUserId||user.linkedMemberId===member.id);
    if(linked?.allSitesAccess===true||linked?.role==='Director')return (db.sites||[]).filter(row=>!row.archived).map(row=>row.id);
    if((linked?.allowedSites||[]).length)return [...new Set(linked.allowedSites.filter(Boolean))];
    const ids=new Set();
    for(const item of db.items||[]){
      if(!currentItemActive(item))continue;
      const assigned=item.assignedId===member.id||(item.priceworkAllocations||[]).some(row=>row.memberId===member.id)||(item.lifts||[]).some(lift=>lift.assignedId===member.id||(lift.priceworkAllocations||[]).some(row=>row.memberId===member.id));
      if(assigned&&item.site)ids.add(item.site);
    }
    for(const shift of db.attendanceShifts||[])if(shift.workerId===member.id&&!shift.voided&&!shift.clockOut?.time&&shift.siteId)ids.add(shift.siteId);
    return [...ids];
  }
  window.fieldV1996CurrentMemberSiteIds=currentMemberSiteIds;
  window.v1996MemberSiteIds=currentMemberSiteIds;
  window.v1996CanViewMember=function(member,user=currentUser()){
    if(!member||!user)return false;
    if(user.role==='Director'||user.allSitesAccess===true)return true;
    const allowed=new Set(typeof v1996PermittedSiteIds==='function'?v1996PermittedSiteIds(user,true):(user.allowedSites||[]));
    return currentMemberSiteIds(member).some(id=>allowed.has(id));
  };
  window.v1996MemberMatchesContext=function(member,user=currentUser()){
    return v1996CanViewMember(member,user)&&(site==='all'||currentMemberSiteIds(member).includes(site));
  };
  window.v1996MembersForSite=function(siteId){
    const rows=typeof v1996AllMembers==='function'?v1996AllMembers():(db.gangs||[]).flatMap(group=>(group.members||[]).map(member=>({member,group})));
    return rows.filter(row=>v1996CanViewMember(row.member)&&(siteId==='all'||currentMemberSiteIds(row.member).includes(siteId)));
  };
  if(typeof v194MemberAssignedToSite==='function')window.v194MemberAssignedToSite=(row,siteId)=>currentMemberSiteIds(row?.member).includes(siteId);

  // Admin uses a separate people renderer, so apply the same current-Site
  // scope there instead of relying only on the detail-page guard.
  if(typeof v183AdminIndividuals==='function')window.v183AdminIndividuals=function(){
    const all=v183ActiveMembers().filter(member=>v1996MemberMatchesContext(member)),query=adminSearch.trim().toLowerCase(),people=all.filter(member=>!query||[member.name,member.role,v183MemberUser(member)?.name,v183MemberUser(member)?.role].join(' ').toLowerCase().includes(query));
    return `<div class="card admin-section v183-admin-individuals"><div class="sectionhead"><div><h2>Individuals</h2><div class="muted">People in ${esc(site==='all'?'your permitted Sites':siteName(site))} · ${people.length} shown</div></div><button class="btn orange" onclick="v176NewPerson()">＋ Add Individual</button></div>${adminSearchBox('Search name, trade or linked role…',people.length,all.length)}<div class="v183-admin-people">${people.map(member=>`<button class="v182-admin-person" onclick="openTeamMember('${esc(V183_INDIVIDUALS_ID)}','${esc(member.id)}')"><span><b>${esc(member.name)}</b><small>${esc(member.role||'Individual')} · ${v183MemberUser(member)?'Login linked':'No login linked'}</small></span><strong>Open ›</strong></button>`).join('')||'<div class="admin-no-results">No individuals match this Site view.</div>'}</div></div>`
  };

  // Historic Team archives do not yet carry reliable Site ownership. Keep the
  // company-wide archive away from Site-scoped managers until those IDs exist.
  if(typeof v173CanOpenView==='function'){
    const baseCanOpenView=v173CanOpenView;window.v173CanOpenView=function(target,user=currentUser()){if(target==='workforce-archive'&&!companyWideAccess(user))return false;return baseCanOpenView.call(this,target,user)};
  }
  for(const name of ['v177RestorePerson','v177RestoreTeam']){
    const base=window[name];if(typeof base!=='function')continue;window[name]=function(...args){if(!companyWideAccess())return toast('Former People and Team restoration requires company-wide access');return base.apply(this,args)};
  }
  if(typeof v177ArchiveWorkspace==='function'){
    const baseArchiveWorkspace=v177ArchiveWorkspace;window.v177ArchiveWorkspace=function(...args){if(!companyWideAccess())return '<div class="panel empty-help"><b>Company-wide access is required to open former People and deleted Teams.</b></div>';return baseArchiveWorkspace.apply(this,args)};
  }

  function canManageMemberId(memberId){const member=findMember(memberId);return !!member&&v1996CanViewMember(member)}
  window.fieldV1996CanManageMember=canManageMemberId;
  function guardMemberFunction(name,index){
    const base=window[name];if(typeof base!=='function')return;
    window[name]=function(...args){
      if(!canManageMemberId(args[index]))return toast('This person is outside your Site access');
      return base.apply(this,args);
    };
  }
  [['v176MovePerson',0],['v176DeletePerson',0],['v176SaveUserLink',1],['v176CreateUserForMember',1],['v176SaveUserForMember',1],['v176OpenWorkforceEditor',1],['v176SaveWorkforceEditor',1],['editAttendanceMemberSettings',1],['saveAttendanceMemberSettings',1],['saveTeamMemberRecord',1],['removeTeamMemberPhoto',1],['v172OpenOperativeAccess',1],['v172ApplyAccessLocal',1],['v172SaveOperativeAccess',1]].forEach(([name,index])=>guardMemberFunction(name,index));
  function canManageWholeMember(memberId){
    if(companyWideAccess())return true;
    const member=findMember(memberId),allowed=new Set(permitted()),memberSites=currentMemberSiteIds(member);
    return !!member&&memberSites.length>0&&memberSites.every(id=>allowed.has(id))
  }
  for(const [name,index] of [['v176DeletePerson',0],['v176SaveUserLink',1],['v176CreateUserForMember',1],['v176SaveUserForMember',1]]){
    const base=window[name];if(typeof base!=='function')continue;
    window[name]=function(...args){if(!canManageWholeMember(args[index]))return toast('This person also belongs to a Site outside your access. Ask a Director or company-wide manager to change their login or remove them.');return base.apply(this,args)}
  }

  // Give every newly created person an explicit current Site before the base
  // workflow attempts to reopen that record.
  if(typeof v176NewPerson==='function'){
    const baseNewPerson=v176NewPerson;
    window.v176NewPerson=function(...args){
      const result=baseNewPerson.apply(this,args),box=document.querySelector('.modalbox'),button=box?.querySelector('[onclick*="v176SaveNewPerson"]');
      if(!box||!button||document.getElementById('field-v1996-person-site'))return result;
      const sites=activeSites().filter(row=>canAccessSite(row.id)),chosen=site!=='all'&&canAccessSite(site)?site:(sites[0]?.id||'');
      const field=document.createElement('div');field.className='field';field.innerHTML=`<label for="field-v1996-person-site">Current Site</label><select id="field-v1996-person-site" class="select" ${sites.length===1?'disabled':''}>${sites.map(row=>`<option value="${esc(row.id)}" ${row.id===chosen?'selected':''}>${esc(row.name)}</option>`).join('')}</select><small class="muted">This controls where the person appears now. Historic timesheets remain unchanged.</small>`;
      button.parentNode.insertBefore(field,button);return result;
    };
  }
  if(typeof v176SaveNewPerson==='function'){
    const baseSaveNewPerson=v176SaveNewPerson;
    window.v176SaveNewPerson=function(...args){
      const siteId=document.getElementById('field-v1996-person-site')?.value||(site!=='all'&&canAccessSite(site)?site:(permitted().length===1?permitted()[0]:''));
      if(!siteId||!canAccessSite(siteId))return toast('Choose a Site you are allowed to manage');
      const before=new Set((typeof v183Members==='function'?v183Members():(db.gangs||[]).flatMap(group=>group.members||[])).map(member=>member.id)),previousOpen=openTeamMember;
      openTeamMember=function(teamId,memberId){const member=findMember(memberId);if(member&&!before.has(memberId)){member.clockSiteIds=[siteId];member.siteIds=[siteId]}return previousOpen(teamId,memberId)};
      try{
        const result=baseSaveNewPerson.apply(this,args),created=(typeof v183Members==='function'?v183Members():(db.gangs||[]).flatMap(group=>group.members||[])).find(member=>!before.has(member.id));
        if(created){created.clockSiteIds=[siteId];created.siteIds=[siteId];save()}
        return result;
      }finally{openTeamMember=previousOpen}
    };
  }

  // A Team can contain people from several Sites; show only the current scope.
  if(typeof manageTeamMembers==='function')window.manageTeamMembers=function(id){
    if(!hasPerm('manage_gangs'))return toast('You do not have Team administration access');
    const team=(db.gangs||[]).find(row=>row.id===id);if(!team)return;
    const visible=member=>v1996MemberMatchesContext(member),members=(team.members||[]).filter(visible),individuals=(typeof v176Individuals==='function'?v176Individuals()?.members:[])||[],available=individuals.filter(visible),individualId=typeof V183_INDIVIDUALS_ID!=='undefined'?V183_INDIVIDUALS_ID:(typeof V176_INDIVIDUALS_ID!=='undefined'?V176_INDIVIDUALS_ID:'individuals');
    if(!members.length&&!available.length&&site!=='all')return toast('This Team has no people in the selected Site');
    modal=`<div class="modal"><div class="modalbox"><div class="sectionhead"><div><span class="att-kicker">TEAM MEMBERSHIP</span><h2>${esc(team.name)}</h2><p class="muted">Only people in ${esc(site==='all'?'your permitted Sites':siteName(site))} are shown.</p></div></div><div class="team-members">${members.map(member=>`<div class="team-member"><div class="clickable" style="flex:1" onclick="openTeamMember('${esc(team.id)}','${esc(member.id)}')"><b>${esc(member.name)}</b><span>${esc(member.role||'Team member')}</span></div><button class="btn light smallbtn" onclick="v176MovePerson('${esc(member.id)}','${esc(individualId)}')">Make individual</button><button class="btn light smallbtn v176-team-danger" onclick="v176DeletePerson('${esc(member.id)}')">Remove</button></div>`).join('')||'<div class="empty-help"><b>No permitted members in this Team.</b></div>'}</div><div class="field"><label for="v176-add-existing">Add an existing Individual</label><select id="v176-add-existing" class="select"><option value="">Choose a person…</option>${available.map(member=>`<option value="${esc(member.id)}">${esc(member.name)} · ${esc(member.role||'Person')}</option>`).join('')}</select></div><div class="actions"><button class="btn blue" onclick="let memberId=document.getElementById('v176-add-existing').value;if(memberId)v176MovePerson(memberId,'${esc(team.id)}');else toast('Choose a person')">Add selected person</button><button class="btn orange" onclick="v176NewPerson('${esc(team.id)}')">＋ Create new member</button><button class="btn light" onclick="modal=null;render()">Done</button></div></div></div>`;render();
  };

  // Explicit-Site assignment and issue ownership.
  function assignmentSite(requested=''){
    if(requested&&requested!=='all')return requested;
    const item=(db.items||[]).find(row=>row.id===selected);if(item?.site)return item.site;
    const formSite=document.getElementById('ns')?.value;if(formSite)return formSite;
    if(site!=='all'&&canAccessSite(site))return site;
    const ids=permitted();return ids.length===1?ids[0]:'';
  }
  function workAssigneeAllowed(value,siteId){if(!value||value==='__not_required__')return true;return currentMemberSiteIds(findMember(value)).includes(siteId)}
  function issueAssigneeAllowed(value,siteId){
    if(!value)return true;const [kind,id]=String(value).split(':');
    if(kind==='person')return workAssigneeAllowed(id,siteId);
    if(kind==='user'){const user=(db.users||[]).find(row=>row.id===id&&row.accountActive!==false);return !!user&&(user.role==='Director'||user.allSitesAccess===true||(user.allowedSites||[]).includes(siteId))}
    if(kind==='gang'){const group=(db.gangs||[]).find(row=>row.id===id);return !!group&&(group.members||[]).some(member=>currentMemberSiteIds(member).includes(siteId))}
    return false;
  }
  window.fieldV1996WorkAssigneeAllowed=workAssigneeAllowed;
  window.fieldV1996IssueAssigneeAllowed=issueAssigneeAllowed;
  window.v188AssignmentOptions=function(selectedValue='',notRequired=false,siteId=''){
    const sid=assignmentSite(siteId),rows=sid?v1996MembersForSite(sid).map(row=>row.member).sort((a,b)=>String(a.name).localeCompare(String(b.name))):[];
    return `<option value="">To be Confirmed</option><option value="__not_required__" ${notRequired?'selected':''}>Not Required — shared / changing labour</option>${rows.map(member=>`<option value="${esc(member.id)}" ${!notRequired&&selectedValue===member.id?'selected':''}>${esc(member.name)}${member.role?' · '+esc(member.role):''}</option>`).join('')}`;
  };
  window.fieldV1996RefreshNewItemAssignees=function(siteId){const select=document.getElementById('ng');if(select)select.innerHTML=v188AssignmentOptions('',false,siteId)};
  if(typeof newItem==='function'){
    const baseNewItem=newItem;window.newItem=function(...args){const result=baseNewItem.apply(this,args),siteSelect=document.getElementById('ns');if(siteSelect){siteSelect.addEventListener('change',()=>fieldV1996RefreshNewItemAssignees(siteSelect.value));fieldV1996RefreshNewItemAssignees(siteSelect.value)}return result};
  }
  if(typeof editWorkItemTeam==='function'){
    const baseEditAssignment=editWorkItemTeam;window.editWorkItemTeam=function(...args){const item=(db.items||[]).find(row=>row.id===selected);if(!item||!canUpdateItem(item))return toast('You cannot update this work record');const result=baseEditAssignment.apply(this,args),select=document.getElementById('wit-team');if(select)select.innerHTML=v188AssignmentOptions(item.assignedId,item.assignmentNotRequired,item.site);return result};
  }
  function guardAssignmentSave(name,siteGetter,valueGetter){const base=window[name];if(typeof base!=='function')return;window[name]=function(...args){const sid=siteGetter(...args),value=valueGetter(...args);if(!sid||!canAccessSite(sid))return toast('That Site is outside your access');if(!workAssigneeAllowed(value,sid))return toast('Choose a person currently assigned to this Site');return base.apply(this,args)}}
  guardAssignmentSave('createItem',()=>document.getElementById('ns')?.value||'',()=>document.getElementById('ng')?.value||'');
  guardAssignmentSave('saveWorkItemTeam',()=>db.items.find(row=>row.id===selected)?.site||'',()=>document.getElementById('wit-team')?.value||'');
  guardAssignmentSave('saveLiftCard',()=>db.items.find(row=>row.id===selected)?.site||'',index=>document.getElementById(`lf-assigned-${index}`)?.value||'');
  let issueSiteHint='';
  window.issueAssigneeOptions=function(value='',siteId=''){
    const sid=assignmentSite(siteId||issueSiteHint),options=[['','Unassigned']],seen=new Set();
    for(const row of sid?v1996MembersForSite(sid):[]){const key='person:'+row.member.id;if(!seen.has(key)){seen.add(key);options.push([key,'Person · '+row.member.name])}}
    for(const user of db.users||[]){if(user.accountActive===false||!issueAssigneeAllowed('user:'+user.id,sid))continue;const key='user:'+user.id;if(!seen.has(key)){seen.add(key);options.push([key,'User · '+user.name])}}
    return options.map(([key,label])=>`<option value="${esc(key)}" ${value===key?'selected':''}>${esc(label)}</option>`).join('');
  };
  if(typeof editIssueRecord==='function'){
    const baseEditIssue=editIssueRecord;window.editIssueRecord=function(itemId,...rest){const item=db.items.find(row=>row.id===itemId);if(!item||!canViewItem(item))return toast('This issue is outside your access');issueSiteHint=item.site;try{return baseEditIssue.call(this,itemId,...rest)}finally{issueSiteHint=''}};
  }
  function guardIssueSave(name,itemGetter,valueId){const base=window[name];if(typeof base!=='function')return;window[name]=function(...args){const item=itemGetter(...args),value=document.getElementById(valueId)?.value||'';if(!item||!canViewItem(item))return toast('This issue is outside your access');if(!issueAssigneeAllowed(value,item.site))return toast('Choose an assignee who can access this Site');return base.apply(this,args)}}
  guardIssueSave('saveIssue',()=>db.items.find(row=>row.id===selected),'ia');
  guardIssueSave('saveIssueRecord',itemId=>db.items.find(row=>row.id===itemId),'ei-assigned');

  // The earlier guard incorrectly treated only v188-* IDs as real IDs.
  for(const name of ['quickUpdate','quickProgress','saveQuickProgress']){
    const base=window[name];if(typeof base!=='function')continue;
    window[name]=function(itemId,...args){const item=db.items.find(row=>row.id===itemId);if(!item||!canUpdateItem(item))return toast('You cannot update this work record');const previous=selected;selected=itemId;let result;try{result=base.call(this,itemId,...args)}finally{if(selected===itemId)selected=previous}if(name==='saveQuickProgress'&&modal===null)render();return result};
  }

  // Diary access, context-aware local drafts and the actual amendment route.
  let diaryContext=null,amendmentFromDraft='',openingDraftAmendment=false;
  function diaryAllowed(row,manage=false){return !!row&&canAccessSite(row.siteId)&&hasPerm(manage?'manage_site_diary':'view_site_diary')}
  function diaryFields(){return [['sd-teams','teams'],['sd-work','work'],['sd-del','deliveries'],['sd-delay','delays'],['sd-notes','notes']]}
  function saveDiaryDraftFor(siteId,date){if(!siteId||!date)return;const draft={siteId,date,savedAt:new Date().toISOString()};for(const [id,key] of diaryFields())draft[key]=document.getElementById(id)?.value||'';try{localStorage.setItem(v1996DiaryDraftKey(siteId,date),JSON.stringify(draft))}catch(error){}}
  function restoreDiaryDraft(siteId,date){const draft=v1996LoadDiaryDraft(siteId,date);if(!draft)return false;for(const [id,key] of diaryFields()){const field=document.getElementById(id);if(field){field.value=draft[key]||'';if(typeof v1995DiaryTouched!=='undefined')v1995DiaryTouched.add(id)}}const editor=document.querySelector('.v1995-diary-editor');if(editor&&!editor.querySelector('.field-v1996-draft-restored'))editor.querySelector('.v169-autofill-note')?.insertAdjacentHTML('afterend','<div class="v169-autofill-note field-v1996-draft-restored"><b>Draft restored</b><span>Your unsaved wording from this Site and date has been put back.</span></div>');if(typeof markDirty==='function')markDirty();return true}
  if(typeof addDiaryEntry==='function'){
    const baseAddDiary=addDiaryEntry;window.addDiaryEntry=function(...args){const result=baseAddDiary.apply(this,args),siteId=document.getElementById('sd-site')?.value||'',date=document.getElementById('sd-date')?.value||'';diaryContext={siteId,date};restoreDiaryDraft(siteId,date);return result};
  }
  if(typeof v1995RefreshDiaryPrefill==='function'){
    const baseRefreshDiary=v1995RefreshDiaryPrefill;window.v1995RefreshDiaryPrefill=function(...args){const next={siteId:document.getElementById('sd-site')?.value||'',date:document.getElementById('sd-date')?.value||''};if(diaryContext)saveDiaryDraftFor(diaryContext.siteId,diaryContext.date);if(typeof v1996DiaryDraftTimer!=='undefined')clearTimeout(v1996DiaryDraftTimer);if(typeof v1995DiaryTouched!=='undefined')v1995DiaryTouched.clear();const result=baseRefreshDiary.apply(this,args);diaryContext=next;restoreDiaryDraft(next.siteId,next.date);return result};
  }
  for(const [name,manage] of [['openDiaryEntry',false],['addDiaryAmendment',true],['v1996OpenDiaryDuplicate',false]]){
    const base=window[name];if(typeof base!=='function')continue;window[name]=function(id,...args){const row=(db.siteDiary||[]).find(entry=>entry.id===id);if(!diaryAllowed(row,manage))return toast('This Site Diary record is outside your access');if(name==='addDiaryAmendment'&&!openingDraftAmendment)amendmentFromDraft='';return base.call(this,id,...args)};
  }
  if(typeof saveDiaryAmendment==='function'){
    const baseSaveAmendment=saveDiaryAmendment;window.saveDiaryAmendment=function(id,...args){const row=(db.siteDiary||[]).find(entry=>entry.id===id);if(!diaryAllowed(row,true))return toast('This Site Diary record is outside your access');const before=(row.amendments||[]).length,result=baseSaveAmendment.call(this,id,...args);if((row.amendments||[]).length>before&&amendmentFromDraft===id){v1996ClearDiaryDraft(row.siteId,row.date);amendmentFromDraft='';if(typeof v1996CommitDraft==='function')v1996CommitDraft()}return result};
  }
  if(typeof saveDiaryEntry==='function'){
    const baseSaveDiary=saveDiaryEntry;window.saveDiaryEntry=function(...args){const siteId=document.getElementById('sd-site')?.value||'';if(!siteId||!canAccessSite(siteId))return toast('That Site is outside your access');return baseSaveDiary.apply(this,args)};
  }
  window.fieldV1996CancelDiaryAmendment=function(){if(typeof v1996ConfirmDraftExit==='function'&&!v1996ConfirmDraftExit())return;amendmentFromDraft='';modal=null;render()};
  window.fieldV1996DiaryAmendment=function(id){const row=(db.siteDiary||[]).find(entry=>entry.id===id);if(!diaryAllowed(row,true))return toast('This Site Diary record is outside your access');const draft=v1996LoadDiaryDraft(row.siteId,row.date);openingDraftAmendment=true;try{addDiaryAmendment(id)}finally{openingDraftAmendment=false}amendmentFromDraft=draft?id:'';if(typeof modal==='string'&&modal.includes('diary-amendment-text')){modal=modal.replace('onclick="modal=null;render()">Cancel','onclick="fieldV1996CancelDiaryAmendment()">Cancel');render()}if(draft){const text=diaryFields().map(([,key],index)=>{const labels=['People on site','Work completed or progressed','Deliveries or scaffold','Problems or delays','General notes'];return String(draft[key]||'').trim()?`${labels[index]}:\n${draft[key]}`:''}).filter(Boolean).join('\n\n'),field=document.getElementById('diary-amendment-text');if(field&&text){field.value=text;if(typeof markDirty==='function')markDirty();if(typeof v1996DraftChanged==='function')v1996DraftChanged()}}};
  window.v1996ShowDiaryDuplicate=function(row){if(!diaryAllowed(row,true))return toast('This Site Diary record is outside your access');modal=`<div class="modal"><div class="modalbox v1996-duplicate-diary" role="dialog" aria-modal="true"><span class="att-kicker">ONE DAILY RECORD</span><h2>A Site Diary already exists</h2><p>${esc(siteName(row.siteId))} already has an original diary for <b>${esc(row.date)}</b>. Open it or add a dated amendment so the record stays clear.</p><div class="field-mobile-actions"><button class="btn light" onclick="v1996OpenDiaryDuplicate('${esc(row.id)}')">Open existing</button><button class="btn orange" onclick="fieldV1996DiaryAmendment('${esc(row.id)}')">Add amendment</button></div></div></div>`;render()};
  if(typeof v1991CloseModal==='function'){
    const baseCloseModal=v1991CloseModal;window.v1991CloseModal=function(...args){const wasDraftAmendment=!!amendmentFromDraft&&!!document.getElementById('diary-amendment-text'),result=baseCloseModal.apply(this,args);if(wasDraftAmendment&&!document.getElementById('diary-amendment-text'))amendmentFromDraft='';return result};
  }

  // Shared drawings: retryable upload queue plus record/Site guards.
  function retryableUpload(error){return !/(unauthori[sz]ed|forbidden|permission|session|sign in|too large|unsupported|invalid file|\b401\b|\b403\b|\b413\b|\b415\b)/i.test(String(error?.message||error||''))}
  window.v1996StoreDrawingFile=async function(file,siteId){
    if(!siteId||!canAccessSite(siteId))throw new Error('That Site is outside your access');
    if(sharedMode){
      if(navigator.onLine)try{return await uploadBlobToServer(file,file.name||'drawing',siteId)}catch(error){if(!retryableUpload(error))throw error}
      const random=globalThis.crypto?.randomUUID?.()||Math.random().toString(16).slice(2),key=`drawing-${Date.now()}-${random}`;await putPendingBlob(key,file);if(typeof syncState!=='undefined')syncState='offline';if(typeof updateSyncUI==='function')updateSyncUI();return `pending:${key}`;
    }
    return storeDrawingInBrowser(file);
  };
  function libraryDrawing(id){return (db.siteDrawings||[]).find(row=>row.id===id)}
  function guardDrawing(name,check){const base=window[name];if(typeof base!=='function')return;window[name]=function(...args){const error=check(...args);if(error)return toast(error);return base.apply(this,args)}}
  guardDrawing('openSiteDrawing',id=>{const row=libraryDrawing(id);return !row||!hasPerm('view_drawings')||!canAccessSite(row.siteId)?'This drawing is outside your access':''});
  guardDrawing('deleteSiteDrawing',id=>{const row=libraryDrawing(id);return !row||!canAccessSite(row.siteId)?'This drawing is outside your access':''});
  guardDrawing('v169NewDrawingRevision',id=>{const row=libraryDrawing(id);return !row||!hasPerm('manage_drawings')||!canAccessSite(row.siteId)?'This drawing is outside your access':''});
  guardDrawing('openDrawing',index=>{const item=db.items.find(row=>row.id===selected),drawing=item?.drawings?.[index];return !item||!drawing||!hasPerm('view_drawings')||!canViewItem(item)?'This drawing is outside your access':''});
  guardDrawing('deleteDrawing',index=>{const item=db.items.find(row=>row.id===selected),drawing=item?.drawings?.[index];return !item||!drawing||!canViewItem(item)?'This drawing is outside your access':''});
  if(typeof openDrawingTakeoff==='function'){
    const baseTakeoff=openDrawingTakeoff;window.openDrawingTakeoff=function(scope,drawingId,itemId=''){if(scope==='library'){const row=libraryDrawing(drawingId);if(!row||!hasPerm('view_drawings')||!canAccessSite(row.siteId))return toast('This drawing is outside your access')}else{const item=db.items.find(row=>row.id===itemId);if(!item||!hasPerm('view_drawings')||!canViewItem(item))return toast('This drawing is outside your access')}return baseTakeoff.apply(this,arguments)};
  }
  if(typeof transferSiteDrawing==='function'){
    const baseTransfer=transferSiteDrawing;window.transferSiteDrawing=function(id,targetOverride=''){const drawing=libraryDrawing(id),targetId=targetOverride||document.getElementById('sdw-target')?.value||'',item=db.items.find(row=>row.id===targetId);if(!drawing||!item||!hasPerm('manage_drawings')||!canAccessSite(drawing.siteId)||!canViewItem(item))return toast('This drawing or work record is outside your access');if(drawing.siteId!==item.site)return toast('A drawing can only be added to work on the same Site');return baseTransfer.apply(this,arguments)};
  }
  window.v169SaveDrawingRevision=async function(id){
    const old=libraryDrawing(id),file=uploadFiles('rev-file')[0],revision=(document.getElementById('rev-new')?.value||'').trim(),issuedDate=document.getElementById('rev-issued')?.value||iso(),note=(document.getElementById('rev-note')?.value||'').trim();
    if(!old||!hasPerm('manage_drawings')||!canAccessSite(old.siteId))return toast('This drawing is outside your access');if(old.revisionStatus==='Superseded')return toast('Open the CURRENT drawing before uploading a new revision');if(!file||!revision)return toast('New revision and drawing file are required');
    try{
      const data=await v1996StoreDrawingFile(file,old.siteId),drawing={...old,id:'sdw'+Date.now(),revision,issuedDate,revisionStatus:'Current',supersededBy:'',supersededAt:'',supersededByUser:'',notes:note||old.notes,fileName:file.name||old.fileName,type:file.type||old.type,data,storage:String(data).startsWith('pending:')?'pending':String(data).startsWith('browser:')?'browser':'shared',uploadedDate:iso(),uploadedAt:new Date().toISOString(),uploadedBy:currentUser()?.name||'',lastUsedAt:Date.now(),takeoffs:[],takeoffCalibration:null,highlights:[]};
      (db.siteDrawings||[]).filter(row=>row.siteId===old.siteId&&(old.drawingNumber?row.drawingNumber===old.drawingNumber:row.id===old.id)&&row.revisionStatus!=='Superseded').forEach(row=>{row.revisionStatus='Superseded';row.supersededBy=drawing.id;row.supersededAt=new Date().toISOString();row.supersededByUser=currentUser()?.name||''});db.siteDrawings.push(drawing);save();audit('drawing','drawing library',drawing.id,`${drawing.drawingNumber||drawing.name}: Revision ${revision} uploaded · previous revision superseded`,drawing.siteId);if(typeof v1996CommitDraft==='function')v1996CommitDraft();modal=null;savedState(String(data).startsWith('pending:')?'Revision saved on this phone — waiting to sync':'New drawing revision saved and shared');render();
    }catch(error){toast(error.message||'The drawing revision could not be saved')}
  };

  // Restrict single-Site locking to actual Site-context selectors.
  function genuineSiteSelector(select){const handler=select.getAttribute('onchange')||'';return select.dataset.siteContext==='true'||/setSiteContext\s*\(|setDrawingSiteFilter\s*\(/.test(handler)}
  function repairSingleSiteSelectors(){const ids=permitted();if(ids.length!==1)return;document.querySelectorAll('select.v1996-single-site-select').forEach(select=>{if(genuineSiteSelector(select)){select.value=ids[0];select.disabled=true;return}select.classList.remove('v1996-single-site-select');select.disabled=select.dataset.fieldV1996WasDisabled==='1'})}
  function repairCompanyWideControls(){if(!companyWideAccess())document.querySelectorAll('[onclick*="workforce-archive"]').forEach(control=>control.remove())}
  if(typeof v1996EnhanceRenderedUi==='function'){
    const baseEnhance=v1996EnhanceRenderedUi;window.v1996EnhanceRenderedUi=function(...args){document.querySelectorAll('select').forEach(select=>select.dataset.fieldV1996WasDisabled=select.disabled?'1':'0');const result=baseEnhance.apply(this,args);repairSingleSiteSelectors();repairCompanyWideControls();return result};repairSingleSiteSelectors();repairCompanyWideControls();
  }

  // Document audience and direct mutation enforcement.
  function audienceUsers(siteId=''){
    const user=currentUser(),allowed=new Set(permitted()),director=user?.role==='Director'||user?.allSitesAccess===true;
    return (db.users||[]).filter(row=>{
      if(row.accountActive===false)return false;
      if(director)return siteId?row.role==='Director'||row.allSitesAccess===true||(row.allowedSites||[]).includes(siteId):true;
      if(siteId)return row.role==='Director'||row.allSitesAccess===true||(row.allowedSites||[]).includes(siteId);
      return row.role==='Director'||row.allSitesAccess===true||(row.allowedSites||[]).some(id=>allowed.has(id));
    });
  }
  const documentRoles=['Director','Contracts Manager','Site Manager','Supervisor','Quantity Surveyor','Accounts','Operator'];
  function documentSite(){const value=document.getElementById('v191-doc-site')?.value;if(value!==undefined)return value;if(typeof v191DocumentSite!=='undefined'&&v191DocumentSite&&v191DocumentSite!=='all')return v191DocumentSite;const ids=permitted();return ids.length===1?ids[0]:''}
  function audienceAllowed(value,siteId){if(!value||value==='all')return true;const [kind,id]=String(value).split(':');if(kind==='role')return documentRoles.includes(id);if(kind!=='user'||!id)return false;return audienceUsers(siteId).some(user=>user.id===id)}
  window.v191AudienceOptions=function(selectedValue='all',siteId=''){const sid=siteId||documentSite();return `<option value="all" ${selectedValue==='all'?'selected':''}>All authorised users</option><optgroup label="Provide to a role">${documentRoles.map(role=>`<option value="role:${esc(role)}" ${selectedValue==='role:'+role?'selected':''}>${esc(role)}</option>`).join('')}</optgroup><optgroup label="Provide to one user">${audienceUsers(sid).map(user=>`<option value="user:${esc(user.id)}" ${selectedValue==='user:'+user.id?'selected':''}>${esc(user.name)} · ${esc(user.role)}</option>`).join('')}</optgroup>`};
  window.fieldV1996RefreshDocumentAudience=function(siteId){const select=document.getElementById('v191-doc-audience');if(!select)return;const previous=select.value;select.innerHTML=v191AudienceOptions(previous,siteId);if(audienceAllowed(previous,siteId))select.value=previous;else select.value='all'};
  function documentRow(id,type=''){return (db.documents||[]).find(item=>item.id===id&&(!type||item.type===type))}
  function documentVisibleId(id,type=''){const row=documentRow(id,type);return !!row&&typeof v191DocumentVisible==='function'&&v191DocumentVisible(row)}
  function documentMutableId(id,type=''){const row=documentRow(id,type);return !!row&&hasPerm('manage_documents')&&documentVisibleId(id,type)&&(!!row.siteId||companyWideAccess())}
  function constrainDocumentSiteSelect(select){
    if(!select)return;const parent=typeof v191DocumentFolder!=='undefined'&&v191DocumentFolder?documentRow(v191DocumentFolder,'folder'):null,forced=parent?.siteId||'',preferred=forced||(site!=='all'&&canAccessSite(site)?site:(typeof v191DocumentSite!=='undefined'&&v191DocumentSite!=='all'&&canAccessSite(v191DocumentSite)?v191DocumentSite:(permitted()[0]||'')));
    [...select.options].forEach(option=>{if(option.value&&!canAccessSite(option.value))option.remove();else if(option.value===''&&!companyWideAccess())option.remove()});
    if(forced&&canAccessSite(forced))select.value=forced;else if(preferred&&[...select.options].some(option=>option.value===preferred))select.value=preferred;
    select.disabled=!!forced||(!companyWideAccess()&&[...select.options].filter(option=>option.value).length===1);select.addEventListener('change',()=>fieldV1996RefreshDocumentAudience(select.value));fieldV1996RefreshDocumentAudience(select.value)
  }
  for(const name of ['v191NewFolder','v191UploadDocuments']){
    const base=window[name];if(typeof base!=='function')continue;window[name]=function(...args){const result=base.apply(this,args);constrainDocumentSiteSelect(document.getElementById('v191-doc-site'));return result};
  }
  for(const [name,type] of [['v191OpenDocument','file'],['v192DocumentHistory','file'],['v192OpenRevision','file']]){
    const base=window[name];if(typeof base!=='function')continue;window[name]=function(id,...args){if(!documentVisibleId(id,type))return toast('This document is outside your access');return base.call(this,id,...args)};
  }
  for(const [name,type] of [['v191RenameDocument',''],['v192NewRevision','file'],['v192EditDocumentControl','file'],['v192SaveDocumentControl','file']]){
    const base=window[name];if(typeof base!=='function')continue;window[name]=function(id,...args){if(!documentMutableId(id,type))return toast('This document is outside your management access');return base.call(this,id,...args)};
  }
  if(typeof v191DeleteDocument==='function'){
    const baseDeleteDocument=v191DeleteDocument;window.v191DeleteDocument=function(id,...args){const root=documentRow(id);if(!root||!documentMutableId(id))return toast('This document is outside your management access');const ids=new Set([id]);let changed=true;while(changed){changed=false;for(const row of db.documents||[])if(ids.has(row.parentId)&&!ids.has(row.id)){ids.add(row.id);changed=true}}if([...ids].some(childId=>!documentMutableId(childId)))return toast('This folder contains records outside your access and cannot be removed');return baseDeleteDocument.call(this,id,...args)};
  }
  if(typeof v192SaveRevision==='function'){
    const baseSaveRevision=v192SaveRevision,inFlight=new Set();window.v192SaveRevision=async function(id,...args){if(!documentMutableId(id,'file'))return toast('This document is outside your management access');if(inFlight.has(id))return toast('This revision is already being uploaded');const button=document.activeElement?.closest?.('button');inFlight.add(id);if(typeof v1996DraftState!=='undefined')v1996DraftState.saving=true;if(button){button.disabled=true;button.setAttribute('aria-busy','true')}try{return await baseSaveRevision.call(this,id,...args)}finally{inFlight.delete(id);if(typeof v1996DraftState!=='undefined'&&v1996DraftState.saving)v1996DraftState.saving=false;if(button?.isConnected){button.disabled=false;button.removeAttribute('aria-busy')}}};
  }
  for(const name of ['v191SaveFolder','v191SaveDocuments']){
    const base=window[name];if(typeof base!=='function')continue;window[name]=function(...args){const siteId=documentSite(),audience=document.getElementById('v191-doc-audience')?.value||'all',parentId=typeof v191DocumentFolder!=='undefined'?v191DocumentFolder:'',parent=parentId?documentRow(parentId,'folder'):null;if(!hasPerm('manage_documents'))return toast('Document management permission is required');if(!siteId&&!companyWideAccess())return toast('Choose one of your permitted Sites');if(siteId&&!canAccessSite(siteId))return toast('That Site is outside your access');if(parentId&&!documentVisibleId(parentId,'folder'))return toast('This document folder is outside your access');if(parent?.siteId&&parent.siteId!==siteId)return toast(`This folder belongs to ${siteName(parent.siteId)}. Choose the same Site.`);if(!audienceAllowed(audience,siteId))return toast('Choose a document audience within your Site access');return base.apply(this,args)};
  }

  // Manager phone Team Time uses contractorAttendanceTab as its real state.
  if(typeof attendanceTodayView==='function'){
    const baseToday=attendanceTodayView;window.attendanceTodayView=function(...args){const html=baseToday.apply(this,args);return typeof html==='string'?html.replace(/attendanceTab='timesheets';render\(\)/g,"contractorAttendanceTab='timesheets';attendanceTab='timesheets';render()"):html};
  }

  repairSingleSiteSelectors();repairCompanyWideControls();
})();
