'use strict';
let state, dashboard;
const el=id=>document.getElementById(id), money=n=>'$'+Number(n).toFixed(2), date=n=>n?new Date(n*1000).toLocaleDateString():'—';
function notice(message){el('message').textContent=message;el('message').hidden=false;el('message').scrollIntoView({block:'nearest'});}
async function api(action,data){const r=await fetch('api.php?action='+action,{method:data?'POST':'GET',headers:data?(data instanceof FormData?{'X-CSRF-Token':state.csrf}:{'Content-Type':'application/json','X-CSRF-Token':state.csrf}):{},body:data?(data instanceof FormData?data:JSON.stringify(data)):undefined});let j;try{j=await r.json();}catch{throw new Error('Server did not return JSON. Check PHP and deployment.');}if(!r.ok)throw new Error(j.error||'Request failed.');return j;}
function node(tag,text,cls){const n=document.createElement(tag);if(text!==undefined)n.textContent=text;if(cls)n.className=cls;return n;}
function table(target,headers,rows){const t=node('table'),head=node('tr');headers.forEach(h=>head.append(node('th',h)));const thead=node('thead');thead.append(head);t.append(thead);const body=node('tbody');rows.forEach(row=>{const tr=node('tr');row.forEach(c=>{const td=node('td');td.append(c instanceof Node?c:node('span',String(c)));tr.append(td);});body.append(tr);});t.append(body);el(target).replaceChildren(t);}
function data(form){return Object.fromEntries(new FormData(form));}
async function guarded(button,fn){button.disabled=true;try{await fn();}catch(e){notice(e.message);}finally{button.disabled=false;}}
async function load(){state=await api('status');if(document.body.dataset.page==='account')await account();else await admin();}
async function account(){
 const u=state.user;if(u){location.replace(state.owner?'/image-studio/owner-portal/':['staff','viewer','reseller'].includes(u.role)?'/image-studio/team-portal/':'/image-studio/studio.php');return;}
 el('auth-card').hidden=!!u;el('balance-card').hidden=!u;
 el('manage-link').hidden=!(state.owner||u?.role==='reseller');
 if(u){el('account-name').textContent=u.email;el('balance').textContent=u.credits+' credits available';el('expiry').textContent=u.expires?('Valid until '+date(u.expires)):'Contact us on WhatsApp to activate credits';el('daily').textContent='Daily limit: '+u.daily_limit+' credits'+(u.disabled?' · Access paused':'');}
}
async function admin(){document.querySelectorAll('.portal-sidebar nav a').forEach(a=>{if(!a.getAttribute('href').startsWith('#'))return;const hash=new URL(a.href).hash;a.href=location.pathname+hash;});const team=['staff','viewer'].includes(state.user?.role),manager=state.owner||team||state.user?.role==='reseller',viewer=state.user?.role==='viewer';el('locked').hidden=manager;el('dashboard').hidden=!manager;if(!manager)return;
 dashboard=await api(state.owner||team?'admin':'reseller');el('setup-card').hidden=!state.owner;el('profit-card').hidden=!(state.owner||team);el('approval-card').hidden=!(state.owner||state.user?.role==='staff');el('stalled-card').hidden=!state.owner;el('role-field').hidden=!state.owner;el('disable-field').hidden=!state.owner;
 el('pool').textContent=team?(viewer?'View-only team access. Credit changes and approvals are disabled.':'Team access: manage customer top-ups and verified payments. Owner settings are private.'):state.owner?'Owner access: manage accounts, access, credit grants and verified payment sales.':'Your pool: '+state.user.credits+' credits. Each customer credit is deducted from this pool.';el('remove-field').hidden=!state.owner;
 el('api-nav').hidden=!state.owner;el('team-nav').hidden=!state.owner;el('team-nav').onclick=e=>{e.preventDefault();el('add-team').click();};el('portal-name').textContent=state.owner?'Owner portal':'Team portal';el('assign-team-field').hidden=!state.owner;el('owner-login-card').hidden=!(state.owner&&state.user.email==='studio-owner');el('team-help').hidden=!state.owner;el('add-team').hidden=!state.owner;
 if(state.owner){const f=el('settings-form');for(const[k,v]of Object.entries(state.settings)){const field=f.elements.namedItem(k);if(field){if(field.type==='checkbox')field.checked=!!v;else field.value=v;}}el('connection-state').textContent=state.configured?'Provider key configured. Test an image to verify generation. New generation requires account credits.':'API not connected. Paste your key above.';profit();syncProvider();
 table('orders-table',['Customer','Plan','USD / PKR','Reference','Status','Action'],dashboard.orders.map(o=>{const actions=node('div');if(o.status==='pending'&&(state.owner||state.user?.role==='staff')){for(const a of ['approve','reject']){const b=node('button',a==='approve'?'Verify & approve':'Reject','secondary');b.onclick=()=>{if(a==='approve'&&!confirm('Payment verified in your bank / wallet? Activate this 30-day plan?'))return;guarded(b,async()=>{await api(a,{id:o.id});await load();});};actions.append(b);}}return[o.email,o.plan,money(o.price)+' / '+Number(o.pkr).toFixed(2),o.reference,o.status,actions];}));
 el('stalled').replaceChildren();for(const j of dashboard.pending_jobs){const row=node('p',j.id+' · '+j.credits+' credits · '+date(j.created)+' ');const b=node('button','Refund stalled request','secondary');b.disabled=j.created>Date.now()/1000-600;b.onclick=()=>{if(confirm('Provider processing has stopped? Refund customer credits and retain estimated API cost?'))guarded(b,async()=>{await api('resolve_job',{id:j.id});await load();});};row.append(b);el('stalled').append(row);}
 }
 if(state.user?.role==='staff'){table('orders-table',['Email','Plan','Amount','Reference','Status','Action'],dashboard.orders.map(o=>{const group=node('div');if(o.status==='pending'){for(const action of ['approve','reject']){const b=node('button',action,'secondary');b.onclick=()=>{if(action==='approve'&&!confirm('Payment verified? Activate this plan?'))return;guarded(b,async()=>{await api(action,{id:o.id});await load();});};group.append(b);}}return[o.email,o.plan,money(o.price),o.reference,o.status,group];}));}
 if(team){teamMetrics();}if(state.owner){const pick=el('user-form').elements.assigned_team;pick.replaceChildren(new Option('Owner / Unassigned',''));dashboard.users.filter(u=>['staff','viewer'].includes(u.role)&&!u.disabled).forEach(u=>pick.add(new Option(u.email,u.id)));}
 const select=el('user-select');select.replaceChildren();const fresh=node('option','Add new customer');fresh.value='';select.append(fresh);dashboard.users.filter(u=>u.id!=='owner'&&(state.owner||!team||u.role==='customer')).forEach(u=>{const option=node('option',u.email);option.value=u.id;select.append(option);});el('user-form').elements.fx.value=state.fx_rate;selectUser();if(viewer){Array.from(el('user-form').elements).forEach(field=>field.disabled=true);}
 table('users-table',['Email','Role','Available','Used','Daily limit','Expiry','Status','Action'],dashboard.users.map(u=>[u.email,u.role,u.expires>Date.now()/1000?u.credits:0,u.used,u.daily_limit,date(u.expires),u.disabled?'Paused':u.expires>Date.now()/1000?'Activated':'Awaiting activation',manageButton(u)]));
 table('ledger-table',['Customer','Credits','PKR','USD','Rate','Reason','Date','Invoice / receipt'],dashboard.ledger.map(l=>[l.email,l.credits,Number(l.pkr).toFixed(2),money(l.usd),l.fx,l.reason,date(l.created),receiptActions(l)]));
}
function manageButton(u){const b=node('button','Activate / Top-up','secondary');b.disabled=u.id==='owner'||state.user?.role==='viewer'||(state.user?.role==='staff'&&u.role!=='customer');b.onclick=()=>{el('user-select').value=u.id;selectUser();el('user-form').scrollIntoView({behavior:'smooth',block:'start'});};return b;}
function receiptActions(l){const group=node('div');if(state.user?.role==='viewer')return node('span',l.has_receipt?'Attached':'—');if(l.has_receipt){const view=node('a','View receipt');view.href='api.php?action=receipt&id='+l.id;view.target='_blank';view.rel='noopener noreferrer';group.append(view);}const file=node('input');file.type='file';file.accept='image/png,image/jpeg,image/webp';file.style.maxWidth='190px';file.setAttribute('aria-label','Attach receipt for '+l.email);file.onchange=()=>{if(!file.files[0])return;const body=new FormData();body.append('ledger_id',l.id);body.append('receipt',file.files[0]);guarded(file,async()=>{await api('upload_receipt',body);notice('Receipt saved privately.');await load();});};group.append(file);return group;}
function selectUser(){const f=el('user-form'),u=dashboard.users.find(u=>u.id===f.elements.id.value);f.elements.email.value=u?.email||'';f.elements.email.disabled=!!u;f.elements.password.value='';f.elements.password.disabled=!!u;f.elements.email.required=!u;f.elements.password.required=!u;f.elements.credits.value=0;f.elements.remove_credits.value=0;f.elements.pkr.value=0;f.elements.daily_limit.value=u?.daily_limit||20;f.elements.role.value=u?.role||'customer';f.elements.assigned_team.value=u?.parent_id||'';f.elements.disabled.checked=!!u?.disabled;f.elements.reason.value='';delete f.dataset.transactionId;el('receipt-file').value='';}
function conversion(){const p=Number(el('convert-pkr').value),rate=Number(el('convert-fx').value);el('conversion').textContent=rate>0&&p>=0?money(p/rate):'Enter a valid amount and rate.';}
function teamMetrics(){el('metrics').replaceChildren();for(const[label,value]of [['Assigned customers',dashboard.registered_users],['My paid sales',dashboard.payments],['My recorded revenue',money(dashboard.revenue)],['Customer credits remaining',dashboard.remaining_credits]]){const c=node('div',undefined,'metric');c.append(node('small',label),node('strong',value));el('metrics').append(c);}}
function profit(){el('metrics').replaceChildren();for(const[label,value]of [['Customers',dashboard.registered_users],['Paid sales',dashboard.payments],['Sales revenue',money(dashboard.revenue)],['API cost / estimate',money(dashboard.api_cost)],['Customer credits remaining',dashboard.remaining_credits],['Processed requests',Number(dashboard.usage.total||0)]]){const c=node('div',undefined,'metric');c.append(node('small',label),node('strong',value));el('metrics').append(c);}}
async function syncProvider(){if(!state?.owner)return;loadEmailDelivery();const box=el('provider-sync');try{const p=await api('provider_balance');box.textContent=!p.connected?p.message:p.balance===null?p.message:'Runware balance: '+(p.currency==='USD'?money(p.balance):p.balance+' '+p.currency)+' · Free balance: '+money(p.free_balance||0)+' · '+(p.stale?'Sync delayed. Last update: ':'Synced: ')+(p.updated?new Date(p.updated*1000).toLocaleTimeString():'waiting');}catch{box.textContent='Balance sync unavailable. Retry shortly.';}}
async function loadEmailDelivery(){
 let section=el('email-delivery-panel');
 if(!section){section=node('section');section.id='email-delivery-panel';section.append(node('h3','Email delivery status'),node('p','Host acceptance is not proof of inbox delivery. Confirm delivery in cPanel Track Delivery; check SPF, DKIM and DMARC.'),node('div'));section.lastChild.id='email-delivery-table';el('setup-card').append(section);}
 try{const result=await api('email_delivery');table('email-delivery-table',['Email','Type','Status','Date'],result.deliveries.map(e=>[e.email,e.kind,e.status,date(e.created)]));}
 catch{el('email-delivery-table').textContent='Email status unavailable. Ensure the latest API files are uploaded.';}
}
document.addEventListener('DOMContentLoaded',async()=>{try{state=await api('status');const token=new URLSearchParams(location.hash.slice(1)).get('owner');history.replaceState(null,'',location.origin+location.pathname.replace(/^\/+/, '/')+location.search);if(token)await api('owner_login',{token});await load();}catch(e){notice(e.message);}
 if(el('auth-form')){
  const signup=location.pathname.replace(/^\/+/, '/').replace(/\/$/,'')==='/image-studio/signup'||new URLSearchParams(location.search).get('mode')==='signup';
  if(location.pathname==='/image-studio/backend-login'){el('auth-switch').hidden=true;document.querySelector('.auth-free-note').hidden=true;}
  el('auth-title').textContent=signup?'Start Free. Create Something Amazing.':'Welcome back to Ai luq Ai';
  el('auth-intro').textContent=signup?'3 FREE IMAGES · 2 FREE VIDEOS AT LAUNCH':'Access Image Studio, Video Studio and your separate credit balances.';
  if(signup){el('auth-intro').classList.add('free-offer');document.querySelector('.auth-free-note').textContent='Images: eligible Gmail verification required · 7-day validity · No card needed. Videos: two 5-second clips planned for launch, not available yet. Check Inbox/Spam for verification; trial limits apply.';}
  const signupEmail=el('auth-form').elements.email;
  if(signup){signupEmail.placeholder='you@gmail.com';signupEmail.pattern='[^@\\s]+@gmail\\.com';signupEmail.title='Use an @gmail.com address for sign-up.';signupEmail.addEventListener('input',()=>{signupEmail.value=signupEmail.value.toLowerCase();});}
  el('auth-submit').textContent=signup?'Create account & open studio →':'Login & open studio →';
  el('auth-form').elements.password.autocomplete=signup?'new-password':'current-password';
  el('auth-switch').href=signup?'/image-studio/login':'/image-studio/signup';
  el('auth-switch').textContent=signup?'Already registered? Login →':'New here? Sign Up Free →';
  if(!signup){const forgot=node('a','Forgot password?');forgot.href='/image-studio/forgot-password';forgot.id='forgot-password-link';el('auth-switch').after(forgot);}
  el('auth-form').onsubmit=e=>{e.preventDefault();guarded(e.submitter,async()=>{await api(signup?'register':'login',data(e.target));e.target.reset();await load();});};
  el('logout').onclick=()=>guarded(el('logout'),async()=>{await api('logout',{});await load();});
 }
 if(el('owner-login-form')){el('owner-login-form').onsubmit=e=>{e.preventDefault();guarded(e.submitter,async()=>{await api('owner_credentials',data(e.target));e.target.reset();notice('Owner login created. Use /image-studio/backend-login next time.');await load();});};el('admin-signout').onclick=()=>guarded(el('admin-signout'),async()=>{await api('logout',{});location.replace('/image-studio/backend-login');});}
 if(el('runware-connect-form')){el('runware-connect-form').onsubmit=e=>{e.preventDefault();const m=el('runware-connect-message'),b=e.submitter;m.textContent='Checking Runware…';b.disabled=true;(async()=>{try{const d=data(e.target);d.provider='runware';d.standard_cost=0.03;d.premium_cost=0.05;await api('setup',d);e.target.reset();m.textContent='Runware key saved. Connection verified.';await load();}catch(error){m.textContent=error.message;}finally{b.disabled=false;}})();};}
 if(el('settings-form')){el('settings-form').onsubmit=e=>{e.preventDefault();guarded(e.submitter,async()=>{const d=data(e.target);d.sales_enabled=e.target.elements.sales_enabled.checked;await api('setup',d);e.target.elements.api_key.value='';e.target.elements.runware_api_key.value='';notice('Settings saved.');await load();});};el('user-select').onchange=selectUser;el('add-team').onclick=()=>{el('user-select').value='';selectUser();const f=el('user-form');f.elements.role.value='staff';f.elements.reason.value='New team member';f.scrollIntoView({behavior:'smooth'});f.elements.email.focus();el('customers-section').scrollIntoView({block:'start'});};el('user-form').onsubmit=e=>{e.preventDefault();guarded(e.submitter,async()=>{const d=data(e.target);d.disabled=e.target.elements.disabled.checked;if(!e.target.dataset.transactionId)e.target.dataset.transactionId=crypto.randomUUID().replaceAll('-','');d.transaction_id=e.target.dataset.transactionId;const result=await api('manage_user',d);const file=el('receipt-file').files[0];if(file){try{const body=new FormData();body.append('ledger_id',result.ledger_id);body.append('receipt',file);await api('upload_receipt',body);}catch(error){notice('Credits saved. Receipt was not saved: '+error.message+'. Attach it from the sales ledger.');await load();return;}}notice('User activated / credits updated. Sale and receipt saved.');await load();});};const sale=node('p','Converted sale: $0.00');el('user-form').elements.pkr.parentElement.after(sale);const calculate=()=>{const f=el('user-form'),rate=Number(f.elements.fx.value);sale.textContent='Converted sale: '+(rate>0?money(Number(f.elements.pkr.value)/rate):'Enter a valid exchange rate.');};el('user-form').elements.pkr.oninput=calculate;el('user-form').elements.fx.oninput=calculate;el('refresh').onclick=()=>guarded(el('refresh'),load);}
});

let autoSyncBusy=false;
setInterval(async()=>{
 if(document.body.dataset.page!=='admin'||document.hidden||autoSyncBusy||!state?.user)return;
 const active=document.activeElement;if(active?.matches('input,textarea,select')||document.querySelector('button:disabled.primary')||el('user-form')?.elements.reason.value||el('settings-form')?.elements.runware_api_key.value||el('settings-form')?.elements.api_key.value||el('runware-connect-form')?.elements.runware_api_key.value)return;
 autoSyncBusy=true;try{await load();}catch{}finally{autoSyncBusy=false;}
},60000);
