{
  lib,
  config,
  pkgs,
  ...
}:
let
  smtp = config.secretsSpec.users.admin.smtp;
  pangolin = config.secretsSpec.docker.pangolin;

  # Create the configuration files as derivations
  pangolinConfigFile = pkgs.writeText "pangolin-config.yml" ''
    app:
      dashboard_url: "https://pangolin.ryot.foo"
      log_level: "debug"
      save_logs: true

    domains:
      domain1:
        base_domain: "ryot.foo"
        cert_resolver: "letsencrypt"
        prefer_wildcard_cert: true
      domain2:
        base_domain: "toph.cc"
        cert_resolver: "letsencrypt"
        prefer_wildcard_cert: true
      domain3:
        base_domain: "goldenlemon.cc"
        cert_resolver: "letsencrypt"
        prefer_wildcard_cert: true
      domain4:
        base_domain: "kwahson.xyz"
        cert_resolver: "letsencrypt"
        prefer_wildcard_cert: true

    server:
      external_port: 3000
      internal_port: 3001
      next_port: 3002
      internal_hostname: "pangolin"
      session_cookie_name: "p_session_token"
      resource_access_token_param: "p_token"
      resource_access_token_headers:
        id: "P-Access-Token-Id"
        token: "P-Access-Token"
      resource_session_request_param: "p_session_request"
      secret: "${pangolin.SECRET}"

    traefik:
      cert_resolver: "letsencrypt"
      http_entrypoint: "web"
      https_entrypoint: "websecure"

    gerbil:
      start_port: 51820
      base_endpoint: "pangolin.ryot.foo"
      use_subdomain: false
      block_size: 24
      site_block_size: 30
      subnet_group: 104.40.3.1/24

    rate_limits:
      global:
        window_minutes: 1
        max_requests: 100

    email:
      smtp_host: "${smtp.host}"
      smtp_port: ${toString smtp.port}
      smtp_user: "${smtp.user}"
      smtp_pass: "${smtp.password}"
      no_reply: "no-reply@ryot.foo"

    users:
      server_admin:
        email: "${pangolin.USER}"
        password: "${pangolin.PASSWORD}"

    flags:
      require_email_verification: true
      disable_signup_without_invite: true
      disable_user_create_org: true
      allow_raw_resources: true
      allow_base_domain_resources: true
  '';

  traefikConfigFile = pkgs.writeText "traefik-config.yml" ''
    api:
      insecure: true
      dashboard: true

    providers:
      http:
        endpoint: "http://pangolin:3001/api/v1/traefik-config"
        pollInterval: "5s"
      file:
        filename: "/etc/traefik/dynamic_config.yml"

    experimental:
      plugins:
        badger:
          moduleName: "github.com/fosrl/badger"
          version: "v1.2.0"

    log:
      level: "DEBUG"
      format: "common"

    certificatesResolvers:
      letsencrypt:
        acme:
          dnsChallenge:
            provider: cloudflare
            delayBeforeCheck: 60
            resolvers:
              - "1.1.1.1:53"
              - "8.8.8.8:53"
          email: chris@toph.cc
          storage: "/letsencrypt/acme.json"
          caServer: "https://acme-v02.api.letsencrypt.org/directory"

    entryPoints:
      web:
        address: ":80"
      websecure:
        address: ":443"
        transport:
          respondingTimeouts:
            readTimeout: "30m"
        http:
          tls:
            certResolver: "letsencrypt"
      tcp-222:
        address: ":222/tcp"

    serversTransport:
      insecureSkipVerify: true
  '';

  dynamicConfigFile = pkgs.writeText "dynamic-config.yml" ''
    http:
      middlewares:
        redirect-to-https:
          redirectScheme:
            scheme: https

      routers:
        # HTTP to HTTPS redirect router
        main-app-router-redirect:
          rule: "Host(`pangolin.ryot.foo`)"
          service: next-service
          entryPoints:
            - web
          middlewares:
            - redirect-to-https

        # Next.js router
        next-router:
          rule: "Host(`pangolin.ryot.foo`) && !PathPrefix(`/api/v1`)"
          service: next-service
          entryPoints:
            - websecure
          tls:
            certResolver: letsencrypt
            domains:
              - main: "ryot.foo"
                sans:
                  - "*.ryot.foo"

        # API router
        api-router:
          rule: "Host(`pangolin.ryot.foo`) && PathPrefix(`/api/v1`)"
          service: api-service
          entryPoints:
            - websecure
          tls:
            certResolver: letsencrypt

        # WebSocket router
        ws-router:
          rule: "Host(`pangolin.ryot.foo`)"
          service: api-service
          entryPoints:
            - websecure
          tls:
            certResolver: letsencrypt

      services:
        next-service:
          loadBalancer:
            servers:
              - url: "http://pangolin:3002"

        api-service:
          loadBalancer:
            servers:
              - url: "http://pangolin:3000"
  '';

  keyFile = pkgs.writeText "pangolin-key" pangolin.KEY;
in
{
  imports = lib.custom.scanPaths ./.;

  boot.kernelModules = [ "wireguard" ];

  ## Tmp files and Service to Avoid symlinks
  systemd.tmpfiles.rules = [
    "d /etc/pangolin/config 0755 root root -"
    "d /etc/pangolin/config/traefik 0755 root root -"
    "d /etc/pangolin/config/letsencrypt 0755 root root -"
  ];

  systemd.services.pangolin-config-sync = {
    description = "Sync Pangolin configuration files";
    wantedBy = [ "multi-user.target" ];
    before = [ "docker-compose-pangolin-root.target" ];
    serviceConfig = {
      Type = "oneshot";
      RemainAfterExit = true;
    };
    script = ''
      cp ${keyFile} /etc/pangolin/config/key
      chmod 0600 /etc/pangolin/config/key
      cp ${pangolinConfigFile} /etc/pangolin/config/config.yml
      cp ${traefikConfigFile} /etc/pangolin/config/traefik/traefik_config.yml
      cp ${dynamicConfigFile} /etc/pangolin/config/traefik/dynamic_config.yml
    '';
  };
}
