{ self, domains, serverPort, pkgs }:
let
  lib = pkgs.lib;
  serverPortStr = builtins.toString serverPort;
in {
  enable = true;
  logError = "/var/log/nginx/error.log info";
  commonHttpConfig = self.lib.commonHttpConfig;

  virtualHosts = self.lib.forDomains lib domains (domain: {
    ${domain} = {
      enableACME = true;  # Enable Let's Encrypt for SSL.
      forceSSL = true;    # Force HTTP to HTTPS redirection.

      # Enable detailed access logging
      extraConfig = ''
        access_log /var/log/nginx/access.log detailed;
        access_log /var/log/nginx/debug_404.log debug_404 if=$is_404;
        
        # Enable request body reading for logging
        client_body_buffer_size 128k;
        client_max_body_size 10m;
        proxy_request_buffering on;
        
        # Add request ID for tracing
        add_header X-Request-ID $request_id;
        
        # Custom error pages to capture more details
        error_page 404 @custom_404;
      '';

      locations."@custom_404" = {
        extraConfig = ''
          internal;
          access_log /var/log/nginx/404_details.log debug_404;
          return 404 '{"error": "Not Found", "timestamp": "$time_iso8601", "request_id": "$request_id"}';
          add_header Content-Type application/json;
        '';
      };

      locations."/shop-verification-QR2Opqr7JX.txt" = {
        root = pkgs.runCommand "shop-verification-root" {} ''
          mkdir -p $out
          cp ${./shop-verification-QR2Opqr7JX.txt} $out/shop-verification-QR2Opqr7JX.txt
        '';
        tryFiles = "/shop-verification-QR2Opqr7JX.txt =404";
      };

      locations."/apays/callback" = {
        extraConfig = ''
          # Enable request body reading for callback logging
          proxy_request_buffering on;
          
          # Handle both /apays/callback and /apays/callback/something
          rewrite ^/apays/callback/?(.*)$ /$1 break;

          proxy_pass http://127.0.0.1:${serverPortStr}/rpc/apays_callback;
          proxy_set_header Host \$host;
          proxy_set_header X-Real-IP \$remote_addr;
        '';
      };

      locations."/cardlink/callback" = {
        extraConfig = ''
          # Enable request body reading for callback logging
          proxy_request_buffering on;
          
          # Handle both /cardlink/callback and /cardlink/callback/something
          rewrite ^/cardlink/callback/?(.*)$ /$1 break;

          proxy_pass http://127.0.0.1:${serverPortStr}/rpc/cardlink_callback;
          proxy_set_header Host \$host;
          proxy_set_header X-Real-IP \$remote_addr;
        '';
      };

      locations."/aaio/callback" = {
        extraConfig = ''
          # Enable request body reading for callback logging
          proxy_request_buffering on;
          
          # Handle both /aaio/callback and /aaio/callback/something
          rewrite ^/aaio/callback/?(.*)$ /$1 break;

          proxy_pass http://127.0.0.1:${serverPortStr}/api/rpc/aaio_callback;
          proxy_set_header Host \$host;
          proxy_set_header X-Real-IP \$remote_addr;
        '';
      };

      locations."/freekassa/callback" = {
        extraConfig = ''
          # Enable request body reading for callback logging
          proxy_request_buffering on;
          
          # Handle both /freekassa/callback and /freekassa/callback/something
          rewrite ^/freekassa/callback/?(.*)$ /$1 break;

          proxy_pass http://127.0.0.1:${serverPortStr}/rpc/freekassa_callback;
          proxy_set_header Host \$host;
          proxy_set_header X-Real-IP \$remote_addr;
        '';
      };

      locations."/proxy-link" = {
        extraConfig = ''
          if ($uri = "/proxy-link") {
            rewrite ^ /rpc/proxy break;
          }            
          if ($uri = "/proxy-link/") {
            rewrite ^ /rpc/proxy break;
          }

          rewrite ^/proxy-link\.(.*)$ /rpc/$1 break; 

          proxy_pass http://127.0.0.1:${serverPortStr};
	  proxy_set_header Accept text/plain;
          proxy_set_header Content-Profile public_api;
          proxy_set_header Accept-Profile public_api;
          proxy_set_header Host $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;
        '';
      };

      locations."/public-api" = {
        extraConfig = ''
          if ($uri = "/public-api") {
            rewrite ^ / break;
          }            
          if ($uri = "/public-api/") {
            rewrite ^ / break;
          }
          rewrite (.+)/(.*) $1.$2;       
          rewrite ^/public-api\.(.*)$ /rpc/$1 break; 

          proxy_pass http://127.0.0.1:${serverPortStr};
          proxy_set_header Content-Profile public_api;
          proxy_set_header Accept-Profile public_api;
          proxy_set_header Host $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;
        '';
      };

      locations."/reseller-api" = {
        extraConfig = ''
          if ($uri = "/reseller-api") {
            rewrite ^ / break;
          }            
          if ($uri = "/reseller-api/") {
            rewrite ^ / break;
          }
          rewrite (.+)/(.*) $1.$2;       
          rewrite ^/reseller-api\.(.*)$ /rpc/$1 break; 

          proxy_pass http://127.0.0.1:${serverPortStr};
          proxy_set_header Content-Profile reseller_gateway;
          proxy_set_header Accept-Profile reseller_gateway;
          proxy_set_header Host $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;
        '';
      };

      locations."/admin" = {
        extraConfig = ''
          if ($uri = "/admin") {
            rewrite ^/admin$ / break;
          }

          rewrite ^/admin/(.*)$ /$1 break;
          proxy_pass http://127.0.0.1:${serverPortStr};
          proxy_set_header Content-Profile admin;
          proxy_set_header Accept-Profile admin;
          proxy_set_header Host $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;
        '';
      };

      locations."/api/v2/rpc" = {
        extraConfig = ''
          if ($uri = "/api/v2/rpc") {
            rewrite ^ /rpc break;
          }
          if ($uri = "/api/v2/rpc/") {
            rewrite ^ /rpc break;
          }

          rewrite (.+)/(.*) $1.$2;       
          rewrite ^/api/v2/rpc\.(.*)$ /rpc/$1 break; 

          proxy_pass http://127.0.0.1:${serverPortStr};
          proxy_set_header Host $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;
        '';
      };

      locations."/api/v2/rest" = {
        extraConfig = ''
          if ($uri = "/api/v2/rest") {
            rewrite ^ / break;
          }
          if ($uri = "/api/v2/rest/") {
            rewrite ^ / break;
          }

          rewrite (.+)/(.*) $1.$2;
          rewrite ^/api/v2/rest\.(.*)$ /$1 break;

          proxy_pass http://127.0.0.1:${serverPortStr};
          proxy_set_header Host $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;
        '';
      };

      locations."/api" = {
        extraConfig = ''
          if ($uri = "/api") {
            rewrite ^/api$ / break;
          }

          rewrite ^/api/(.*)$ /$1 break;
          proxy_pass http://127.0.0.1:${serverPortStr};
          proxy_set_header Host $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;
        '';
      };
    };
    # TODO: move to marzban module
    #"marzban.yukkop.dev" = {
    #  enableACME = true;
    #  forceSSL = true;

    #  # Enable detailed access logging for marzban subdomain
    #  extraConfig = ''
    #    access_log /var/log/nginx/marzban_access.log detailed;
    #    access_log /var/log/nginx/marzban_404.log debug_404 if=$is_404;
    #    
    #    # Add request ID for tracing
    #    add_header X-Request-ID $request_id;
    #    
    #    # Custom error pages to capture more details
    #    error_page 404 @marzban_custom_404;
    #  '';

    #  locations."@marzban_custom_404" = {
    #    extraConfig = ''
    #      internal;
    #      access_log /var/log/nginx/marzban_404_details.log debug_404;
    #      return 404 '{"error": "Not Found", "timestamp": "$time_iso8601", "request_id": "$request_id", "service": "marzban"}';
    #      add_header Content-Type application/json;
    #    '';
    #  };

    #  locations."/" = {
    #    extraConfig = ''
    #      proxy_pass http://127.0.0.1:8000;
    #      proxy_set_header Host $host;
    #      proxy_set_header X-Real-IP $remote_addr;
    #      proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    #    '';
    #  };
    #};
  });
}
