{
  config,
  lib,
  pkgs,
  ...
}: {
  options.services.virt-home-assistant = {
    enable = lib.mkEnableOption "Wether to enable home assistant virtual machine";
    networkBridge = lib.mkOption {
      type = lib.types.str;
      description = "what network bridge should we attach to the image";
    };
    hostDevice = lib.mkOption {
      type = lib.types.str;
      description = "what host devices should be attached to the image";
    };
    initialVersion = lib.mkOption {
      type = lib.types.str;
      description = "what home assistant image version should we pull for initial instal";
      default = "15.0";
    };
    imageName = lib.mkOption {
      type = lib.types.str;
      description = "where should the image be installed to";
      default = "home-assistant.qcow2";
    };
    installLocation = lib.mkOption {
      type = lib.types.str;
      description = "where should the image be installed to";
      default = "/etc/hass";
    };
    virtualMachineName = lib.mkOption {
      type = lib.types.str;
      description = "what name should we give the virtual machine";
      default = "home-assistant";
    };
    subdomain = lib.mkOption {
      type = lib.types.str;
      description = "subdomain of base domain that home-assistant will be hosted at";
      default = "home-assistant";
    };
  };
  config = lib.mkIf config.services.virt-home-assistant.enable (lib.mkMerge [
    {
      # environment.systemPackages = with pkgs; [
      #   virt-manager
      # ];

      # TODO: move this to external module and just have an assertion here that its enabled
      # enable virtualization on the system
      virtualisation = {
        libvirtd = {
          enable = true;
          qemu.ovmf.enable = true;
        };
      };

      # TODO: deactivation script?
      # create service to install and start the container
      systemd.services.virt-install-home-assistant = let
        # TODO: all of these need to be escaped to be used in commands reliably
        bridgedNetwork = config.services.virt-home-assistant.networkBridge;
        hostDevice = config.services.virt-home-assistant.hostDevice;
        virtualMachineName = config.services.virt-home-assistant.virtualMachineName;
        imageName = config.services.virt-home-assistant.imageName;
        installLocation = config.services.virt-home-assistant.installLocation;
        installImage = "${installLocation}/${imageName}";
        initialVersion = config.services.virt-home-assistant.initialVersion;

        home-assistant-qcow2 = pkgs.fetchurl {
          name = "home-assistant.qcow2";
          url = "https://github.com/home-assistant/operating-system/releases/download/${initialVersion}/haos_ova-${initialVersion}.qcow2.xz";
          hash = "sha256-V1BEjvvLNbMMKJVyMCmipjQ/3owoJteeVxoF9LDHo1U=";
          postFetch = ''
            cp $out src.xz
            rm -r $out
            ${pkgs.xz}/bin/unxz src.xz --stdout > $out/${imageName}
          '';
        };

        # Write a script to install the Home Assistant OS qcow2 image
        virtInstallScript = pkgs.writeShellScriptBin "virt-install-hass" ''
          # Copy the initial image out of the package store to the install location if we don't have one yet
          if [ ! -f ${installImage} ]; then
            cp ${home-assistant-qcow2} ${installLocation}
          fi

          # Check if VM already exists, and other pre-conditions
          if ! ${pkgs.libvirt}/bin/virsh list --all | grep -q ${virtualMachineName}; then
            ${pkgs.virt-manager}/bin/virt-install --name ${virtualMachineName} \
              --description "Home Assistant OS" \
              --os-variant=generic \
              --boot uefi \
              --ram=2048 \
              --vcpus=2 \
              --import \
              --disk ${installImage},bus=sata \
              --network bridge=${bridgedNetwork} \
              --host-device ${hostDevice} \
              --graphics none
            ${pkgs.libvirt}/bin/virsh autostart ${virtualMachineName}
          fi
        '';
      in {
        description = "Install and start Home Assistant";
        wantedBy = ["multi-user.target"];
        after = ["local-fs.target"];
        requires = ["libvirtd.service"];
        serviceConfig.Type = "oneshot";
        serviceConfig = {
          ExecStart = "${virtInstallScript}/bin/virt-install-hass";
        };
      };

      # TODO: figure out what we need to proxy to the virtual image
      # host = {
      #   reverse_proxy.subdomains.${config.services.virt-home-assistant.subdomain} = {
      #     target = "http://localhost:${toString config.services.home-assistant.config.http.server_port}";

      #     websockets.enable = true;
      #     forwardHeaders.enable = true;

      #     extraConfig = ''
      #       add_header Upgrade $http_upgrade;
      #       add_header Connection \"upgrade\";

      #       proxy_buffering off;

      #       proxy_read_timeout 90;
      #     '';
      #   };
      # };
    }
    (lib.mkIf config.services.fail2ban.enable {
      # TODO: figure out how to write a config for this, prob based on nginx proxy logs?
    })
    (lib.mkIf config.host.impermanence.enable {
      # assertions = [
      #   {
      #     assertion = config.services.virt-home-assistant.installLocation == configDir;
      #     message = "home assistant install location does not match persistence";
      #   }
      # ];
      environment.persistence."/persist/system/root" = {
        enable = true;
        hideMounts = true;
        directories = [
          {
            directory = config.services.virt-home-assistant.installLocation;
          }
        ];
      };
    })
  ]);
}