{ config, pkgs, ... }:
let
  mosquittoPort = 1883;
  zigbee2mqttPort = 8080;
  # "sha256-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA="
  ha-bambulab = pkgs.stdenv.mkDerivation {
    pname = "ha-bambulab";
    version = "v2.1.5";  # Update with correct version
    
    src = pkgs.fetchFromGitHub {
      owner = "greghesp";  # Update with correct owner
      repo = "ha-bambulab";  # Update with correct repo name
      rev = "v2.1.5";  # Or specific tag/commit 
      sha256 = "sha256-iVcNFdkzdMVjbQuzrTLib8fhirnc+OJdPzM60EnyVe0=";  # Replace with actual hash
    };
    
    installPhase = ''
      mkdir -p $out/custom_components
      cp -r custom_components/bambu_lab $out/custom_components/
    '';
  };
  ha-gehome = pkgs.stdenv.mkDerivation {
    pname = "ha-gehome";
    version = "v2025.2.1";  # Update with correct version
    
    src = pkgs.fetchFromGitHub {
      owner = "simbaja";  # Update with correct owner
      repo = "ha_gehome";  # Update with correct repo name
      rev = "v2025.2.1";  # Or specific tag/commit 
      sha256 = "sha256-nb+KrJoWqvhqH6E7A22xXwQzTYp7yn+hl9WRDXn95Cc=";  # Replace with actual hash
    };
    
    installPhase = ''
      mkdir -p $out/custom_components
      cp -r custom_components/ge_home $out/custom_components/
    '';
  };
  ha-mail-and-packages = pkgs.stdenv.mkDerivation {
    pname = "Home-Assistant-Mail-And-Packages";
    version = "0.4.2";  # Update with correct version
    
    src = pkgs.fetchFromGitHub {
      owner = "moralmunky";  # Update with correct owner
      repo = "Home-Assistant-Mail-And-Packages";  # Update with correct repo name
      rev = "0.4.2";  # Or specific tag/commit 
      sha256 = "sha256-5LBTlRlkSUx8DOY+F7UvUs4dzjZKdBdgnDUdK6DBdew=";  # Replace with actual hash
    };
    
    installPhase = ''
      mkdir -p $out/custom_components
      cp -r custom_components/mail_and_packages $out/custom_components/
    '';
  };
  ha-overseerr = pkgs.stdenv.mkDerivation {
    pname = "ha-overseerr";
    version = "0.1.42";  # Update with correct version
    
    src = pkgs.fetchFromGitHub {
      owner = "vaparr";  # Update with correct owner
      repo = "ha-overseerr";  # Update with correct repo name
      rev = "0.1.42";  # Or specific tag/commit 
      sha256 = "sha256-UvUowCgfay9aRV+iC/AQ9vvJzhGZbH+/1kVjxPFBKcI=";  # Replace with actual hash
    };
    
    installPhase = ''
      mkdir -p $out/custom_components
      cp -r custom_components/overseerr $out/custom_components/
    '';
  };
  ha-petlibro = pkgs.stdenv.mkDerivation {
    pname = "ha-petlibro";
    version = "v1.0.21.1";  # Update with correct version
    
    src = pkgs.fetchzip {
      url = "https://github.com/jjjonesjr33/petlibro/archive/refs/tags/v1.0.21.1.zip";
      sha256 = "sha256-3EckyAgWxlZeqy9g13yP2nKCcjnyVIp8EdiE/A1pNu4=";  # Replace with actual hash
    };
    
    installPhase = ''
      mkdir -p $out/custom_components
      cp -r custom_components/petlibro $out/custom_components/
    '';
  };
  ha-wyzeapi = pkgs.stdenv.mkDerivation {
    pname = "ha-wyzeapi";
    version = "0.1.32";  # Update with correct version
    
    src = pkgs.fetchzip {
      url = "https://github.com/SecKatie/ha-wyzeapi/archive/refs/tags/0.1.32.zip";
      sha256 = "sha256-3xUynZBEHuO2hKLYCb2sBpJAe0JF/8uKqR304Y7JQmE=";  # Replace with actual hash
    };
    
    installPhase = ''
      mkdir -p $out/custom_components
      cp -r custom_components/wyzeapi $out/custom_components/
    '';
  };
  
  # In configuration.nix or a separate file
  pythonSteam = pkgs.python3.withPackages (ps: [
    (ps.buildPythonPackage rec {
      pname = "steam";
      version = "1.4.4";  # Check for the latest version
      src = pkgs.fetchPypi {
        inherit pname version;
        sha256 = "sha256-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA="; # Get the correct hash
      };
      doCheck = false;
      propagatedBuildInputs = [ ps.requests ps.protobuf ];
    })
  ]);
