{ config, lib, ... }:
let
  cameras = {
    "ulfried" = {
      frigate.record = {
        enabled = true;
        continuous.days = 0;
        alerts.retain = {
          days = 30;
          mode = "motion";
        };
      };
    };
    "gnisbert" = { };
    "taubis" = {
      frigate = {
        detect.enabled = true;
        record = {
          enabled = true;
          continuous.days = 1;
          detections.retain.days = 7;
        };
      };
    };
    "foeff" = {
      videoPassthrough = true;
      frigate.record = {
        enabled = true;
        continuous.days = 0;
        alerts.retain = {
          days = 30;
          mode = "motion";
        };
      };
    };
  };

  # Uppercase camera name for use as systemd credential / env var name
  varName = name: lib.toUpper (lib.replaceStrings [ "-" ] [ "_" ] name);

  go2rtcCameraStreams =
    name: cam:
    let
      video = lib.optionalString (cam.videoPassthrough or false) "#video=copy";
    in
    {
      "${name}" = [
        "\${${varName name}_URL}"
        "ffmpeg:${name}#audio=opus#audio=aac${video}"
      ];
      "${name}_sub" = [
        "\${${varName name}_SUB_URL}"
        "ffmpeg:${name}_sub#audio=opus#audio=aac${video}"
      ];
    };

  frigateInputs = name: [
    {
      path = "rtsp://127.0.0.1:8554/${name}?timeout=30";
      input_args = "preset-rtsp-generic";
      roles = [ "record" ];
    }
    {
      path = "rtsp://127.0.0.1:8554/${name}_sub?timeout=30";
      input_args = "preset-rtsp-generic";
      roles = [
        "detect"
        "audio"
      ];
    }
  ];

  # Only cameras with a frigate key get a frigate camera entry
  frigCameras = lib.filterAttrs (_: cam: cam ? frigate) cameras;
in
{
  age.secrets = lib.mkMerge (
    lib.mapAttrsToList (name: _: {
      "camera-${name}-url".file = ../../secrets/camera-${name}-url.age;
      "camera-${name}-sub-url".file = ../../secrets/camera-${name}-sub-url.age;
    }) cameras
  );

  systemd.services.go2rtc.serviceConfig.LoadCredential = lib.concatMap (name: [
    "${varName name}_URL:${config.age.secrets."camera-${name}-url".path}"
    "${varName name}_SUB_URL:${config.age.secrets."camera-${name}-sub-url".path}"
  ]) (lib.attrNames cameras);

  services.go2rtc = {
    enable = true;
    settings = {
      rtsp.listen = ":8554";
      webrtc.listen = ":8555";
      streams = lib.foldl' lib.mergeAttrs { } (lib.mapAttrsToList go2rtcCameraStreams cameras);
    };
  };

  services.frigate = {
    enable = true;
    hostname = "kameramann.lan.baubs.net";
    settings = {
      go2rtc.streams = lib.foldl' lib.mergeAttrs { } (
        lib.mapAttrsToList (name: _: {
          "${name}" = [ ];
          "${name}_sub" = [ ];
        }) cameras
      );
      detect.enabled = true;
      objects.track = [
        "person"
        "bird"
        "car"
      ];
      classification.bird.enabled = true;
      cameras = lib.mapAttrs (
        name: cam: cam.frigate // { ffmpeg.inputs = frigateInputs name; }
      ) frigCameras;
    };
  };

  networking.firewall.allowedTCPPorts = [
    5000
    1984
    80
    8555
  ];
  networking.firewall.allowedUDPPorts = [ 8555 ];
}
