import { NextRequest, NextResponse } from "next/server";
import { MetaService } from "../services/meta.service";
import { validateBasicMetas } from "../helpers/entity-meta.helpers";
function withUnifiedMeta(entityType) {
  return function(handler) {
    return async function(req, context) {
      const method = req.method;
      if (method === "GET") {
        return handleGetWithMeta(req, context, handler, entityType);
      } else if (method === "PUT" || method === "PATCH" || method === "POST") {
        return handleUpdateWithMeta(req, context, handler, entityType);
      } else {
        return handler(req, context);
      }
    };
  };
}
async function handleGetWithMeta(req, context, handler, entityType) {
  var _a;
  const result = await handler(req, context);
  const includeMeta = parseIncludeMetaParam(req);
  if (!includeMeta) {
    return result;
  }
  const userId = (_a = req.auth) == null ? void 0 : _a.userId;
  if (!userId) {
    return result;
  }
  const includePrivate = req.nextUrl.searchParams.get("includePrivate") === "true";
  if (result instanceof NextResponse) {
    return result;
  }
  return await enrichWithMeta(result, entityType, userId, includeMeta, includePrivate);
}
async function handleUpdateWithMeta(req, context, handler, entityType) {
  var _a;
  const body = await req.clone().json();
  const userId = (_a = req.auth) == null ? void 0 : _a.userId;
  const { meta, ...entityData } = body;
  let result;
  const isMetaOnlyUpdate = meta && Object.keys(entityData).length === 0;
  if (isMetaOnlyUpdate) {
    const params = await context.params;
    const id = params.id;
    if (!userId) {
      throw new Error("User authentication required for metadata updates");
    }
    result = await getExistingEntity(entityType, id, userId);
  } else {
    const modifiedReq = createModifiedRequest(req, entityData);
    result = await handler(modifiedReq, context);
  }
  if (meta && userId) {
    const entityId = typeof result === "object" && "id" in result ? result.id : await extractEntityId(context);
    const validation = validateBasicMetas(meta);
    if (!validation.isValid) {
      throw new Error(`Meta validation failed: ${validation.errors.join(", ")}`);
    }
    await MetaService.setBulkEntityMetas(entityType, entityId, meta, userId);
    const includeMeta = parseIncludeMetaParam(req);
    if (includeMeta && !(result instanceof NextResponse)) {
      result = await enrichWithMeta(result, entityType, userId, includeMeta, false);
    }
  }
  return result;
}
function parseIncludeMetaParam(req) {
  const includeMetaParam = req.nextUrl.searchParams.get("includeMeta");
  if (!includeMetaParam || includeMetaParam === "false") {
    return null;
  }
  if (includeMetaParam === "true" || includeMetaParam === "all") {
    return true;
  }
  return includeMetaParam.split(",").map((key) => key.trim());
}
async function enrichWithMeta(result, entityType, userId, includeMeta, includePrivate) {
  const isArray = Array.isArray(result);
  const entities = isArray ? result : [result];
  const enrichedEntities = await Promise.all(
    entities.map(async (entity) => {
      let meta;
      if (includeMeta === true) {
        meta = await MetaService.getEntityMetas(entityType, entity.id, userId, includePrivate);
      } else if (Array.isArray(includeMeta)) {
        meta = await MetaService.getSpecificEntityMetas(entityType, entity.id, includeMeta, userId);
      } else {
        meta = {};
      }
      return {
        ...entity,
        meta
      };
    })
  );
  return isArray ? enrichedEntities : enrichedEntities[0];
}
function createModifiedRequest(originalReq, entityData) {
  const newBody = JSON.stringify(entityData);
  return new NextRequest(originalReq.url, {
    method: originalReq.method,
    headers: originalReq.headers,
    body: newBody
  });
}
async function getExistingEntity(entityType, entityId, userId) {
  return { id: entityId };
}
async function extractEntityId(context) {
  const params = await context.params;
  return params.id;
}
export {
  withUnifiedMeta
};
