from __future__ import annotations

import json
from pathlib import Path
from typing import Any, Dict


class FirewallRemediation:
    """Track and restore firewall rule configuration with reversible rollback support."""

    def __init__(self, firewall_state_path: str | Path):
        self.firewall_state_path = Path(firewall_state_path)
        self.firewall_state_path.parent.mkdir(parents=True, exist_ok=True)
        if not self.firewall_state_path.exists():
            self.firewall_state_path.write_text(json.dumps({"rules": {}}, indent=2, sort_keys=True), encoding="utf-8")
        self._backup_store = self.firewall_state_path.parent / "firewall_state_backup.json"

    def load_state(self) -> Dict[str, Any]:
        try:
            payload = json.loads(self.firewall_state_path.read_text(encoding="utf-8"))
        except (json.JSONDecodeError, OSError):
            payload = {"rules": {}}
        if not isinstance(payload, dict):
            payload = {"rules": {}}
        if "rules" not in payload or not isinstance(payload["rules"], dict):
            payload["rules"] = {}
        return payload

    def capture_snapshot(self) -> Dict[str, Any]:
        current = self.load_state()
        self._backup_store.write_text(json.dumps(current, indent=2, sort_keys=True), encoding="utf-8")
        return {"before_state": current, "backup_path": str(self._backup_store)}

    def set_rule(self, rule_name: str, **updates: Any) -> Dict[str, Any]:
        state = self.load_state()
        if "rules" not in state or not isinstance(state["rules"], dict):
            state["rules"] = {}
        self.capture_snapshot()

        current = state["rules"].get(rule_name, {})
        if not isinstance(current, dict):
            current = {}
        current.update(updates)
        state["rules"][rule_name] = current
        self._write_state(state)
        return {"name": rule_name, "status": "updated", "value": current}

    def restore_rule(self, rule_name: str) -> Dict[str, Any]:
        if self._backup_store.exists():
            backup = json.loads(self._backup_store.read_text(encoding="utf-8"))
            if isinstance(backup, dict) and "rules" in backup and isinstance(backup["rules"], dict) and rule_name in backup["rules"]:
                state = self.load_state()
                state["rules"][rule_name] = backup["rules"][rule_name]
                self._write_state(state)
                return {"name": rule_name, "status": "restored", "value": backup["rules"][rule_name]}

        state = self.load_state()
        if "rules" not in state or rule_name not in state["rules"]:
            return {"name": rule_name, "status": "missing"}
        del state["rules"][rule_name]
        self._write_state(state)
        return {"name": rule_name, "status": "restored", "value": None}

    def _write_state(self, state: Dict[str, Any]) -> None:
        self.firewall_state_path.write_text(json.dumps(state, indent=2, sort_keys=True), encoding="utf-8")
