{ config
, lib
, pkgs
, ...
}:
let
  inherit (lib) pipe flatten concatMapAttrs mapAttrsToList;
  inherit (import ../../../lib/caddy.nix { inherit lib; }) security-headers;
  repos = "${config.services.gitolite.dataDir}/repositories";

  mirrors = {
    sourcehut = {
      hostname = "git.sr.ht";
      username = "~alanpearce";
    };
    codeberg = {
      hostname = "codeberg.org";
      username = "alanpearce";
    };
    github = {
      hostname = "github.com";
      username = "alanpearce";
    };
  };

  repoMirrors = {
    nixfiles = [ "sourcehut" ];
    searchix = [ "sourcehut" ];
    website = [ "sourcehut" ];
    homestead = [ "sourcehut" ];
    nix-packages = [ "sourcehut" "github" ];
    zola-bearblog = [ "sourcehut" "codeberg" ];
  };

  createMirrorService =
    name: { hostname, username }:
    {
      "mirror-to-${name}@" = {
        path = with pkgs; [ gitMinimal openssh ];
        serviceConfig = {
          Type = "oneshot";
          User = "gitolite";
          WorkingDirectory = "${repos}/%i.git";
          ExecStart = "${pkgs.gitMinimal}/bin/git push --mirror git@${hostname}:${username}/%i";
        };
        unitConfig = {
          # only mirror public repositories
          ConditionPathExists = "${repos}/%i.git/git-daemon-export-ok";
        };
      };
    };

  createMirrorPath = name: { hostname, username }:
    {
      "mirror-to-${name}@" = {
        pathConfig = {
          PathChanged = "${repos}/%i.git/refs/heads";
          StartLimitIntervalSec = "1h";
          StartLimitBurst = 5;
        };
      };
    };


  mkMirrorWants = repo: map (target: "mirror-to-${target}@${repo}.path");
in
{
  services.fcgiwrap.instances.gitolite = {
    process = {
      user = "gitolite";
      group = "gitolite";
      prefork = 2;
    };
    socket = {
      type = "tcp6";
      address = "[::1]:9000";
    };
  };
  services.gitolite = {
    enable = true;
    adminPubkey = "ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBHYUyDdw92TNXguAxcmcmZmn/7ECGdRp6ckjxU+5zCw3BCnsS5+xEvHBVnnFdJRoH2XpfMeJjE+fi67zFVhlbn4= root@secretive.marvin";
    extraGitoliteRc = ''
      $RC{UMASK} = 0027;
      $RC{LOG_EXTRA} = 0;
      $RC{HOSTNAME} = "${config.networking.hostName}";
      $RC{LOCAL_CODE} = "$rc{GL_ADMIN_BASE}/local";
      push( @{$RC{ENABLE}}, 'D' );
      push( @{$RC{ENABLE}}, 'Shell alan' );
      push( @{$RC{ENABLE}}, 'cgit' );
      push( @{$RC{ENABLE}}, 'repo-specific-hooks' );
    '';
  };
  services.legit = {
    enable = true;
    group = "gitolite";
    settings = {
      server.name = "legit.alanpearce.eu";
      dirs = {
        templates = "/srv/http/legit/src/templates";
      };
      repo = {
        scanPath = "/srv/http/legit/repos";
        readme = [
          "readme"
          "readme.md"
          "README.md"
        ];
      };
    };
  };
  services.gitDaemon = {
    enable = true;
    user = "gitolite";
    group = "gitolite";
    basePath = repos;
  };

  services.caddy.virtualHosts = {
    "git.alanpearce.eu" =
      let
        fcgi = config.services.fcgiwrap.instances.gitolite;
        fcgisocket = "${fcgi.socket.type}/${fcgi.socket.address}";
      in
      {
        useACMEHost = "alanpearce.eu";
        extraConfig = ''
          root * ${pkgs.cgit-pink}/cgit/
          encode zstd gzip
          ${security-headers {
            overrides.content-security-policy = {
              default-src = [ "none" ];
              base-uri = [ "none" ];
              style-src = [ "self" "unsafe-inline" ];
              script-src = [ "self" "unsafe-inline" ];
              form-action = [ "self" ];
              connect-src = [ "self" ];
              img-src = [ "https" ];
              object-src = [ "none" ];
            };
          }}
          handle_path /custom/* {
            file_server {
              root /srv/http/cgit/
            }
          }
          rewrite /robots.txt /assets/robots.txt
          handle_path /assets/* {
            file_server  {
              hide cgit.cgi
            }
          }
          @git_http_backend path_regexp "^.*/(HEAD|info/refs|objects/info/[^/]+|git-upload-pack)$"
          handle @git_http_backend {
            reverse_proxy ${fcgisocket} {
              request_buffers 4k
              transport fastcgi {
                env SCRIPT_FILENAME ${pkgs.git}/libexec/git-core/git-http-backend
                env GIT_PROJECT_ROOT ${repos}
              }
            }
          }
          handle {
            reverse_proxy ${fcgisocket} {
              transport fastcgi {
                env       SCRIPT_FILENAME  {http.vars.root}/cgit.cgi
                env       CGIT_CONFIG      ${pkgs.writeText "cgitrc" ''
                  head-include=/srv/http/cgit/responsive-cgit-css-master/head.html
                  css=/custom/responsive-cgit-css-master/cgit.css
                  virtual-root=/
                  logo=
                  readme=:README.md
                  source-filter=${pkgs.cgit-pink}/lib/cgit/filters/syntax-highlighting.py
                  about-filter=${pkgs.cgit-pink}/lib/cgit/filters/about-formatting.sh
                  enable-git-config=1
                  enable-index-owner=0
                  enable-index-links=1
                  enable-follow-links=0
                  enable-log-linecount=1
                  max-stats=year
                  snapshots=tar.lz tar.zst zip
                  enable-http-clone=1
                  enable-commit-graph=1
                  mimetype-file=${pkgs.nginx}/conf/mime.types
                  section-from-path=1
                  noplainemail=1
                  repository-sort=age
                  root-title=my personal projects
                  clone-url=git://git.alanpearce.eu/$CGIT_REPO_URL https://git.alanpearce.eu/$CGIT_REPO_URL
                  remove-suffix=1
                  strict-export=git-daemon-export-ok
                  scan-path=${repos}
                ''}
                }
              }
          }
        '';
      };

    "legit.alanpearce.eu" =
      let
        server = config.services.legit.settings.server;
      in
      {
        useACMEHost = "alanpearce.eu";
        extraConfig = ''
          encode zstd gzip
          handle_path /static/* {
            root * /srv/http/legit/src/static
            file_server
          }
          ${security-headers {
            overrides.content-security-policy = {
              default-src = [ "none" ];
              base-uri = [ "none" ];
              style-src = [ "self" ];
              script-src = [ "none" ];
              form-action = [ "self" ];
              connect-src = [ "self" ];
              img-src = [ "https" ];
              object-src = [ "none" ];
            };
          }}
          reverse_proxy ${server.host}:${toString server.port}
        '';
      };
  };

  systemd.services = concatMapAttrs createMirrorService mirrors;
  systemd.paths = concatMapAttrs createMirrorPath mirrors;
  systemd.targets.git-mirroring = {
    wantedBy = [ "multi-user.target" ];
    wants = pipe
      repoMirrors [
      (mapAttrsToList mkMirrorWants)
      flatten
    ];
  };
}