{ config, lib, pkgs, ... }:

let
  cfg = config.services.motu-m4-combined;
in
{
  options.services.motu-m4-combined = {
    enable = lib.mkEnableOption "MOTU M4 combined mono input";

    user = lib.mkOption {
      type = lib.types.str;
      description = "User to run the setup service as";
    };

    devicePrefix = lib.mkOption {
      type = lib.types.str;
      default = "alsa_input.usb-MOTU_M4_M4MA0824DV-00.HiFi";
      description = "Device prefix for MOTU M4 inputs";
    };

    virtualSourceName = lib.mkOption {
      type = lib.types.str;
      default = "motu_m4_combined";
      description = "Name of the virtual combined source";
    };

    virtualSourceDescription = lib.mkOption {
      type = lib.types.str;
      default = "MOTU M4 All Inputs (Mono)";
      description = "Human-readable description of the virtual source";
    };

    latencyMs = lib.mkOption {
      type = lib.types.int;
      default = 20;
      description = "Loopback latency in milliseconds";
    };

    usbVendorId = lib.mkOption {
      type = lib.types.str;
      default = "07fd";
      description = "USB Vendor ID for MOTU M4 device";
    };

    usbProductId = lib.mkOption {
      type = lib.types.str;
      default = "000b";
      description = "USB Product ID for MOTU M4 device";
    };
  };

  config = lib.mkIf cfg.enable {
    # Udev rule to tag MOTU M4 device for systemd tracking
    services.udev.extraRules = ''
      # Tag MOTU M4 device so systemd can track it
      SUBSYSTEM=="usb", ATTR{idVendor}=="${cfg.usbVendorId}", ATTR{idProduct}=="${cfg.usbProductId}", TAG+="systemd"
    '';

    # Create loopbacks and remap source via systemd user service
    systemd.user.services.motu-m4-combined-setup = {
      description = "Setup MOTU M4 combined mono input loopbacks";
      # Bind to MOTU M4 USB device - service only runs when device is connected
      bindsTo = [ "dev-serial-by\\x2did-usb\\x2dMOTU_M4_M4MA0824DV\\x2dif05.device" ];
      after = [ 
        "pipewire-pulse.service"
        "dev-serial-by\\x2did-usb\\x2dMOTU_M4_M4MA0824DV\\x2dif05.device"
      ];
      requires = [ "pipewire-pulse.service" ];
      wantedBy = [ "dev-serial-by\\x2did-usb\\x2dMOTU_M4_M4MA0824DV\\x2dif05.device" ];
      
      serviceConfig = {
        Type = "oneshot";
        RemainAfterExit = true;
        
        # Verify MOTU M4 device is actually available before starting
        ExecCondition = pkgs.writeShellScript "motu-m4-check-device" ''
          # Check if MOTU M4 USB device is present
          if ! ${pkgs.usbutils}/bin/lsusb -d ${cfg.usbVendorId}:${cfg.usbProductId} > /dev/null 2>&1; then
            echo "MOTU M4 USB device not found (${cfg.usbVendorId}:${cfg.usbProductId})"
            exit 1
          fi
          
          # Wait a moment for audio subsystem to fully enumerate the device
          sleep 1
          
          # Check if at least one MOTU audio source is available in PipeWire
          if ! ${pkgs.pulseaudio}/bin/pactl list sources short | ${pkgs.gnugrep}/bin/grep -q "${cfg.devicePrefix}"; then
            echo "MOTU M4 audio sources not yet available in PipeWire"
            exit 1
          fi
          
          echo "MOTU M4 device detected and ready"
          exit 0
        '';
        
        ExecStart = pkgs.writeShellScript "motu-m4-setup" ''
          # Wait for pipewire-pulse to be fully ready
          sleep 2
          
          # Create null sink for mixing (internal, not visible in normal output lists)
          ${pkgs.pulseaudio}/bin/pactl load-module module-null-sink \
            sink_name=motu_mixer \
            sink_properties=device.description="MOTU_Mixer_(Internal)" \
            channels=1 \
            channel_map=mono
          
          # Create loopbacks from each M4 input to the mixer
          # Device presence is guaranteed by ExecCondition check
          ${pkgs.pulseaudio}/bin/pactl load-module module-loopback \
            source=${cfg.devicePrefix}__Mic1__source \
            sink=motu_mixer channels=1 latency_msec=${toString cfg.latencyMs} \
            source_dont_move=true sink_dont_move=true
          
          ${pkgs.pulseaudio}/bin/pactl load-module module-loopback \
            source=${cfg.devicePrefix}__Mic2__source \
            sink=motu_mixer channels=1 latency_msec=${toString cfg.latencyMs} \
            source_dont_move=true sink_dont_move=true
          
          ${pkgs.pulseaudio}/bin/pactl load-module module-loopback \
            source=${cfg.devicePrefix}__Line3__source \
            sink=motu_mixer channels=1 latency_msec=${toString cfg.latencyMs} \
            source_dont_move=true sink_dont_move=true
          
          ${pkgs.pulseaudio}/bin/pactl load-module module-loopback \
            source=${cfg.devicePrefix}__Line4__source \
            sink=motu_mixer channels=1 latency_msec=${toString cfg.latencyMs} \
            source_dont_move=true sink_dont_move=true
          
          # Create the virtual source from the mixer monitor
          ${pkgs.pulseaudio}/bin/pactl load-module module-remap-source \
            master=motu_mixer.monitor \
            source_name=${cfg.virtualSourceName} \
            source_properties=device.description="${cfg.virtualSourceDescription}" \
            channels=1 \
            channel_map=mono
        '';
        
        # Clean up modules on service stop/restart
        ExecStop = pkgs.writeShellScript "motu-m4-teardown" ''
          # Unload loopback modules connected to motu_mixer
          ${pkgs.pulseaudio}/bin/pactl list modules short | \
            ${pkgs.gnugrep}/bin/grep "module-loopback.*sink=motu_mixer" | \
            ${pkgs.coreutils}/bin/cut -f1 | \
            while read id; do
              ${pkgs.pulseaudio}/bin/pactl unload-module "$id" 2>/dev/null || true
            done
          
          # Unload the remap source module
          ${pkgs.pulseaudio}/bin/pactl list modules short | \
            ${pkgs.gnugrep}/bin/grep "module-remap-source.*source_name=${cfg.virtualSourceName}" | \
            ${pkgs.coreutils}/bin/cut -f1 | \
            while read id; do
              ${pkgs.pulseaudio}/bin/pactl unload-module "$id" 2>/dev/null || true
            done
          
          # Unload the null sink module
          ${pkgs.pulseaudio}/bin/pactl list modules short | \
            ${pkgs.gnugrep}/bin/grep "module-null-sink.*sink_name=motu_mixer" | \
            ${pkgs.coreutils}/bin/cut -f1 | \
            while read id; do
              ${pkgs.pulseaudio}/bin/pactl unload-module "$id" 2>/dev/null || true
            done
        '';
        
        # Failsafe: ensure cleanup happens even if ExecStop fails
        ExecStopPost = pkgs.writeShellScript "motu-m4-cleanup-failsafe" ''
          # Cleanup any remaining MOTU-related modules (loopbacks, remap source, and null sink)
          ${pkgs.pulseaudio}/bin/pactl list modules short | \
            ${pkgs.gnugrep}/bin/grep -E "module-loopback.*motu_mixer|module-remap-source.*${cfg.virtualSourceName}|module-null-sink.*motu_mixer" | \
            ${pkgs.coreutils}/bin/cut -f1 | \
            while read id; do
              ${pkgs.pulseaudio}/bin/pactl unload-module "$id" 2>/dev/null || true
            done
        '';
      };
    };
  };
}
