import json from datetime import datetime from sqlmodel import Session from app.database import get_engine from app.ha_client import ha_client from app.models import EntityCache, EntityFlag, AuditLog def _get_current_state(session: Session, entity_id: str) -> str | None: """Récupère l'état actuel d'une entité depuis le cache.""" entity = session.get(EntityCache, entity_id) return entity.state if entity else None def _save_original_state(session: Session, entity_id: str): """Sauvegarde l'état original avant désactivation.""" flag = session.get(EntityFlag, entity_id) if not flag: flag = EntityFlag(entity_id=entity_id) # Ne sauvegarder que si pas déjà désactivé (garder le vrai état original) if not flag.original_state: flag.original_state = _get_current_state(session, entity_id) flag.disabled_at = datetime.utcnow() session.add(flag) return flag def _clear_original_state(session: Session, entity_id: str): """Efface l'état original lors de la réactivation.""" flag = session.get(EntityFlag, entity_id) if flag: flag.original_state = None flag.disabled_at = None session.add(flag) async def disable_entity(entity_id: str) -> dict: mode = "local_flag" error = "" # Sauvegarder l'état original with Session(get_engine()) as session: _save_original_state(session, entity_id) session.commit() # Tenter désactivation via HA registry try: await ha_client.update_entity_registry(entity_id, disabled_by="user") mode = "ha_registry" except Exception as e: error = str(e) # Fallback : flag local with Session(get_engine()) as session: flag = session.get(EntityFlag, entity_id) if not flag: flag = EntityFlag(entity_id=entity_id) flag.ignored_local = True session.add(flag) session.commit() _log_action("disable", [entity_id], mode, error) return {"entity_id": entity_id, "mode": mode, "error": error} async def enable_entity(entity_id: str) -> dict: mode = "local_flag" error = "" try: await ha_client.update_entity_registry(entity_id, disabled_by=None) mode = "ha_registry" except Exception as e: error = str(e) with Session(get_engine()) as session: flag = session.get(EntityFlag, entity_id) if flag: flag.ignored_local = False session.add(flag) session.commit() # Effacer l'état original with Session(get_engine()) as session: _clear_original_state(session, entity_id) session.commit() _log_action("enable", [entity_id], mode, error) return {"entity_id": entity_id, "mode": mode, "error": error} def set_flag(entity_ids: list[str], action: str) -> list[dict]: results = [] with Session(get_engine()) as session: for eid in entity_ids: flag = session.get(EntityFlag, eid) if not flag: flag = EntityFlag(entity_id=eid) if action == "favorite": flag.favorite = True elif action == "unfavorite": flag.favorite = False elif action == "ignore": # Sauvegarder l'état original avant ignore if not flag.original_state: flag.original_state = _get_current_state(session, eid) flag.disabled_at = datetime.utcnow() flag.ignored_local = True elif action == "unignore": flag.ignored_local = False flag.original_state = None flag.disabled_at = None session.add(flag) results.append({"entity_id": eid, "action": action, "ok": True}) session.commit() _log_action(action, entity_ids, "ok", "") return results def _log_action(action: str, entity_ids: list[str], result: str, error: str): with Session(get_engine()) as session: log = AuditLog( ts=datetime.utcnow(), action=action, entity_ids_json=json.dumps(entity_ids), result=result, error=error, ) session.add(log) session.commit()