const { validatedRequest } = require("../../utils/middleware/validatedRequest");
const {
  flexUserRoleValid,
  ROLES,
} = require("../../utils/middleware/multiUserProtected");
const { reqBody } = require("../../utils/http");
const { safeJsonParse, decodeHtmlEntities } = require("../../utils/http");
const {
  parseLemonadeServerEndpoint,
} = require("../../utils/AiProviders/lemonade");

function lemonadeUtilsEndpoints(app) {
  if (!app) return;

  app.post(
    "/utils/lemonade/download-model",
    [validatedRequest, flexUserRoleValid([ROLES.admin])],
    async (request, response) => {
      try {
        const { modelId, basePath = "" } = reqBody(request);
        const lemonadeUrl = new URL(
          parseLemonadeServerEndpoint(
            basePath ?? process.env.LEMONADE_LLM_BASE_PATH,
            "base"
          )
        );
        lemonadeUrl.pathname += "api/v1/pull";
        response.writeHead(200, {
          "Content-Type": "text/event-stream",
          "Cache-Control": "no-cache",
          Connection: "keep-alive",
        });

        const lemonadeResponse = await fetch(lemonadeUrl.toString(), {
          method: "POST",
          headers: {
            ...(!!process.env.LEMONADE_LLM_API_KEY
              ? { Authorization: `Bearer ${process.env.LEMONADE_LLM_API_KEY}` }
              : {}),
            "Content-Type": "application/json",
          },
          body: JSON.stringify({
            model_name: String(modelId),
            stream: true,
          }),
        });
        if (!lemonadeResponse.ok)
          throw new Error(
            lemonadeResponse.statusText ||
              "An error occurred while downloading the model"
          );
        const reader = lemonadeResponse.body.getReader();
        let done = false;
        let currentEvent = null;

        while (!done) {
          const { value, done: readerDone } = await reader.read();
          if (readerDone) done = true;

          const chunk = new TextDecoder("utf-8").decode(value);
          const lines = chunk.split("\n");
          for (const line of lines) {
            if (!line.trim()) continue;

            if (line.startsWith("event:")) {
              currentEvent = line.replace("event:", "").trim();
              continue;
            }

            if (line.startsWith("data:")) {
              const jsonStr = line.replace("data:", "").trim();
              const decodedLine = decodeHtmlEntities(jsonStr);
              const data = safeJsonParse(decodedLine);
              if (!data) continue;

              if (currentEvent === "error") {
                throw new Error(
                  data.message ||
                    "An error occurred while downloading the model"
                );
              } else if (currentEvent === "complete") {
                response.write(
                  `data: ${JSON.stringify({ type: "success", percentage: 100, message: "Model downloaded successfully" })}\n\n`
                );
                done = true;
              } else if (currentEvent === "progress") {
                const percentage = data.percent ?? 0;
                const message = data.file
                  ? `Downloading ${data.file}`
                  : "Downloading model...";
                response.write(
                  `data: ${JSON.stringify({ type: "progress", percentage, message })}\n\n`
                );
              }

              currentEvent = null;
            }
          }
        }
      } catch (e) {
        console.error(e);
        response.write(
          `data: ${JSON.stringify({ type: "error", message: e.message })}\n\n`
        );
      } finally {
        response.end();
      }
    }
  );

  app.post(
    "/utils/lemonade/delete-model",
    [validatedRequest, flexUserRoleValid([ROLES.admin])],
    async (request, response) => {
      try {
        const { modelId, basePath = "" } = reqBody(request);
        if (!modelId) {
          return response.status(400).json({
            success: false,
            error: "modelId is required",
          });
        }

        const lemonadeUrl = new URL(
          parseLemonadeServerEndpoint(
            basePath ?? process.env.LEMONADE_LLM_BASE_PATH,
            "base"
          )
        );
        lemonadeUrl.pathname += "api/v1/delete";

        const lemonadeResponse = await fetch(lemonadeUrl.toString(), {
          method: "POST",
          headers: {
            ...(!!process.env.LEMONADE_LLM_API_KEY
              ? { Authorization: `Bearer ${process.env.LEMONADE_LLM_API_KEY}` }
              : {}),
            "Content-Type": "application/json",
          },
          body: JSON.stringify({
            model_name: String(modelId),
          }),
        });

        const data = await lemonadeResponse.json();
        if (!lemonadeResponse.ok || data.status === "error") {
          return response.status(lemonadeResponse.status || 500).json({
            success: false,
            error: data.message || "An error occurred while deleting the model",
          });
        }

        return response.status(200).json({
          success: true,
          message: data.message || `Deleted model: ${modelId}`,
        });
      } catch (e) {
        console.error(e);
        return response.status(500).json({
          success: false,
          error: e.message || "An error occurred while deleting the model",
        });
      }
    }
  );
}

module.exports = {
  lemonadeUtilsEndpoints,
};
