{ pkgs, ... }:

{
  imports = [ ./common.nix ];

  networking.hostName = "axiomania";

  # ============================================================================
  # Firewall
  # ============================================================================
  networking.firewall = {
    allowedTCPPorts = [ 22 80 443 2222 ];
    allowedUDPPorts = [ 51820 53 ]; # Wireguard, Adguard DNS
    checkReversePath = "loose"; # Required for WireGuard NAT
  };

  # ============================================================================
  # Forgejo
  # ============================================================================
  services.forgejo = {
    enable = true;
    database.type = "sqlite3";
    settings = {
      DEFAULT.APP_NAME = "Axiomania Git";

      server = {
        DOMAIN = "git.axiomania.org";
        ROOT_URL = "https://git.axiomania.org/";
        HTTP_ADDR = "127.0.0.1";
        HTTP_PORT = 3000;
        SSH_DOMAIN = "git.axiomania.org";
        SSH_PORT = 2222;
        START_SSH_SERVER = true;
      };

      service = {
        DISABLE_REGISTRATION = true;
        DEFAULT_KEEP_EMAIL_PRIVATE = true;
      };

      repository = {
        DEFAULT_PRIVATE = "private";
      };

      api = {
        ENABLE_SWAGGER = false;
      };

      session = {
        COOKIE_SECURE = true;
      };

      actions = {
        ENABLED = true;
      };
    };
  };

  # ============================================================================
  # Forgejo Actions Runner
  # ============================================================================
  # Requires a registration token from Forgejo.
  # Generate one: ssh root@178.104.15.221, then:
  #   forgejo-runner register (follow prompts)
  # Or via Forgejo web UI: Site Administration > Runners > Create Runner
  # Then put the token in /var/lib/forgejo-runner/token
  services.gitea-actions-runner.instances.default = {
    enable = true;
    name = "axiomania";
    url = "https://git.axiomania.org";
    tokenFile = "/var/lib/forgejo-runner/token";
    labels = [ "native:host" ];
    hostPackages = with pkgs; [
      bash
      coreutils
      curl
      gawk
      git
      gnused
      nodejs
      nix
    ];
  };

  # ============================================================================
  # Vaultwarden (Bitwarden-compatible password manager)
  # ============================================================================
  services.vaultwarden = {
    enable = true;
    config = {
      DOMAIN = "https://vault.axiomania.org";
      SIGNUPS_ALLOWED = false;
      ROCKET_ADDRESS = "127.0.0.1";
      ROCKET_PORT = 8222;
    };
  };

  # ============================================================================
  # Navidrome (music streaming)
  # ============================================================================
  services.navidrome = {
    enable = true;
    settings = {
      Address = "127.0.0.1";
      Port = 4533;
      MusicFolder = "/var/lib/navidrome/music";
    };
  };

  # ============================================================================
  # Syncthing (file sync)
  # ============================================================================
  services.syncthing = {
    enable = true;
    openDefaultPorts = true;
    dataDir = "/var/lib/syncthing";
    settings.gui.insecureSkipHostcheck = true;
  };

  # ============================================================================
  # Attic (Nix binary cache)
  # ============================================================================
  # Requires a secret generated on the server:
  #   openssl genrsa -traditional 4096 | base64 -w0 > /var/lib/atticd/token-secret
  #   echo "ATTIC_SERVER_TOKEN_RS256_SECRET_BASE64=$(cat /var/lib/atticd/token-secret)" > /etc/atticd.env
  services.atticd = {
    enable = true;
    environmentFile = "/etc/atticd.env";
    settings = {
      listen = "[::]:8080";
      storage = {
        type = "local";
        path = "/var/lib/atticd/storage";
      };
      garbage-collection = {
        default-retention-period = "3 months";
      };
      chunking = {
        nar-size-threshold = 65536;
        min-size = 16384;
        avg-size = 65536;
        max-size = 262144;
      };
    };
  };

  # ============================================================================
  # Kavita (ebook library)
  # ============================================================================
  # Generate token on the server:
  #   openssl rand -hex 128 > /var/lib/kavita/token-key
  services.kavita = {
    enable = true;
    settings.Port = 5000;
    tokenKeyFile = "/var/lib/kavita/token-key";
  };

  # ============================================================================
  # Audiobookshelf
  # ============================================================================
  services.audiobookshelf = {
    enable = true;
    port = 8234;
    host = "127.0.0.1";
  };

  # ============================================================================
  # Paperless-ngx (document management)
  # ============================================================================
  services.paperless = {
    enable = true;
    port = 28981;
    address = "127.0.0.1";
    domain = "docs.axiomania.org";
  };

  # ============================================================================
  # Adguard Home (DNS ad blocker)
  # ============================================================================
  # Use as DNS server via Wireguard: set DNS = 10.100.0.1 in client config
  services.adguardhome = {
    enable = true;
    port = 3300;
    host = "127.0.0.1";
  };

  # ============================================================================
  # SearXNG (private search engine)
  # ============================================================================
  # Generate secret on the server:
  #   echo "SEARX_SECRET=$(openssl rand -hex 32)" > /etc/searx/secrets.env
  services.searx = {
    enable = true;
    redisCreateLocally = true;
    settings = {
      server = {
        bind_address = "127.0.0.1";
        port = 8888;
        secret_key = "$SEARX_SECRET";
      };
    };
    environmentFile = "/etc/searx/secrets.env";
  };

  # ============================================================================
  # Homepage (services dashboard)
  # ============================================================================
  services.homepage-dashboard = {
    enable = true;
    listenPort = 8082;
    allowedHosts = "home.axiomania.org";
  };

  # ============================================================================
  # Matrix Conduit (encrypted messaging)
  # ============================================================================
  services.matrix-conduit = {
    enable = true;
    settings.global = {
      server_name = "axiomania.org";
      port = 6167;
      address = "127.0.0.1";
      allow_registration = false;
    };
  };

  # ============================================================================
  # Gokapi (file sharing) — disabled due to CVEs in stable
  # ============================================================================
  # services.gokapi = {
  #   enable = true;
  #   environment = {
  #     GOKAPI_PORT = 53842;
  #   };
  # };

  # ============================================================================
  # Wireguard VPN
  # ============================================================================
  # Generate keys on the server:
  #   wg genkey | tee /etc/wireguard/private.key | wg pubkey > /etc/wireguard/public.key
  networking.wireguard.interfaces.wg0 = {
    ips = [ "10.100.0.1/24" ];
    listenPort = 51820;
    privateKeyFile = "/etc/wireguard/private.key";
    peers = [
      {
        # Minisforum V3 SE (local NixOS machine)
        publicKey = "rEsHqzJVnv9AoOIEVTrdEF3x4G6rWxXqHLXTzAx88gc=";
        allowedIPs = [ "10.100.0.2/32" ];
      }
      {
        # Pixel 5
        publicKey = "jP+rYdc8qKdNY4l3PDFmGiOA31SnJRgcmQIVu6AJ9EM=";
        allowedIPs = [ "10.100.0.3/32" ];
      }
    ];
  };

  # NAT for Wireguard clients to access the internet
  networking.nat = {
    enable = true;
    externalInterface = "enp1s0";
    internalInterfaces = [ "wg0" ];
  };

  # ============================================================================
  # Nginx reverse proxy + ACME
  # ============================================================================
  services.nginx = {
    enable = true;
    recommendedProxySettings = true;
    recommendedTlsSettings = true;
    recommendedOptimisation = true;
    recommendedGzipSettings = true;

    # ── Public services ──
    virtualHosts."git.axiomania.org" = {
      enableACME = true;
      forceSSL = true;
      locations."/" = {
        proxyPass = "http://127.0.0.1:3000";
        proxyWebsockets = true;
      };
    };

    virtualHosts."matrix.axiomania.org" = {
      enableACME = true;
      forceSSL = true;
      locations."/" = {
        proxyPass = "http://127.0.0.1:6167";
        proxyWebsockets = true;
      };
    };

    virtualHosts."cache.axiomania.org" = {
      enableACME = true;
      forceSSL = true;
      locations."/" = {
        proxyPass = "http://[::1]:8080";
        proxyWebsockets = true;
        extraConfig = "client_max_body_size 0;";
      };
    };

    # ── VPN-only services (WireGuard clients only) ──
    virtualHosts."vault.axiomania.org" = {
      enableACME = true;
      forceSSL = true;
      locations."/" = {
        proxyPass = "http://127.0.0.1:8222";
        proxyWebsockets = true;
        extraConfig = "allow 10.100.0.0/24; allow 127.0.0.1; deny all;";
      };
    };

    virtualHosts."music.axiomania.org" = {
      enableACME = true;
      forceSSL = true;
      locations."/" = {
        proxyPass = "http://127.0.0.1:4533";
        proxyWebsockets = true;
        extraConfig = "allow 10.100.0.0/24; allow 127.0.0.1; deny all;";
      };
    };

    virtualHosts."sync.axiomania.org" = {
      enableACME = true;
      forceSSL = true;
      locations."/" = {
        proxyPass = "http://127.0.0.1:8384";
        proxyWebsockets = true;
        extraConfig = "allow 10.100.0.0/24; allow 127.0.0.1; deny all;";
      };
    };

    virtualHosts."books.axiomania.org" = {
      enableACME = true;
      forceSSL = true;
      locations."/" = {
        proxyPass = "http://127.0.0.1:5000";
        proxyWebsockets = true;
        extraConfig = "allow 10.100.0.0/24; allow 127.0.0.1; deny all;";
      };
    };

    virtualHosts."audio.axiomania.org" = {
      enableACME = true;
      forceSSL = true;
      locations."/" = {
        proxyPass = "http://127.0.0.1:8234";
        proxyWebsockets = true;
        extraConfig = "allow 10.100.0.0/24; allow 127.0.0.1; deny all;";
      };
    };

    virtualHosts."docs.axiomania.org" = {
      enableACME = true;
      forceSSL = true;
      locations."/" = {
        proxyPass = "http://127.0.0.1:28981";
        proxyWebsockets = true;
        extraConfig = "allow 10.100.0.0/24; allow 127.0.0.1; deny all;";
      };
    };

    virtualHosts."search.axiomania.org" = {
      enableACME = true;
      forceSSL = true;
      locations."/" = {
        proxyPass = "http://127.0.0.1:8888";
        proxyWebsockets = true;
        extraConfig = "allow 10.100.0.0/24; allow 127.0.0.1; deny all;";
      };
    };

    virtualHosts."home.axiomania.org" = {
      enableACME = true;
      forceSSL = true;
      locations."/" = {
        proxyPass = "http://127.0.0.1:8082";
        proxyWebsockets = true;
        extraConfig = "allow 10.100.0.0/24; allow 127.0.0.1; deny all;";
      };
    };

    # virtualHosts."share.axiomania.org" = {
    #   enableACME = true;
    #   forceSSL = true;
    #   locations."/" = {
    #     proxyPass = "http://127.0.0.1:53842";
    #     proxyWebsockets = true;
    #   };
    # };
  };

  security.acme = {
    acceptTerms = true;
    defaults.email = "gamma.kinematics@gmail.com";
  };

  # ============================================================================
  # Packages
  # ============================================================================
  environment.systemPackages = with pkgs; [
    git
    vim
    htop
    wireguard-tools
  ];
}
