{ config, pkgs, lib, ... }:
with lib;
let
  cfgBase = config.base;
  cfg = config.services.ppWoodpecker;
in
{
  imports = [
    # Woodpeeker is not in stable yet but the module is good enought
    (builtins.fetchurl {
      url = "https://github.com/NixOS/nixpkgs/raw/nixos-unstable/nixos/modules/services/continuous-integration/woodpecker/server.nix";
      sha256 = "13dzbcb0fi0bwam0mlf6d6ly0x90pr8sq68kzs65mszbvsd5lqjb";
    })
    (builtins.fetchurl {
      url = "https://github.com/NixOS/nixpkgs/raw/nixos-unstable/nixos/modules/services/continuous-integration/woodpecker/agents.nix";
      sha256 = "14kjj9ybahmfqflvsa8p0va1z3zhliybggxd148fzz4bnjsqpsla";
    })
  ];
  options.services.ppWoodpecker = {
    serverEnvFile = mkOption {
      type = types.str;
      default = "/etc/woodpecker_server_env";
      description = "The file containing the env secrets WOODPECKER_AGENT_SECRET and WOODPECKER_GITEA_SECRET, cf https://woodpecker-ci.org/docs/administration/vcs/gitea#configuration for gitea";
    };
    agentEnvFile = mkOption {
      type = types.str;
      default = "/etc/woodpecker_agent_env";
      description = "The file containing the env secrets WOODPECKER_AGENT_SECRET";
    };
    domain = mkOption {
      type = types.str;
      default = "ci.${cfgBase.domainName}";
      example = "ci.example.com";
      description = "The domain of the server";
    };
    giteaDomain = mkOption {
      type = types.str;
      default = "git.${cfgBase.domainName}";
      example = "git.example.com";
      description = "The domain of the gitea server";
    };
    giteaClientId = mkOption {
      type = types.str;
      example = "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX";
      description = "The domain of the gitea server";
    };
    admins = mkOption {
      type = lib.types.listOf lib.types.string;
      default = [];
      example = [ "user1" "user2" ];
      description = "List of admins"; 
    };
    maxProcsPerAgent = mkOption {
      type = types.int;
      default = 1;
      example = 4;
      description = "Number of possible paralle process per agent";
    };
  };

  config = {

    services.woodpecker-server.enable = true;
    # To put in woodpecker_server_env:
    # ```
    # WOODPECKER_AGENT_SECRET=XXXXXX
    # WOODPECKER_GITEA_SECRET=gto_XXXXXX
    # ```
    services.woodpecker-server.environmentFile = "${cfg.serverEnvFile}";
    services.woodpecker-server.environment = {
      WOODPECKER_HOST = "https://${cfg.domain}";
      WOODPECKER_OPEN = "true"; # This means user of gitea can connect to the ci
      WOODPECKER_GITEA = "true";
      WOODPECKER_GITEA_CLIENT = "${cfg.giteaClientId}";
      WOODPECKER_GITEA_URL = "https://${cfg.giteaDomain}";
      WOODPECKER_ADMIN = lib.mkIf (cfg.admins != []) (lib.concatStringsSep "," cfg.admins);
    };

    virtualisation.podman.enable = true;
    virtualisation.podman.defaultNetwork.dnsname.enable = true;
    services.woodpecker-agents.agents.podman = {
      enable = true;
      extraGroups = [ "podman" ];
      environmentFile = [ "${cfg.agentEnvFile}" ];
      environment = {
        WOODPECKER_BACKEND = "docker";
        DOCKER_HOST = "unix:////run/podman/podman.sock";
        WOODPECKER_MAX_PROCS = builtins.toString cfg.maxProcsPerAgent;
      };
    };

    security.acme.acceptTerms = true;
    security.acme.defaults.email = cfgBase.adminEmail;
    services.nginx = {
        enable = true;
        virtualHosts = {
          "${cfg.domain}" = {
            forceSSL = true;
            enableACME = true;
            locations."/" = {
              proxyPass = "http://127.0.0.1:8000";
              extraConfig = ''
                proxy_set_header X-Forwarded-Host $host;
                proxy_set_header X-Forwarded-Server $host;
                proxy_set_header X-Real-IP $remote_addr;
                proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
                proxy_set_header X-Forwarded-Proto $scheme;
                proxy_set_header Host $host;
                proxy_pass_request_headers on;
              '';
            };
          };
        };
      };
    networking.firewall.allowedTCPPorts = [ 80 443 ];
  };
}