"use server";

import Dockerode from "dockerode";
import { pullImage } from "./image";

export async function runCode(code: string, language: string) {
  const docker = new Dockerode({ socketPath: "/var/run/docker.sock" });
  let container;

  try {
    if (language === "c") {
      const imageGCC = "gcc:latest";
      const images = await docker.listImages();
      const image = images.find(
        (image) => image.RepoTags && image.RepoTags.includes(imageGCC)
      );
      if (!image) {
        await pullImage(imageGCC);
      }

      container = await docker.createContainer({
        Image: imageGCC,
        Cmd: [
          "sh",
          "-c",
          `export LANG=C.UTF-8 && printf '%s' '${code.replace(
            /'/g,
            "'\\''"
          )}' > main.c && gcc main.c -o main && ./main`,
        ],
        Tty: false,
      });

      await container.start();

      const stream = await container.attach({
        stream: true,
        stdout: true,
        stderr: true,
      });

      const output = await new Promise<string>((resolve, reject) => {
        let output = "";
        stream.on("data", (chunk) => {
          output += chunk.toString("utf8");
        });
        stream.on("end", () => {
          resolve(output);
        });
        stream.on("error", (err) => {
          reject(err);
        });
      });

      console.log("Output:", output);

      // 检查输出中是否有错误信息
      const isCompilationSuccess = !output.includes("error:");

      return {
        success: isCompilationSuccess,
        output: output,
        message: isCompilationSuccess
          ? "Compilation successful"
          : "Compilation failed",
      };
    } else {
      throw new Error(`Unsupported language: ${language}`);
    }
  } catch (error) {
    console.error("Error running code:", error);
    return {
      success: false,
      output: error instanceof Error ? error.message : "Unknown error",
      message: "Compilation failed",
    };
  } finally {
    if (container) {
      try {
        const containerInfo = await container.inspect();
        if (containerInfo.State.Running) {
          await container.stop();
        }
        await container.remove();
      } catch (cleanupError) {
        console.error("Error cleaning up container:", cleanupError);
      }
    }
  }
}
