import { All, Controller, Param, Req, Res } from "@nestjs/common";
import type { Request, Response } from "express";
import { FunctionExecutionService } from "./execution.service.js";

@Controller("exec")
export class ExecutionController {
  constructor(
    private readonly functionExecutionService: FunctionExecutionService
  ) {}

  @All(":projectSlug")
  async handleRoot(
    @Param("projectSlug") projectSlug: string,
    @Req() request: Request,
    @Res() response: Response
  ) {
    await this.dispatchExecution(projectSlug, request, response);
  }

  @All(":projectSlug/*path")
  async handleNested(
    @Param("projectSlug") projectSlug: string,
    @Req() request: Request,
    @Res() response: Response
  ) {
    await this.dispatchExecution(projectSlug, request, response);
  }

  private async dispatchExecution(
    projectSlug: string,
    request: Request,
    response: Response
  ) {
    const executionResult = await this.functionExecutionService.execute(
      projectSlug,
      request
    );

    if (executionResult.responsePayload) {
      const { statusCode, headers, body } = executionResult.responsePayload;
      this.applyHeaders(response, headers);
      this.sendBody(response, statusCode ?? 200, body ?? "");
      return;
    } else {
      this.sendBody(response, 500, executionResult.stderr);
    }
  }

  private applyHeaders(
    response: Response,
    headers: Record<string, string> | undefined
  ) {
    if (!headers) {
      return;
    }

    for (const [key, value] of Object.entries(headers)) {
      response.setHeader(key, value);
    }
  }

  private sendBody(response: Response, statusCode: number, body: string) {
    response.status(statusCode).send(body);
  }
}
