// @ts-check
(()=>{
  'use strict';
  const App=window.IUS_TEMPLATE,{utils,state}=App;
  const DB_NAME='ius-template-comments',STORE='comments';let dbPromise=null,currentKey=null,visible=4;const memory=new Map();
  const seeds={
    'post:designing-for-depth':[
      {id:'seed-depth-1',displayName:'Alex Morgan',body:'The distinction between structural depth and decorative shadow is useful. The elevation rule makes the interface easier to audit.',website:'',locale:'en',createdAt:'2026-07-20T10:15:00.000Z',local:false},
      {id:'seed-depth-2',displayName:'佐藤 美咲',body:'動きが情報へのアクセスを遅らせないという原則が特に重要だと思います。',website:'',locale:'ja',createdAt:'2026-07-21T08:40:00.000Z',local:false}
    ],
    'post:building-a-useful-case-study':[{id:'seed-evidence-1',displayName:'Jordan Lee',body:'Clear labelling of sample data is an excellent inclusion for a reusable template.',website:'',locale:'en',createdAt:'2026-07-10T14:20:00.000Z',local:false}],
    'post:offline-localisation-that-scales':[{id:'seed-local-1',displayName:'田中 健',body:'日付と検証メッセージまで含めることで、多言語対応が完成するという説明が分かりやすいです。',website:'',locale:'ja',createdAt:'2026-07-03T09:00:00.000Z',local:false}]
  };
  function openDB(){if(dbPromise)return dbPromise;dbPromise=new Promise((resolve,reject)=>{if(!('indexedDB'in window)){resolve(null);return}let req;try{req=indexedDB.open(DB_NAME,1)}catch(_){resolve(null);return}req.onupgradeneeded=()=>{const db=req.result;if(!db.objectStoreNames.contains(STORE)){const store=db.createObjectStore(STORE,{keyPath:'id'});store.createIndex('pageKey','pageKey',{unique:false});store.createIndex('createdAt','createdAt',{unique:false})}};req.onsuccess=()=>resolve(req.result);req.onerror=()=>reject(req.error)});return dbPromise}
  async function getLocal(pageKey){try{const db=await openDB();if(!db){try{return JSON.parse(localStorage.getItem(`comments:${pageKey}`)||'[]')}catch(_){return memory.get(pageKey)||[]}}return await new Promise((resolve,reject)=>{const tx=db.transaction(STORE,'readonly'),req=tx.objectStore(STORE).index('pageKey').getAll(pageKey);req.onsuccess=()=>resolve(req.result);req.onerror=()=>reject(req.error)})}catch(_){return[]}}
  async function put(comment){try{const db=await openDB();if(!db){const key=`comments:${comment.pageKey}`;try{const arr=JSON.parse(localStorage.getItem(key)||'[]');arr.push(comment);localStorage.setItem(key,JSON.stringify(arr))}catch(_){const arr=memory.get(comment.pageKey)||[];arr.push(comment);memory.set(comment.pageKey,arr)}return}await new Promise((resolve,reject)=>{const tx=db.transaction(STORE,'readwrite');tx.objectStore(STORE).put(comment);tx.oncomplete=()=>resolve();tx.onerror=()=>reject(tx.error)})}catch(e){throw e}}
  async function remove(id,pageKey){try{const db=await openDB();if(!db){const key=`comments:${pageKey}`;try{const arr=JSON.parse(localStorage.getItem(key)||'[]').filter(c=>c.id!==id);localStorage.setItem(key,JSON.stringify(arr))}catch(_){memory.set(pageKey,(memory.get(pageKey)||[]).filter(c=>c.id!==id))}return}await new Promise((resolve,reject)=>{const tx=db.transaction(STORE,'readwrite');tx.objectStore(STORE).delete(id);tx.oncomplete=()=>resolve();tx.onerror=()=>reject(tx.error)})}catch(e){throw e}}
  async function all(pageKey){return[...(seeds[pageKey]||[]),...(await getLocal(pageKey))]}
  function initials(name){return name.trim().split(/\s+/).slice(0,2).map(part=>part[0]||'').join('').toUpperCase()||'?'}
  function validWebsite(value){if(!value)return'';try{const u=new URL(value);return ['http:','https:'].includes(u.protocol)?u.href:''}catch(_){return''}}
  async function render(){if(!currentKey)return;const list=utils.$('[data-comment-list]'),sort=utils.$('[data-comment-sort]')?.value||'newest';if(!list)return;const rows=await all(currentKey);rows.sort((a,b)=>(sort==='oldest'?1:-1)*(new Date(a.createdAt)-new Date(b.createdAt)));utils.$('[data-comment-count]').textContent=String(rows.length);list.replaceChildren();if(!rows.length){const p=document.createElement('p');p.className='local-notice';p.textContent=App.modules.i18n.t('comments.empty');list.append(p);return}rows.slice(0,visible).forEach(c=>{const article=document.createElement('article');article.className='comment-card';const avatar=document.createElement('div');avatar.className='comment-avatar';avatar.setAttribute('aria-hidden','true');avatar.textContent=initials(c.displayName);const body=document.createElement('div'),meta=document.createElement('div');meta.className='comment-meta';const name=document.createElement('strong');name.textContent=c.displayName;const time=document.createElement('time');time.dateTime=c.createdAt;time.textContent=new Intl.DateTimeFormat(state.locale==='ja'?'ja-JP':'en-GB',{dateStyle:'medium',timeStyle:'short'}).format(new Date(c.createdAt));meta.append(name,time);body.append(meta);if(c.website){const a=document.createElement('a');a.className='comment-website';a.href=c.website;a.target='_blank';a.rel='ugc nofollow noopener noreferrer';a.textContent=new URL(c.website).hostname;body.append(a)}const p=document.createElement('p');p.className='comment-body';p.textContent=c.body;body.append(p);if(c.local){const del=document.createElement('button');del.type='button';del.className='comment-delete';del.textContent=App.modules.i18n.t('comments.delete');del.addEventListener('click',async()=>{await remove(c.id,currentKey);render()});body.append(del)}article.append(avatar,body);list.append(article)});const more=utils.$('[data-comment-load]');if(more)more.hidden=rows.length<=visible}
  function openComposer(){const f=utils.$('[data-comment-form]');if(!f)return;f.hidden=false;utils.$('#comment-name',f)?.focus()}
  function closeComposer(){const f=utils.$('[data-comment-form]');if(f)f.hidden=true}
  function setPage(slug){currentKey=`post:${slug}`;visible=App.data.siteConfig?.comments?.pageSize||4;closeComposer();render()}
  function init(){
    utils.$('[data-comment-compose]')?.addEventListener('click',openComposer);utils.$('[data-comment-cancel]')?.addEventListener('click',closeComposer);utils.$('[data-comment-sort]')?.addEventListener('change',render);utils.$('[data-comment-load]')?.addEventListener('click',()=>{visible+=App.data.siteConfig?.comments?.pageSize||4;render()});
    const textarea=utils.$('#comment-body'),counter=utils.$('[data-comment-counter]');textarea?.addEventListener('input',()=>{if(counter)counter.textContent=String(textarea.value.length)});
    utils.$('[data-comment-form]')?.addEventListener('submit',async event=>{event.preventDefault();const form=event.currentTarget,status=utils.$('[data-comment-status]');status.className='form-status';if(!form.reportValidity()){status.textContent=App.modules.i18n.t('form.required');status.classList.add('error');return}const fd=new FormData(form),body=String(fd.get('body')||'').trim().replace(/[\u0000-\u0008\u000B\u000C\u000E-\u001F]/g,'');if(!body){status.textContent=App.modules.i18n.t('form.required');return}try{await put({id:crypto.randomUUID?crypto.randomUUID():`local-${Date.now()}`,pageKey:currentKey,displayName:String(fd.get('displayName')||'').trim().slice(0,80),body:body.slice(0,1200),website:validWebsite(String(fd.get('website')||'')),locale:state.locale,createdAt:new Date().toISOString(),local:true});form.reset();if(counter)counter.textContent='0';status.textContent=App.modules.i18n.t('comments.pending');status.classList.add('success');await render();setTimeout(closeComposer,800)}catch(_){status.textContent=App.modules.i18n.t('comments.error');status.classList.add('error')}});
    document.addEventListener('ius:localechange',render);
  }
  App.modules.comments={init,setPage,render};
})();
