/* Admin Alfred Glass — style harmonisé et configuration du cadre Maison. */
(() => {
'use strict';
const page = document.body.dataset.page;
if (!['config','surveillance'].includes(page)) return;
document.body.classList.add('alfred-admin-glass');
const rail = document.createElement('aside');
rail.className = 'ag-rail';
rail.setAttribute('aria-label','Navigation Alfred');
rail.innerHTML = `⌂Accueil⚙Réglages▤Suivi`;
document.querySelector('.admin-layout')?.prepend(rail);
const brand = document.querySelector('.admin-header .brand small');
if (brand) brand.textContent = 'Assistant vocal · Centre de contrôle';
const main = document.getElementById('mainArea');
if (!main || page !== 'config') return;
const editor = document.createElement('section');
editor.id='agMaisonEditor';
editor.className='panel ag-maison-editor';
editor.innerHTML = `
⌂
Cadre « Maison » de l’accueil
Personnalise jusqu’à trois informations affichées en haut de l’écran principal
Choisis un compteur global ou une entité précise de Home Assistant, et personnalise le libellé. Les valeurs sont actualisées automatiquement sans redémarrer Alfred.
`;
main.querySelector('.restart-panel')?.before(editor);
const types = [
['lights_on','Nombre de lumières allumées'],
['covers_closed','Nombre de volets fermés'],
['indoor_temperature','Température intérieure'],
['entity','Entité Home Assistant précise']
];
const defaults = [
{kind:'lights_on',label:'Lumières allumées'},
{kind:'covers_closed',label:'Volets fermés'},
{kind:'indoor_temperature',label:'Température intérieure'}
];
const list = editor.querySelector('#agMaisonRows');
const message = editor.querySelector('#agMaisonMessage');
const add = editor.querySelector('#agAddMaison');
let entities = [];
let rows = defaults.map(x=>({...x}));
let busy=false;
const msg=(text,error=false)=>{message.textContent=text;message.classList.toggle('ag-error',error);};
const el=(name,cls,text)=>{const node=document.createElement(name);if(cls)node.className=cls;if(text!==undefined)node.textContent=text;return node;};
function render() {
list.replaceChildren();
rows.forEach((row,i)=>{
const box=el('div','ag-row');
const header=el('div','ag-row-header');
header.append(el('strong','',`Ligne ${i+1}`));
const nav=el('div','ag-row-buttons');
const action=(name,symbol,title,fn)=>{
const b=el('button','ag-small-button',symbol);b.type='button';b.title=title;b.setAttribute('aria-label',title);
b.disabled=busy;b.addEventListener('click',fn);nav.append(b);
};
action('up','↑','Monter',()=>{if(i){[rows[i-1],rows[i]]=[rows[i],rows[i-1]];render();}});
action('down','↓','Descendre',()=>{if(i{if(rows.length>1){rows.splice(i,1);render();}});
header.append(nav);box.append(header);
const settings=el('div','ag-row-fields');
const kindWrap=el('label','ag-field');kindWrap.append(el('span','', 'Information affichée'));
const kind=el('select');
types.forEach(([value,txt])=>{const o=el('option','',txt);o.value=value;o.selected=row.kind===value;kind.append(o);});
kind.addEventListener('change',()=>{row.kind=kind.value;if(row.kind==='entity'&&!row.entity_id)row.entity_id=entities[0]?.id||'';render();});
kindWrap.append(kind);settings.append(kindWrap);
const labelWrap=el('label','ag-field');labelWrap.append(el('span','', 'Intitulé personnalisé'));
const text=el('input');text.type='text';text.maxLength=38;text.required=true;text.value=row.label||'';
text.addEventListener('input',()=>{row.label=text.value;});labelWrap.append(text);settings.append(labelWrap);
if(row.kind==='entity'){
const entityWrap=el('label','ag-field ag-wide');entityWrap.append(el('span','', 'Entité Home Assistant'));
const field=el('input');field.type='text';field.maxLength=120;
field.value=row.entity_id||'';field.placeholder='sensor.salon_temperature';
field.setAttribute('list',`agEntityList${i}`);
field.addEventListener('input',()=>{row.entity_id=field.value.trim();});
const choices=el('datalist');choices.id=`agEntityList${i}`;
entities.forEach(entry=>{const o=el('option');o.value=entry.id;o.label=entry.name;choices.append(o);});
entityWrap.append(field,choices);
const helper=el('small','',entities.length
? 'Choisis une entité proposée ou saisis son identifiant.'
: 'Saisis un identifiant comme sensor.salon_temperature si Home Assistant est inaccessible.');
entityWrap.append(helper);settings.append(entityWrap);
}
box.append(settings);list.append(box);
});
add.disabled=rows.length>=3 || busy;
}
function tryAuthFetch(url,options={}){
return fetch('/api/control/auth',{cache:'no-store',credentials:'same-origin'}).then(async r=>{
const a=await r.json();if(!a.authenticated)throw new Error('Connexion administrateur nécessaire.');
const headers=options.method==='POST'?{'Content-Type':'application/json','X-Alfred-CSRF':a.csrf}:{};
const response=await fetch(url,{...options,headers,credentials:'same-origin',cache:'no-store'});
const body=await response.json().catch(()=>({}));
if(!response.ok)throw new Error(body.error||`Erreur HTTP ${response.status}`);
return body;
});
}
async function refresh(){
if(busy)return;
busy=true;
try{
const config=await tryAuthFetch('/api/control/home-card');
rows=Array.isArray(config.rows)?config.rows:defaults.map(x=>({...x}));
const response=await tryAuthFetch('/api/control/home-entities').catch(err=>{msg('Liste des entités indisponible : '+err.message,true);return null;});
entities=response?.entities||[];
if(response)msg(`${entities.length} entités Home Assistant disponibles.`);
}catch(e){msg(e.message,true);}
finally{busy=false;render();}
}
editor.querySelector('#agDefaultMaison').addEventListener('click',()=>{rows=defaults.map(x=>({...x}));render();msg('Valeurs par défaut prêtes à enregistrer.');});
add.addEventListener('click',()=>{if(rows.length>=3)return;rows.push({kind:'entity',label:'Information',entity_id:entities[0]?.id||''});render();});
editor.querySelector('#agSaveMaison').addEventListener('click',async()=>{
if(busy)return;
busy=true;
try{
const result=await tryAuthFetch('/api/control/home-card',{method:'POST',body:JSON.stringify({rows})});
rows=result.rows;
msg('Cadre Maison enregistré. Les changements apparaîtront sur l’accueil en quelques secondes.');
}catch(e){msg('Impossible d’enregistrer : '+e.message,true);}
finally{busy=false;render();}
});
let loaded=false;
async function checkLogin(){
if(!main.hidden&&!loaded){loaded=true;await refresh();}
if(main.hidden)loaded=false;
}
new MutationObserver(checkLogin).observe(main,{attributes:true,attributeFilter:['hidden']});
checkLogin();
})();