in
{

  services.home-assistant = {
    enable = true;
    openFirewall = true;
    configWritable = true; # todo
    extraComponents = [
      # Components required to complete the onboarding
      "analytics"
      "google_translate"
      "met"
      "radio_browser"
      "shopping_list"
      # Recommended for fast zlib compression
      # https://www.home-assistant.io/integrations/isal
      "isal"
      "subaru"
      "vesync"
      "mqtt" # Enables MQTT integration in HA
      "ffmpeg" # Enables camera streams
      "zha" # Enables Zigbee integration
      "homekit"
      "music_assistant"
    ];
    customComponents = with pkgs.home-assistant-custom-components; [
      auth-header
    ];
    customLovelaceModules = with pkgs.home-assistant-custom-lovelace-modules; [
      atomic-calendar-revive
      bubble-card
      button-card
      hourly-weather
      mini-graph-card
      mini-media-player
      multiple-entity-row
      mushroom
      vacuum-card
      weather-chart-card
      zigbee2mqtt-networkmap
    ];
    # use postgresql instead of sqlite
    extraPackages = ps: with ps; [
      # Core functionality
      aiohttp
      aiodns
      paho-mqtt
      pillow
      pytz
      pyyaml
      sqlalchemy
      
      # Discovery & networking
      zeroconf
      netdisco
      ifaddr
      ssdp
      
      # Device protocols
      pyserial                # Serial communications
      bluepy                  # Bluetooth LE
      
      # Smart home ecosystems
      mutagen                 # Media file metadata
      pysonos                 # Sonos
      pywemo                  # Belkin WeMo
      python-miio             # Xiaomi devices
      python-kasa             # TP-Link
      
      # Sensors & monitoring
      meteocalc               # Weather calculations
      speedtest-cli           # Internet speed
      
      # Visualization & UI
      matplotlib              # Graphing
      
      # Security
      bcrypt
      cryptography
      pyjwt
      
      # Media
      ha-ffmpeg               # Camera streams
      
      # Specialized integrations
      python-matter-server    # Matter protocol
      
      # System integrations
      psutil                  # System monitoring
      
      psycopg2
      numpy
      hassil 
      pyturbojpeg
      paho-mqtt
      pychromecast
      pyatv 
      python-otbr-api 
      brother
      pyipp
      govee-ble
      adguardhome
      nextcord
      aiogithubapi
      jellyfin-apiclient-python
      pylitterbot
      dateparser
      aionut
      nextcloudmonitor
      ollama
      pynecil
      aiopyarr
      pysabnzbd
      getmac
      zigpy
      bellows         # For Zigbee EmberZNet-based adapters
      zigpy-xbee      # For XBee adapters
      zigpy-deconz    # For ConBee/RaspBee adapters
      pyicloud        # iCloud
      pyatv           # Apple TV
      opencv-python
      face-recognition
      ibeacon-ble
      gehomesdk
      onedrive-personal-sdk
      python-roborock
      pythonSteam
      apple-weatherkit
    ];
    
    config = {
      # Includes dependencies for a basic setup
      # https://www.home-assistant.io/integrations/default_config/
      default_config = {};

      cloud = false;
      
      frontend = {
        themes = "!include_dir_merge_named themes";
      };

      "automation ui" = "!include /etc/nixos/hosts/homeassistant/automations.yaml";
      "scene ui" = "!include /etc/nixos/hosts/homeassistant/scenes.yaml";
      "script ui" = "!include /etc/nixos/hosts/homeassistant/scripts.yaml";

      http = {
        use_x_forwarded_for = true;
        trusted_proxies = [
          "172.30.33.0/24"
          "10.0.1.3"
          "10.0.1.0/24"
        ];
      };

      recorder = {
        db_url = "postgresql://@/hass";
        purge_keep_days = 180;
      };

      auth_header = {
        debug = false;
        username_header = "X-authentik-username";
      };

      # https://www.home-assistant.io/integrations/ota_updater/
      zha.zigpy_config.ota.z2m_remote_index = "https://raw.githubusercontent.com/Koenkk/zigbee-OTA/master/index.json";
    };
  };

  # https://www.home-assistant.io/integrations/automation/
  # systemd.tmpfiles.rules = [
  #   "f ${config.services.home-assistant.configDir}/automations.yaml 0755 hass hass"
  # ];

  # This bypasses the component validation and places it directly in HA's data directory
  system.activationScripts.installCustomComponents = ''
    mkdir -p ${config.services.home-assistant.configDir}/custom_components
    cp -r ${ha-bambulab}/custom_components/bambu_lab ${config.services.home-assistant.configDir}/custom_components/
    cp -r ${ha-gehome}/custom_components/ge_home ${config.services.home-assistant.configDir}/custom_components/
    cp -r ${ha-mail-and-packages}/custom_components/mail_and_packages ${config.services.home-assistant.configDir}/custom_components/
    cp -r ${ha-overseerr}/custom_components/overseerr ${config.services.home-assistant.configDir}/custom_components/
    cp -r ${ha-petlibro}/custom_components/petlibro ${config.services.home-assistant.configDir}/custom_components/
    cp -r ${ha-wyzeapi}/custom_components/wyzeapi ${config.services.home-assistant.configDir}/custom_components/

    ln -sf /etc/nixos/hosts/homeassistant/automations.yaml ${config.services.home-assistant.configDir}/automations.yaml
    ln -sf /etc/nixos/hosts/homeassistant/scenes.yaml ${config.services.home-assistant.configDir}/scenes.yaml
    ln -sf /etc/nixos/hosts/homeassistant/scripts.yaml ${config.services.home-assistant.configDir}/scripts.yaml


    chown -R hass:hass ${config.services.home-assistant.configDir}
    chmod -R 750 ${config.services.home-assistant.configDir}
  '';

  services = {
    postgresql = {
      enable = true;
      ensureDatabases = [ "hass" ];
      ensureUsers = [{
        name = "hass";
        ensureDBOwnership = true;
      }];
    };

    # Enable and configure Mosquitto MQTT broker
    mosquitto = {
      enable = true;
      listeners = [
        {
          acl = [ "pattern readwrite #" ];
          omitPasswordAuth = true;
          settings.allow_anonymous = true;
        }
      ];
    };

    zigbee2mqtt = {
      enable = true;
      settings = {
        homeassistant = {
          enabled = config.services.home-assistant.enable;
          # Optional: Home Assistant discovery topic (default: shown below)
          # Note: should be different from [MQTT base topic](../mqtt.md) to prevent errors in HA software
          discovery_topic = "homeassistant";
          # Optional: Home Assistant status topic (default: shown below)
          status_topic = "homeassistant/status";
          # Optional: Experimental support for Home Assistant event entities, may break in the future (default: shown below) when enabled:
          # - An `event` entity will be discovered for each 'action'.
          # - The `event_type` attribute will contain the action itself, additional attributes like `button` will have further information.
          experimental_event_entities = false;
          # Optional: Home Assistant legacy action sensor (default: `false`), when enabled:
          # - Zigbee2MQTT will send an empty 'action' after one has been send
          # - A 'sensor_action' will be discovered
          legacy_action_sensor = false;
        };

        permit_join = true;
        # Web interface
        frontend = {
          port = zigbee2mqttPort;  # Choose an available port
        };
        # MQTT configuration
        mqtt = {
          base_topic = "zigbee2mqtt";
          server = "mqtt://localhost:1883";
          # If using authentication:
          # user = "mqttuser";
          # password = "your-password";
        };
        serial = {
          port = "/dev/ttyUSB0";
        };
      };
    };

    music-assistant = {
      enable = true;
      providers = [
        # "airplay" # music-assistant: airplay support is missing libraop, a library we will not package because it depends on OpenSSL 1.1.
        "apple_music"
        "bluesound"
        "builtin"
        "chromecast"
        "deezer"
        "dlna"
        "fanarttv"
        "filesystem_local"
        "filesystem_smb"
        "fully_kiosk"
        "hass"
        "hass_players"
        "jellyfin"
        "musicbrainz"
        "opensubsonic"
        "player_group"
        "plex"
        "qobuz"
        "radiobrowser"
        "siriusxm"
        "snapcast"
        "sonos"
        "sonos_s1"
        "soundcloud"
        "spotify"
        "template_player_provider"
        "test"
        "theaudiodb"
        "tidal"
        "tunein"
        "ytmusic"
      ];
    };

    # Enable AirPlay
    pipewire = {
      # opens UDP ports 6001-6002
      raopOpenFirewall = true;

      extraConfig.pipewire = {
        "10-airplay" = {
          "context.modules" = [
            {
              name = "libpipewire-module-raop-discover";

              # increase the buffer size if you get dropouts/glitches
              # args = {
              #   "raop.latency.ms" = 500;
              # };
            }
          ];
        };
      };
    };
  };

  # Enable required hardware support for the Zigbee adapter
  hardware.bluetooth.enable = true;  # Some adapters use Bluetooth
  
  # Ensure proper permissions for Zigbee USB devices
  # services.udev.extraRules = ''
  #   # For CC2531, CC2530, CC1352P-2, CC2538 and similar adapters
  #   SUBSYSTEM=="tty", ATTRS{idVendor}=="0451", ATTRS{idProduct}=="16a8", SYMLINK+="zigbee", MODE="0666"
  #   SUBSYSTEM=="tty", ATTRS{idVendor}=="1a86", ATTRS{idProduct}=="7523", SYMLINK+="zigbee", MODE="0666"
    
  #   # For ConBee/RaspBee by Dresden Elektronik
  #   SUBSYSTEM=="tty", ATTRS{idVendor}=="1cf1", ATTRS{idProduct}=="0030", SYMLINK+="zigbee", MODE="0666"
    
  #   # For Electrolama zig-a-zig-ah (zzh!)
  #   SUBSYSTEM=="tty", ATTRS{idVendor}=="1a86", ATTRS{idProduct}=="7523", SYMLINK+="zigbee", MODE="0666"
  # '';

  environment.systemPackages = with pkgs; [
    mosquitto  # MQTT command-line tools
    usbutils   # For lsusb to help identify your adapter
  ];

  networking.firewall.allowedTCPPorts = [
    mosquittoPort
    zigbee2mqttPort
    8095
    8097
  ];
}
