const root = document.querySelector('#installer');
const toastRoot = document.querySelector('#toast');
const query = new URLSearchParams(location.search);
const state = {
  step: 1,
  token: query.get('token') || sessionStorage.getItem('oc_install_token') || '',
  status: null,
  smtpTested: false,
  installing: false,
  complete: null,
  data: {
    site: { appName: 'OnlyCoin', companyName: '', appOrigin: location.origin, supportEmail: '', timezone: 'Europe/Istanbul' },
    admin: { name: '', email: '', password: '', confirmPassword: '' },
    smtp: { host: '', port: 587, secure: false, startTls: true, username: '', password: '', fromEmail: '', fromName: 'OnlyCoin', ehloName: location.hostname || 'onlycoin.local' }
  }
};
if (state.token) sessionStorage.setItem('oc_install_token', state.token);
const esc = (value) => String(value ?? '').replace(/[&<>'"]/g, c => ({'&':'&amp;','<':'&lt;','>':'&gt;',"'":'&#39;','"':'&quot;'}[c]));
function toast(message, type=''){const el=document.createElement('div');el.className=`toast ${type}`;el.textContent=message;toastRoot.appendChild(el);setTimeout(()=>el.remove(),5000)}
async function api(path,{method='GET',body}={}){const headers={'Content-Type':'application/json','X-Install-Token':state.token,'X-Request-ID':crypto.randomUUID()};const r=await fetch(path,{method,headers,body:body==null?undefined:JSON.stringify(body)});const data=await r.json().catch(()=>({}));if(!r.ok)throw Object.assign(new Error(data.message||'İşlem tamamlanamadı.'),{code:data.code,details:data.details});return data}
const steps=[['Sunucu Kontrolü','Sistem ve adres'],['Site & Yönetici','Kurumsal bilgiler'],['E-posta','SMTP doğrulama'],['Kurulum','Kontrol ve tamamla']];
function shell(content){root.innerHTML=`<div class="install-shell"><aside class="install-aside"><div class="brand"><img src="/install/assets/onlycoin-token.png" alt="OnlyCoin"><div><strong>ONLYCOIN</strong><small>PRODUCTION INSTALLER</small></div></div><div class="steps">${steps.map((s,i)=>`<div class="step-pill ${state.step===i+1?'active':''} ${state.step>i+1?'done':''}"><b>${state.step>i+1?'✓':i+1}</b><div><span>${s[0]}</span><small>${s[1]}</small></div></div>`).join('')}</div><div class="aside-note">Kurulum tamamlandığında sihirbaz kilitlenir. Kurulum boş kullanıcı ve finans kayıtlarıyla başlar. Ödeme, presale ve dağıtım modülleri gerçek sağlayıcılar girilene kadar kapalı kalır.</div></aside><main class="install-main"><div class="panel">${content}</div></main></div>`}
function field(name,label,type='text',value='',extra=''){return `<div class="field ${extra.includes('full')?'full':''}"><label for="${name}">${label}</label><input id="${name}" name="${name}" type="${type}" value="${esc(value)}" ${extra.replace('full','')} required></div>`}
function readForm(form, target){const fd=new FormData(form);for(const [key,value] of fd)target[key]=value;form.querySelectorAll('input[type=checkbox]').forEach(el=>target[el.name]=el.checked)}
function step1(){const req=state.status?.requirements;const checks=req?.checks||[];shell(`<div class="eyebrow">AŞAMA 1 / 4</div><h1>Sunucu ve yayın adresi</h1><p class="lead">OnlyCoin canlı kuruluma başlamadan önce Node.js, SQLite ve yazma izinlerini doğrular. Kurulum anahtarı yalnızca ilk kurulum sırasında geçerlidir.</p><div class="card"><div class="check-list">${checks.map(c=>`<div class="requirement ${c.ok?'ok':'bad'}"><i>${c.ok?'✓':'!'}</i><b>${esc(c.label)}</b><small>${esc(c.value)}</small></div>`).join('')}</div></div><form id="step-form" class="card"><div class="form-grid">${field('installToken','Kurulum anahtarı','password',state.token,'autocomplete="off" full')}${field('appOrigin','Canlı site adresi','url',state.data.site.appOrigin,'placeholder="https://onlycoin.example" full')}<div class="field"><label for="timezone">Saat dilimi</label><select id="timezone" name="timezone"><option ${state.data.site.timezone==='Europe/Istanbul'?'selected':''}>Europe/Istanbul</option><option ${state.data.site.timezone==='UTC'?'selected':''}>UTC</option><option ${state.data.site.timezone==='Europe/London'?'selected':''}>Europe/London</option><option ${state.data.site.timezone==='America/New_York'?'selected':''}>America/New_York</option></select></div></div><div class="actions"><span></span><button class="button primary" ${!req?.ok?'disabled':''}>Devam Et</button></div></form>`)}
function step2(){shell(`<div class="eyebrow">AŞAMA 2 / 4</div><h1>Site ve ilk yönetici</h1><p class="lead">İlk yönetici veritabanında güçlü parola özetiyle oluşturulur. Ortak veya varsayılan yönetici parolası kullanılmaz.</p><form id="step-form" class="card"><div class="form-grid">${field('appName','Platform adı','text',state.data.site.appName)}${field('companyName','Şirket / proje sahibi','text',state.data.site.companyName)}${field('supportEmail','Destek e-postası','email',state.data.site.supportEmail||state.data.admin.email)}${field('adminName','Yönetici adı soyadı','text',state.data.admin.name)}${field('adminEmail','Yönetici e-postası','email',state.data.admin.email)}${field('adminPassword','Yönetici parolası','password',state.data.admin.password,'minlength="14" autocomplete="new-password"')}${field('adminConfirmPassword','Parola tekrarı','password',state.data.admin.confirmPassword,'minlength="14" autocomplete="new-password"')}<div class="field full"><small>Parola en az 14 karakter olmalı; büyük harf, küçük harf, rakam ve özel karakter içermelidir.</small></div></div><div class="actions"><button type="button" class="button secondary" data-back>Geri</button><button class="button primary">Devam Et</button></div></form>`)}
function step3(){const s=state.data.smtp;shell(`<div class="eyebrow">AŞAMA 3 / 4</div><h1>SMTP ve kayıt doğrulaması</h1><p class="lead">Kayıt işleminin gerçekten çalışması için e-posta doğrulaması zorunludur. Kurulum, yönetici adresine gerçek bir test e-postası göndermeden tamamlanmaz.</p><form id="smtp-form" class="card"><div class="form-grid">${field('host','SMTP sunucusu','text',s.host,'placeholder="smtp.example.com"')}${field('port','SMTP portu','number',s.port,'min="1" max="65535"')}${field('username','SMTP kullanıcı adı','text',s.username,'autocomplete="username"')}${field('password','SMTP parolası','password',s.password,'autocomplete="new-password"')}${field('fromEmail','Gönderen e-posta','email',s.fromEmail||state.data.admin.email)}${field('fromName','Gönderen adı','text',s.fromName||state.data.site.appName)}${field('ehloName','EHLO alan adı','text',s.ehloName,'full')}<label class="check-row"><input name="secure" type="checkbox" ${s.secure?'checked':''}><span>Doğrudan TLS kullan (genellikle port 465)</span></label><label class="check-row"><input name="startTls" type="checkbox" ${s.startTls?'checked':''}><span>STARTTLS kullan (genellikle port 587)</span></label></div><div id="smtp-state" class="smtp-state ${state.smtpTested?'ok':''}">${state.smtpTested?'✓ SMTP test e-postası başarıyla gönderildi.':'Kuruluma devam etmek için SMTP testini çalıştırın.'}</div><div class="actions"><button type="button" class="button secondary" data-back>Geri</button><button type="button" class="button primary" id="smtp-test">SMTP Testi Gönder</button></div></form>`)}
function step4(){const d=state.data;return shell(`<div class="eyebrow">AŞAMA 4 / 4</div><h1>Kontrol et ve kurulumu tamamla</h1><p class="lead">Kurulum; boş kullanıcı tabanı, sıfır finans hareketi ve kapalı ödeme modülleriyle üretim başlangıcı oluşturur.</p><div class="card summary"><div><small>Platform</small><b>${esc(d.site.appName)}</b></div><div><small>Canlı adres</small><b>${esc(d.site.appOrigin)}</b></div><div><small>Yönetici</small><b>${esc(d.admin.name)} · ${esc(d.admin.email)}</b></div><div><small>SMTP</small><b>${esc(d.smtp.host)}:${esc(d.smtp.port)} · ${esc(d.smtp.fromEmail)}</b></div><div><small>Kayıt</small><b>E-posta doğrulamalı</b></div><div><small>Başlangıç verisi</small><b>Boş kullanıcı ve finans kayıtları</b></div></div><div class="security-box">Presale, deposit, withdrawal, ödeme sağlayıcıları ve otomatik mainnet dağıtımı kurulum sonrasında kapalıdır. Bunlar yalnızca gerçek sözleşme, cüzdan, merchant ve uyum bilgileri girildiğinde yönetim panelinden etkinleştirilir.</div><label class="check-row" style="margin-top:18px"><input id="final-confirm" type="checkbox"><span>Kurulum bilgilerini kontrol ettim; canlı yapılandırmayı oluşturmaya hazırım.</span></label><div class="actions"><button class="button secondary" data-back>Geri</button><button class="button primary" id="complete-install" disabled>Kurulumu Tamamla</button></div>`)}
function success(){const m=state.complete?.installation;shell(`<div class="success"><div class="icon">✓</div><h1>OnlyCoin kurulumu tamamlandı</h1><p class="lead" style="margin:auto">Sunucu üretim yapılandırmasıyla yeniden başlatılıyor. Yönetim paneline e-posta adresiniz ve belirlediğiniz parola ile giriş yapın.</p><div class="card summary" style="text-align:left"><div><small>Kurulum Kimliği</small><b>${esc(m?.installationId||'-')}</b></div><div><small>Site</small><b>${esc(m?.appOrigin||state.data.site.appOrigin)}</b></div></div><a class="button primary" href="/admin/">Yönetim Panelini Aç</a><p id="restart-state" class="smtp-state">Sunucunun yeniden başlaması bekleniyor…</p></div>`);pollRestart()}
function render(){if(state.complete)return success();if(state.status?.installed){return shell(`<div class="success"><div class="icon">✓</div><h1>Kurulum zaten tamamlanmış</h1><p class="lead" style="margin:auto">Kurulum sihirbazı güvenlik nedeniyle kilitlidir.</p><a class="button primary" href="/admin/">Yönetim Paneline Git</a></div>`)}({1:step1,2:step2,3:step3,4:step4}[state.step]||step1)()}
function validateStep2(){const a=state.data.admin;if(!a.email||!a.name)throw new Error('Yönetici adı ve e-postası zorunludur.');if(a.password!==a.confirmPassword)throw new Error('Yönetici parolaları eşleşmiyor.');if(a.password.length<14||!/[A-ZÇĞİÖŞÜ]/u.test(a.password)||!/[a-zçğıöşü]/u.test(a.password)||!/\d/.test(a.password)||!/[^\p{L}\p{N}]/u.test(a.password))throw new Error('Yönetici parolası güvenlik politikasını karşılamıyor.');if(!state.data.site.supportEmail)state.data.site.supportEmail=a.email}
async function smtpTest(){const form=document.querySelector('#smtp-form');readForm(form,state.data.smtp);state.smtpTested=false;render();const button=document.querySelector('#smtp-test');button.disabled=true;button.innerHTML='<span class="spinner"></span>Test ediliyor';try{await api('/api/install/test-smtp',{method:'POST',body:{smtp:state.data.smtp,recipient:state.data.admin.email}});state.smtpTested=true;toast('SMTP test e-postası gönderildi.');render();setTimeout(()=>{state.step=4;render()},500)}catch(e){render();toast(e.message,'error')}}
async function complete(){if(!document.querySelector('#final-confirm')?.checked)return;state.installing=true;const btn=document.querySelector('#complete-install');btn.disabled=true;btn.innerHTML='<span class="spinner"></span>Kuruluyor';try{state.complete=await api('/api/install/complete',{method:'POST',body:{...state.data,smtpTestRecipient:state.data.admin.email}});sessionStorage.removeItem('oc_install_token');render()}catch(e){state.installing=false;render();toast(e.message,'error')}}
async function pollRestart(){const node=document.querySelector('#restart-state');for(let i=0;i<80;i++){await new Promise(r=>setTimeout(r,500));try{const r=await fetch('/api/health',{cache:'no-store'});const d=await r.json();if(r.ok&&d.installed&&d.runtimeReady){node.className='smtp-state ok';node.textContent='✓ Sunucu üretim modunda çalışıyor. Yönetim paneli hazır.';return}}catch{} }node.textContent='Sunucu otomatik yeniden başlamadı. Başlatma penceresini kapatıp BASLAT-WINDOWS.bat dosyasını yeniden çalıştırın.'}
document.addEventListener('submit',e=>{if(e.target.id!=='step-form')return;e.preventDefault();try{if(state.step===1){const fd=Object.fromEntries(new FormData(e.target));state.token=fd.installToken.trim();sessionStorage.setItem('oc_install_token',state.token);state.data.site.appOrigin=fd.appOrigin.trim();state.data.site.timezone=fd.timezone;state.step=2}else if(state.step===2){const fd=Object.fromEntries(new FormData(e.target));state.data.site.appName=fd.appName;state.data.site.companyName=fd.companyName;state.data.site.supportEmail=fd.supportEmail;state.data.admin={name:fd.adminName,email:fd.adminEmail,password:fd.adminPassword,confirmPassword:fd.adminConfirmPassword};validateStep2();state.data.smtp.fromEmail=state.data.admin.email;state.data.smtp.fromName=state.data.site.appName;state.step=3}render()}catch(err){toast(err.message,'error')}});
document.addEventListener('click',e=>{if(e.target.closest('[data-back]')){state.step=Math.max(1,state.step-1);render()}if(e.target.closest('#smtp-test'))smtpTest();if(e.target.closest('#complete-install'))complete()});document.addEventListener('change',e=>{if(e.target.id==='final-confirm')document.querySelector('#complete-install').disabled=!e.target.checked});
(async()=>{try{state.status=await api('/api/install/status');if(state.status.installed)state.token='';render()}catch(e){root.innerHTML=`<div class="fatal card"><h1>Kurulum başlatılamadı</h1><p>${esc(e.message)}</p></div>`}})();
