const { Memory } = require("../models/memory");
const { SystemSettings } = require("../models/systemSettings");
const { userFromSession, reqBody } = require("../utils/http");
const { validatedRequest } = require("../utils/middleware/validatedRequest");
const {
  flexUserRoleValid,
  ROLES,
} = require("../utils/middleware/multiUserProtected");
const { validWorkspaceSlug } = require("../utils/middleware/validWorkspace");

async function memoryFeatureEnabled(_req, response, next) {
  const enabled = await SystemSettings.memoriesEnabled();
  if (!enabled)
    return response.status(403).json({ error: "Personalization is disabled." });
  next();
}

/**
 * Loads the memory by :memoryId and, in multi-user mode, scopes the query to the requester's userId.
 * A memory owned by another user returns null here and is indistinguishable from "not found" — 404 either way.
 */
async function validateMemoryOwner(request, response, next) {
  try {
    const clause = { id: Number(request.params.memoryId) };
    if (response.locals.multiUserMode) {
      const user = await userFromSession(request, response);
      clause.userId = user?.id ?? null;
    }

    const memory = await Memory.get(clause);
    if (!memory)
      return response.status(404).json({ error: "Memory not found." });

    next();
  } catch (e) {
    console.error(e);
    return response.sendStatus(500);
  }
}

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

  app.get(
    "/workspaces/:slug/memories",
    [
      validatedRequest,
      flexUserRoleValid([ROLES.all]),
      memoryFeatureEnabled,
      validWorkspaceSlug,
    ],
    async (request, response) => {
      try {
        const user = await userFromSession(request, response);
        const workspace = response.locals.workspace;

        const [globalMemories, workspaceMemories] = await Promise.all([
          Memory.globalForUser(user?.id),
          Memory.forUserWorkspace(user?.id, workspace.id),
        ]);
        response.status(200).json({
          memories: { global: globalMemories, workspace: workspaceMemories },
        });
      } catch (e) {
        console.error(e);
        return response.sendStatus(500);
      }
    }
  );

  app.post(
    "/workspaces/:slug/memories",
    [
      validatedRequest,
      flexUserRoleValid([ROLES.all]),
      memoryFeatureEnabled,
      validWorkspaceSlug,
    ],
    async (request, response) => {
      try {
        const user = await userFromSession(request, response);
        const workspace = response.locals.workspace;
        const { content, scope = "workspace" } = reqBody(request);
        const { memory, message } = await Memory.create({
          userId: user?.id,
          workspaceId: scope === "global" ? null : workspace.id,
          scope,
          content: content.trim(),
        });

        if (!memory) return response.status(400).json({ error: message });
        response.status(200).json({ memory });
      } catch (e) {
        console.error(e);
        return response.sendStatus(500);
      }
    }
  );

  app.put(
    "/memories/:memoryId",
    [
      validatedRequest,
      flexUserRoleValid([ROLES.all]),
      memoryFeatureEnabled,
      validateMemoryOwner,
    ],
    async (request, response) => {
      try {
        const memoryId = Number(request.params.memoryId);
        const { content } = reqBody(request);
        const { memory, message } = await Memory.update(memoryId, {
          content: content.trim(),
        });

        if (!memory) return response.status(400).json({ error: message });
        response.status(200).json({ memory });
      } catch (e) {
        console.error(e);
        return response.sendStatus(500);
      }
    }
  );

  app.delete(
    "/memories/:memoryId",
    [
      validatedRequest,
      flexUserRoleValid([ROLES.all]),
      memoryFeatureEnabled,
      validateMemoryOwner,
    ],
    async (request, response) => {
      try {
        const memoryId = Number(request.params.memoryId);
        await Memory.delete(memoryId);
        response.status(200).json({ success: true });
      } catch (e) {
        console.error(e);
        return response.sendStatus(500);
      }
    }
  );

  app.post(
    "/memories/:memoryId/promote",
    [
      validatedRequest,
      flexUserRoleValid([ROLES.all]),
      memoryFeatureEnabled,
      validateMemoryOwner,
    ],
    async (request, response) => {
      try {
        const memoryId = Number(request.params.memoryId);
        const { memory, message } = await Memory.promoteToGlobal(memoryId);
        if (!memory) return response.status(400).json({ error: message });

        response.status(200).json({ memory });
      } catch (e) {
        console.error(e);
        return response.sendStatus(500);
      }
    }
  );

  app.post(
    "/memories/:memoryId/demote/:slug",
    [
      validatedRequest,
      flexUserRoleValid([ROLES.all]),
      memoryFeatureEnabled,
      validateMemoryOwner,
      validWorkspaceSlug,
    ],
    async (request, response) => {
      try {
        const memoryId = Number(request.params.memoryId);
        const targetWorkspace = response.locals.workspace;

        const { memory, message } = await Memory.demoteToWorkspace(
          memoryId,
          targetWorkspace.id
        );

        if (!memory) return response.status(400).json({ error: message });
        response.status(200).json({ memory });
      } catch (e) {
        console.error(e);
        return response.sendStatus(500);
      }
    }
  );
}

module.exports = { memoryEndpoints };
