{ config, pkgs, lib, ... }:
# I gave up writing this lol

with lib;

let
  cfg = config.services.woodpecker;
  droneserver = config.users.users.droneserver.name;

in
{
  options = {
    enable = mkEnableOption "Woodpecker CI/CD";

    user = mkOption {
      type = types.str;
      default = "woodpeckerserver";
      description = "User account under which woodpecker server runs.";
    };

    group = mkOption {
      type = types.str;
      default = "woodpeckerserver";
      description = "Group account under which woodpecker server runs.";
    };

    hostname = mkOption {
      type = types.str;
      example = "woodpecker.example.com";
      description = "VirtualHost created for nginx";
    };
  };

  config = mkIf cfg.enable {
    users.users = optionalAttrs (cfg.user == name) {
      ${name} = {
        group = cfg.group;
        description = "woodpecker server user";
        home = cfg.dataDir;
        createHome = true;
      };
    };

    users.groups = optionalAttrs (cfg.group == name) {
      ${name}.gid = config.ids.gids.headphones;
    };

    services.nginx.virtualHosts."drone.my-server.tld" = {
      enableACME = true;
      forceSSL = true;
      locations."/".proxyPass = "http://localhost:3030/";
    };

    services.postgresql = {
      ensureDatabases = [ droneserver ];
      ensureUsers = [{
        name = droneserver;
        ensurePermissions = {
          "DATABASE ${droneserver}" = "ALL PRIVILEGES";
        };
      }];
    };

    # Secrets configured:
    # - DRONE_GITEA_CLIENT_ID
    # - DRONE_GITEA_CLIENT_SECRET
    # - DRONE_RPC_SECRET
    # To get these secrets, please check Drone's documentation for Gitea integration:
    # https://docs.drone.io/server/provider/gitea/

    # agenix secret

    systemd.services.drone-server = {
      wantedBy = [ "multi-user.target" ];
      serviceConfig = {
        EnvironmentFile = [
          config.sops.secrets.drone.path
        ];
        Environment = [
          "DRONE_DATABASE_DATASOURCE=postgres:///droneserver?host=/run/postgresql"
          "DRONE_DATABASE_DRIVER=postgres"
          "DRONE_SERVER_PORT=:3030"
          "DRONE_USER_CREATE=username:viperML,admin:true" # set your admin username

          "DRONE_GITEA_SERVER=https://git.my-domain.tld"
          "DRONE_SERVER_HOST=drone.my-domain.tld"
          "DRONE_SERVER_PROTO=https"
        ];
        ExecStart = "${pkgs.drone}/bin/drone-server";
        User = droneserver;
        Group = droneserver;
      };
    };

    ### Docker runner

    users.users.drone-runner-docker = {
      isSystemUser = true;
      group = "drone-runner-docker";
    };
    users.groups.drone-runner-docker = { };
    # Allow the runner to use docker
    users.groups.docker.members = [ "drone-runner-docker" ];

    systemd.services.drone-runner-docker = {
      enable = true;
      wantedBy = [ "multi-user.target" ];
      ### MANUALLY RESTART SERVICE IF CHANGED
      restartIfChanged = false;
      serviceConfig = {
        Environment = [
          "DRONE_RPC_PROTO=http"
          "DRONE_RPC_HOST=localhost:3030"
          "DRONE_RUNNER_CAPACITY=2"
          "DRONE_RUNNER_NAME=drone-runner-docker"
        ];
        EnvironmentFile = [
          config.sops.secrets.drone.path
        ];
        ExecStart = "${pkgs.drone-runner-docker}/bin/drone-runner-docker";
        User = "drone-runner-docker";
        Group = "drone-runner-docker";
      };
    };

    ### Exec runner

    users.users.drone-runner-exec = {
      isSystemUser = true;
      group = "drone-runner-exec";
    };
    users.groups.drone-runner-exec = { };
    # Allow the exec runner to write to build with nix
    nix.allowedUsers = [ "drone-runner-exec" ];

    systemd.services.drone-runner-exec = {
      enable = true;
      wantedBy = [ "multi-user.target" ];
      ### MANUALLY RESTART SERVICE IF CHANGED
      restartIfChanged = true;
      confinement.enable = true;
      confinement.packages = [
        pkgs.git
        pkgs.gnutar
        pkgs.bash
        pkgs.nixFlakes
        pkgs.gzip
      ];
      path = [
        pkgs.git
        pkgs.gnutar
        pkgs.bash
        pkgs.nixFlakes
        pkgs.gzip
      ];
      serviceConfig = {
        Environment = [
          "DRONE_RPC_PROTO=http"
          "DRONE_RPC_HOST=127.0.0.1:3030"
          "DRONE_RUNNER_CAPACITY=2"
          "DRONE_RUNNER_NAME=drone-runner-exec"
          "NIX_REMOTE=daemon"
          "PAGER=cat"
          "DRONE_DEBUG=true"
        ];
        BindPaths = [
          "/nix/var/nix/daemon-socket/socket"
          "/run/nscd/socket"
          # "/var/lib/drone"
        ];
        BindReadOnlyPaths = [
          "/etc/passwd:/etc/passwd"
          "/etc/group:/etc/group"
          "/nix/var/nix/profiles/system/etc/nix:/etc/nix"
          "${config.environment.etc."ssl/certs/ca-certificates.crt".source}:/etc/ssl/certs/ca-certificates.crt"
          "${config.environment.etc."ssh/ssh_known_hosts".source}:/etc/ssh/ssh_known_hosts"
          "${builtins.toFile "ssh_config" ''
          Host git.ayats.org
          ForwardAgent yes
        ''}:/etc/ssh/ssh_config"
          "/etc/machine-id"
          "/etc/resolv.conf"
          "/nix/"
        ];
        EnvironmentFile = [
          config.sops.secrets.drone.path
        ];
        ExecStart = "${pkgs.drone-runner-exec}/bin/drone-runner-exec";
        User = "drone-runner-exec";
        Group = "drone-runner-exec";
      };
    };
  };
