import { NextResponse } from "next/server";
import { authenticateRequest, hasRequiredScope, canBypassTeamContext } from "../auth/dual-auth";
import { resolveEntityFromUrl, validateEntityOperation } from "./resolver";
import { generateEntitySchemas } from "../../entities/schema-generator";
import { queryWithRLS, mutateWithRLS, queryOneWithRLS } from "../../db";
import {
  createApiResponse,
  createApiError,
  parsePaginationParams,
  createPaginationMeta,
  parseMetaParams,
  parseChildParams,
  includeEntityMetadata,
  includeEntityChildren,
  processEntityMetadata,
  handleEntityMetadataInResponse,
  addCorsHeaders,
  handleCorsPreflightRequest
} from "../helpers";
import { afterEntityCreate, afterEntityUpdate, afterEntityDelete } from "../../entities/entity-hooks";
async function includeTaxonomiesInData(entityConfig, items, userId) {
  var _a, _b, _c;
  if (!((_a = entityConfig.taxonomies) == null ? void 0 : _a.enabled) || !((_c = (_b = entityConfig.taxonomies) == null ? void 0 : _b.types) == null ? void 0 : _c.length) || items.length === 0) {
    return items;
  }
  const entityIds = items.map((item) => item.id);
  const entityType = entityConfig.slug;
  const taxonomyMap = {};
  const placeholders = entityIds.map((_, i) => `$${i + 2}`).join(", ");
  const taxonomyQuery = `
    SELECT
      etr."entityId",
      etr."order",
      t.id,
      t.name,
      t.slug,
      t.type,
      t.color,
      t.icon
    FROM entity_taxonomy_relations etr
    JOIN taxonomies t ON etr."taxonomyId" = t.id
    WHERE etr."entityType" = $1
      AND etr."entityId" IN (${placeholders})
      AND t."isActive" = true
      AND t."deletedAt" IS NULL
    ORDER BY etr."order" ASC
  `;
  const taxonomyResults = await queryWithRLS(taxonomyQuery, [entityType, ...entityIds], userId);
  for (const row of taxonomyResults) {
    if (!taxonomyMap[row.entityId]) {
      taxonomyMap[row.entityId] = {};
    }
    const taxonomyTypeConfig = entityConfig.taxonomies.types.find((tc) => tc.type === row.type);
    if (taxonomyTypeConfig) {
      const fieldName = taxonomyTypeConfig.field;
      if (!taxonomyMap[row.entityId][fieldName]) {
        taxonomyMap[row.entityId][fieldName] = [];
      }
      taxonomyMap[row.entityId][fieldName].push({
        id: row.id,
        name: row.name,
        slug: row.slug,
        color: row.color,
        icon: row.icon
      });
    }
  }
  return items.map((item) => {
    const itemTaxonomies = taxonomyMap[item.id] || {};
    const taxonomyFields = {};
    for (const tc of entityConfig.taxonomies.types) {
      taxonomyFields[tc.field] = itemTaxonomies[tc.field] || [];
    }
    return {
      ...item,
      ...taxonomyFields
    };
  });
}
async function processTaxonomyRelations(entityConfig, entityId, data, userId, isUpdate = false) {
  var _a, _b, _c;
  if (!((_a = entityConfig.taxonomies) == null ? void 0 : _a.enabled) || !((_c = (_b = entityConfig.taxonomies) == null ? void 0 : _b.types) == null ? void 0 : _c.length)) {
    return;
  }
  const entityType = entityConfig.slug;
  for (const taxonomyType of entityConfig.taxonomies.types) {
    const fieldName = taxonomyType.field;
    const taxonomyIds = data[fieldName];
    if (taxonomyIds === void 0) continue;
    if (isUpdate) {
      await mutateWithRLS(
        `DELETE FROM entity_taxonomy_relations
         WHERE "entityType" = $1 AND "entityId" = $2
         AND "taxonomyId" IN (SELECT id FROM taxonomies WHERE type = $3)`,
        [entityType, entityId, taxonomyType.type],
        userId
      );
    }
    if (Array.isArray(taxonomyIds) && taxonomyIds.length > 0) {
      for (let i = 0; i < taxonomyIds.length; i++) {
        const taxonomyId = typeof taxonomyIds[i] === "object" && taxonomyIds[i] !== null ? taxonomyIds[i].id : taxonomyIds[i];
        await mutateWithRLS(
          `INSERT INTO entity_taxonomy_relations ("entityType", "entityId", "taxonomyId", "order")
           VALUES ($1, $2, $3, $4)`,
          [entityType, entityId, taxonomyId, i + 1],
          userId
        );
      }
    }
  }
}
function parseTaxonomyFilterParams(url, entityConfig) {
  var _a;
  if (!((_a = entityConfig.taxonomies) == null ? void 0 : _a.enabled)) return null;
  const categoryId = url.searchParams.get("categoryId");
  if (categoryId) {
    const categoryType = entityConfig.taxonomies.types.find((t) => t.type.includes("category"));
    if (categoryType) {
      return { taxonomyId: categoryId, taxonomyType: categoryType.type };
    }
  }
  const taxonomyId = url.searchParams.get("taxonomyId");
  if (taxonomyId) {
    return { taxonomyId, taxonomyType: url.searchParams.get("taxonomyType") || void 0 };
  }
  return null;
}
function getTableName(entityConfig) {
  return entityConfig.tableName || entityConfig.slug;
}
function getTeamIdFromRequest(request) {
  return request.headers.get("x-team-id");
}
function isBuilderRequest(request) {
  return request.headers.get("x-builder-source") === "true";
}
async function validateTeamMembership(userId, teamId) {
  try {
    console.log("[GenericHandler] Validating team membership:", { userId, teamId, teamIdLength: teamId == null ? void 0 : teamId.length });
    const member = await queryOneWithRLS(
      'SELECT id FROM "team_members" WHERE "teamId" = $1 AND "userId" = $2',
      [teamId, userId],
      userId
    );
    console.log("[GenericHandler] Team membership result:", { found: !!member, memberId: member == null ? void 0 : member.id });
    return !!member;
  } catch (error) {
    console.error("[GenericHandler] Error validating team membership:", error);
    return false;
  }
}
async function validateTeamContextWithBypass(request, authResult, userId) {
  const teamId = getTeamIdFromRequest(request);
  const canBypass = await canBypassTeamContext(authResult, request);
  if (canBypass) {
    console.log("[GenericHandler] Admin bypass active:", { userId, teamId: teamId || "cross-team" });
    return { valid: true, teamId };
  }
  if (!teamId) {
    const response = createApiError(
      "Team context required. Include x-team-id header.",
      400,
      void 0,
      "TEAM_CONTEXT_REQUIRED"
    );
    return { valid: false, error: await addCorsHeaders(response) };
  }
  const isMember = await validateTeamMembership(userId, teamId);
  if (!isMember) {
    const response = createApiError(
      "Access denied: You are not a member of this team",
      403,
      void 0,
      "TEAM_ACCESS_DENIED"
    );
    return { valid: false, error: await addCorsHeaders(response) };
  }
  return { valid: true, teamId };
}
async function handleGenericList(request) {
  var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j;
  try {
    const resolution = await resolveEntityFromUrl(request.nextUrl.pathname);
    if (!resolution.isValidEntity || !resolution.entityConfig) {
      const response2 = createApiError("Entity not found", 404);
      return addCorsHeaders(response2);
    }
    if (!validateEntityOperation(resolution.entityConfig, "list")) {
      const response2 = createApiError("List operation not supported for this entity", 405);
      return addCorsHeaders(response2);
    }
    const authResult = await authenticateRequest(request);
    let userId = null;
    let teamId = null;
    if (!authResult.success && ((_a = resolution.entityConfig.access) == null ? void 0 : _a.public)) {
      console.log(`[GenericHandler] Public access allowed for ${resolution.entityConfig.slug} list`);
    } else if (!authResult.success) {
      return NextResponse.json(
        { success: false, error: "Authentication required", code: "AUTHENTICATION_FAILED" },
        { status: 401 }
      );
    } else {
      if (authResult.rateLimitResponse) {
        return authResult.rateLimitResponse;
      }
      if (!hasRequiredScope(authResult, `${resolution.entityConfig.slug}:read`)) {
        const response2 = createApiError("Insufficient permissions", 403);
        return addCorsHeaders(response2);
      }
      userId = authResult.user.id;
      const teamValidation = await validateTeamContextWithBypass(request, authResult, userId);
      if (!teamValidation.valid) {
        return teamValidation.error;
      }
      teamId = teamValidation.teamId;
    }
    const pagination = parsePaginationParams(request);
    const metaParams = parseMetaParams(request);
    const url = new URL(request.url);
    const fieldsParam = url.searchParams.get("fields");
    const distinctParam = url.searchParams.get("distinct") === "true";
    const idsFromParams = url.searchParams.getAll("ids");
    const specificIds = idsFromParams.length > 0 ? idsFromParams.flatMap((param) => param.split(",").map((id) => id.trim())).filter(Boolean) : null;
    const knownParams = /* @__PURE__ */ new Set(["page", "limit", "fields", "distinct", "ids", "parentId", "search", "sortBy", "sortOrder", "child", "meta", "from", "to", "dateField"]);
    const customFilters = {};
    url.searchParams.forEach((value, key) => {
      if (!knownParams.has(key) && value) {
        if (!customFilters[key]) {
          customFilters[key] = [];
        }
        const values = value.includes(",") ? value.split(",").map((v) => v.trim()) : [value];
        customFilters[key].push(...values);
      }
    });
    const entityConfig = resolution.entityConfig;
    let fields;
    if (fieldsParam && distinctParam) {
      const fieldName = fieldsParam;
      const isJsonbField = fieldName === "contentLanguages" || fieldName === "brandValues" || fieldName === "hashtags";
      if (isJsonbField) {
        return handleDistinctJsonbField(entityConfig, fieldName, url, userId);
      } else {
        fields = `DISTINCT "${fieldName}" as value, "${fieldName}" as label, '${entityConfig.slug}' as "entityType"`;
      }
    } else if (fieldsParam) {
      const requestedFields = fieldsParam.split(",").map((f) => f.trim());
      const validFields = requestedFields.filter(
        (fieldName) => entityConfig.fields.some((field) => field.name === fieldName)
      );
      fields = ["id", ...validFields].map((fieldName) => {
        const columnName = /[A-Z]/.test(fieldName) ? `"${fieldName}"` : fieldName;
        return `t.${columnName}`;
      }).join(", ");
    } else {
      const systemFields = ["id", "createdAt", "updatedAt"];
      if ((_b = entityConfig.builder) == null ? void 0 : _b.enabled) {
        systemFields.push("blocks");
      }
      const configFields = entityConfig.fields.map((field) => {
        const columnName = /[A-Z]/.test(field.name) ? `"${field.name}"` : field.name;
        return `t.${columnName}`;
      });
      const systemFieldsFormatted = systemFields.map((fieldName) => {
        const columnName = /[A-Z]/.test(fieldName) ? `"${fieldName}"` : fieldName;
        return `t.${columnName}`;
      });
      fields = [...systemFieldsFormatted, ...configFields].join(", ");
    }
    let query;
    let queryParams;
    let paramIndex = 1;
    const searchParam = url.searchParams.get("search");
    const fromDate = url.searchParams.get("from");
    const toDate = url.searchParams.get("to");
    const dateFieldName = url.searchParams.get("dateField");
    const isPublicEntity = ((_c = entityConfig.access) == null ? void 0 : _c.public) === true;
    const requestingPublishedOnly = (_d = customFilters["status"]) == null ? void 0 : _d.includes("published");
    const skipUserFilter = isPublicEntity && requestingPublishedOnly;
    if (skipUserFilter && process.env.NODE_ENV === "development") {
      console.log(`[GenericHandler] Public access mode: skipping userId filter for ${entityConfig.slug} (status=published)`);
    }
    const tableName = getTableName(entityConfig);
    const taxonomyFilter = parseTaxonomyFilterParams(url, entityConfig);
    if (specificIds && specificIds.length > 0) {
      const idPlaceholders = specificIds.map(() => `$${paramIndex++}`).join(", ");
      query = `SELECT ${fields} FROM "${tableName}" t WHERE t.id IN (${idPlaceholders})`;
      queryParams = [...specificIds];
      if (teamId && !skipUserFilter) {
        query += ` AND t."teamId" = $${paramIndex++}`;
        queryParams.push(teamId);
      }
      if (userId && !((_e = entityConfig.access) == null ? void 0 : _e.shared) && !skipUserFilter) {
        query += ` AND t."userId" = $${paramIndex++}`;
        queryParams.push(userId);
      }
    } else if (fieldsParam && distinctParam) {
      const fieldName = fieldsParam;
      const parentId = url.searchParams.get("parentId");
      query = `SELECT ${fields} FROM "${tableName}" t WHERE 1=1`;
      queryParams = [];
      if (teamId && !skipUserFilter) {
        query += ` AND t."teamId" = $${paramIndex++}`;
        queryParams.push(teamId);
      }
      if (parentId) {
        query += ` AND t."parentId" = $${paramIndex++}`;
        queryParams.push(parentId);
      }
      if (userId && !((_f = entityConfig.access) == null ? void 0 : _f.shared) && !skipUserFilter) {
        query += ` AND t."userId" = $${paramIndex++}`;
        queryParams.push(userId);
      }
      query += ` ORDER BY "${fieldName}" ASC LIMIT $${paramIndex++}`;
      queryParams.push(pagination.limit);
    } else {
      const whereConditions = [];
      queryParams = [];
      paramIndex = 1;
      if (teamId && !skipUserFilter) {
        whereConditions.push(`t."teamId" = $${paramIndex++}`);
        queryParams.push(teamId);
      }
      if (userId && !((_g = entityConfig.access) == null ? void 0 : _g.shared) && !skipUserFilter) {
        whereConditions.push(`t."userId" = $${paramIndex++}`);
        queryParams.push(userId);
      }
      if (searchParam && searchParam.trim() !== "") {
        const searchTerm = searchParam.trim();
        const hasName = entityConfig.fields.some((f) => f.name === "name");
        const hasTitle = entityConfig.fields.some((f) => f.name === "title");
        const hasSlug = entityConfig.fields.some((f) => f.name === "slug");
        const hasContent = entityConfig.fields.some((f) => f.name === "content");
        if (hasName || hasTitle || hasSlug || hasContent) {
          const searchConditions = [];
          if (hasName) {
            searchConditions.push(`t.name ILIKE $${paramIndex}`);
          }
          if (hasTitle) {
            searchConditions.push(`t.title ILIKE $${paramIndex}`);
          }
          if (hasSlug) {
            searchConditions.push(`t.slug ILIKE $${paramIndex}`);
          }
          if (hasContent) {
            searchConditions.push(`t.content ILIKE $${paramIndex}`);
          }
          whereConditions.push(`(${searchConditions.join(" OR ")})`);
          queryParams.push(`%${searchTerm}%`);
          paramIndex++;
        }
      }
      if (dateFieldName && (fromDate || toDate)) {
        const field = entityConfig.fields.find((f) => f.name === dateFieldName);
        if (field && (field.type === "datetime" || field.type === "date")) {
          if (fromDate) {
            whereConditions.push(`t."${dateFieldName}" >= $${paramIndex++}`);
            queryParams.push(fromDate);
          }
          if (toDate) {
            whereConditions.push(`t."${dateFieldName}" <= $${paramIndex++}`);
            queryParams.push(toDate);
          }
        }
      }
      Object.entries(customFilters).forEach(([key, values]) => {
        const field = entityConfig.fields.find((f) => f.name === key);
        if (field && values.length > 0) {
          const columnName = `"${key}"`;
          if (field.type === "relation-multi" || key === "socialPlatformId") {
            const orConditions = values.map(() => {
              const condition = `t.${columnName}::jsonb @> $${paramIndex++}::jsonb`;
              return condition;
            });
            values.forEach((value) => {
              queryParams.push(JSON.stringify([value]));
            });
            whereConditions.push(`(${orConditions.join(" OR ")})`);
          } else {
            const orConditions = values.map(() => {
              const condition = `t.${columnName} = $${paramIndex++}`;
              return condition;
            });
            values.forEach((value) => {
              queryParams.push(value);
            });
            whereConditions.push(`(${orConditions.join(" OR ")})`);
          }
        }
      });
      if (taxonomyFilter == null ? void 0 : taxonomyFilter.taxonomyId) {
        whereConditions.push(`EXISTS (
          SELECT 1 FROM entity_taxonomy_relations etr
          WHERE etr."entityId" = t.id::text
            AND etr."entityType" = '${entityConfig.slug}'
            AND etr."taxonomyId" = $${paramIndex++}
        )`);
        queryParams.push(taxonomyFilter.taxonomyId);
      }
      const whereClause = whereConditions.length > 0 ? `WHERE ${whereConditions.join(" AND ")}` : "";
      query = `
        SELECT ${fields}
        FROM "${tableName}" t
        ${whereClause}
        ORDER BY t."createdAt" DESC
        LIMIT $${paramIndex++} OFFSET $${paramIndex++}
      `;
      queryParams.push(pagination.limit, pagination.offset);
    }
    const data = await queryWithRLS(query, queryParams, userId);
    let totalResult;
    const countWhereConditions = [];
    const countParams = [];
    let countParamIndex = 1;
    if (teamId && !skipUserFilter) {
      countWhereConditions.push(`"teamId" = $${countParamIndex++}`);
      countParams.push(teamId);
    }
    if (userId && !((_h = entityConfig.access) == null ? void 0 : _h.shared) && !skipUserFilter) {
      countWhereConditions.push(`"userId" = $${countParamIndex++}`);
      countParams.push(userId);
    }
    if (searchParam && searchParam.trim() !== "") {
      const searchTerm = searchParam.trim();
      const hasName = entityConfig.fields.some((f) => f.name === "name");
      const hasTitle = entityConfig.fields.some((f) => f.name === "title");
      const hasSlug = entityConfig.fields.some((f) => f.name === "slug");
      const hasContent = entityConfig.fields.some((f) => f.name === "content");
      if (hasName || hasTitle || hasSlug || hasContent) {
        const searchConditions = [];
        if (hasName) {
          searchConditions.push(`name ILIKE $${countParamIndex}`);
        }
        if (hasTitle) {
          searchConditions.push(`title ILIKE $${countParamIndex}`);
        }
        if (hasSlug) {
          searchConditions.push(`slug ILIKE $${countParamIndex}`);
        }
        if (hasContent) {
          searchConditions.push(`content ILIKE $${countParamIndex}`);
        }
        countWhereConditions.push(`(${searchConditions.join(" OR ")})`);
        countParams.push(`%${searchTerm}%`);
        countParamIndex++;
      }
    }
    if (dateFieldName && (fromDate || toDate)) {
      const field = entityConfig.fields.find((f) => f.name === dateFieldName);
      if (field && (field.type === "datetime" || field.type === "date")) {
        if (fromDate) {
          countWhereConditions.push(`"${dateFieldName}" >= $${countParamIndex++}`);
          countParams.push(fromDate);
        }
        if (toDate) {
          countWhereConditions.push(`"${dateFieldName}" <= $${countParamIndex++}`);
          countParams.push(toDate);
        }
      }
    }
    Object.entries(customFilters).forEach(([key, values]) => {
      const field = entityConfig.fields.find((f) => f.name === key);
      if (field && values.length > 0) {
        const columnName = `"${key}"`;
        if (field.type === "relation-multi" || key === "socialPlatformId") {
          const orConditions = values.map(() => {
            const condition = `${columnName}::jsonb @> $${countParamIndex++}::jsonb`;
            return condition;
          });
          values.forEach((value) => {
            countParams.push(JSON.stringify([value]));
          });
          countWhereConditions.push(`(${orConditions.join(" OR ")})`);
        } else {
          const orConditions = values.map(() => {
            const condition = `${columnName} = $${countParamIndex++}`;
            return condition;
          });
          values.forEach((value) => {
            countParams.push(value);
          });
          countWhereConditions.push(`(${orConditions.join(" OR ")})`);
        }
      }
    });
    if (taxonomyFilter == null ? void 0 : taxonomyFilter.taxonomyId) {
      countWhereConditions.push(`EXISTS (
        SELECT 1 FROM entity_taxonomy_relations etr
        WHERE etr."entityId" = id::text
          AND etr."entityType" = '${entityConfig.slug}'
          AND etr."taxonomyId" = $${countParamIndex++}
      )`);
      countParams.push(taxonomyFilter.taxonomyId);
    }
    const countWhereClause = countWhereConditions.length > 0 ? `WHERE ${countWhereConditions.join(" AND ")}` : "";
    totalResult = await queryWithRLS(
      `SELECT COUNT(*) as count FROM "${tableName}" ${countWhereClause}`,
      countParams,
      userId
    );
    const total = ((_i = totalResult[0]) == null ? void 0 : _i.count) || 0;
    const paginationMeta = createPaginationMeta(pagination.page, pagination.limit, total);
    let dataWithMeta = data;
    if (metaParams.includeMetadata && userId) {
      dataWithMeta = await includeEntityMetadata(
        resolution.entityName,
        data,
        metaParams,
        userId
      );
    }
    const childParams = parseChildParams(request);
    let dataWithChild = dataWithMeta;
    if (childParams.includeChildren && userId) {
      dataWithChild = await includeEntityChildren(
        resolution.entityName,
        dataWithMeta,
        childParams,
        userId,
        resolution.entityConfig
      );
    }
    let dataWithTaxonomies = dataWithChild;
    if ((_j = entityConfig.taxonomies) == null ? void 0 : _j.enabled) {
      dataWithTaxonomies = await includeTaxonomiesInData(
        entityConfig,
        dataWithChild,
        userId
      );
    }
    const response = createApiResponse(dataWithTaxonomies, paginationMeta);
    return addCorsHeaders(response);
  } catch (error) {
    console.error("Error in generic list handler:", error);
    const response = createApiError("Internal server error", 500);
    return addCorsHeaders(response);
  }
}
async function handleGenericCreate(request) {
  var _a, _b, _c, _d, _e, _f, _g;
  try {
    const resolution = await resolveEntityFromUrl(request.nextUrl.pathname);
    if (!resolution.isValidEntity || !resolution.entityConfig) {
      const response2 = createApiError("Entity not found", 404);
      return addCorsHeaders(response2);
    }
    if (!validateEntityOperation(resolution.entityConfig, "create")) {
      const response2 = createApiError("Create operation not supported for this entity", 405);
      return addCorsHeaders(response2);
    }
    const authResult = await authenticateRequest(request);
    if (!authResult.success) {
      return NextResponse.json(
        { success: false, error: "Authentication required", code: "AUTHENTICATION_FAILED" },
        { status: 401 }
      );
    }
    if (authResult.rateLimitResponse) {
      return authResult.rateLimitResponse;
    }
    if (!hasRequiredScope(authResult, `${resolution.entityConfig.slug}:write`)) {
      const response2 = createApiError("Insufficient permissions", 403);
      return addCorsHeaders(response2);
    }
    let body;
    try {
      body = await request.json();
    } catch {
      const response2 = createApiError("Invalid JSON body", 400);
      return addCorsHeaders(response2);
    }
    const { metas, ...entityData } = body;
    const rawUserId = entityData.userId;
    const entityConfig = resolution.entityConfig;
    const tableName = getTableName(entityConfig);
    const schemas = generateEntitySchemas(entityConfig);
    const validation = schemas.create.safeParse(entityData);
    if (!validation.success) {
      console.error(`[${entityConfig.slug}] Validation failed:`, {
        entityData,
        errors: validation.error.issues
      });
      const response2 = createApiError("Validation error", 400, validation.error.issues, "VALIDATION_ERROR");
      return addCorsHeaders(response2);
    }
    const validatedData = validation.data;
    const idStrategy = ((_a = entityConfig.idStrategy) == null ? void 0 : _a.type) || "uuid";
    let insertFields;
    let placeholders;
    let values;
    let paramCount;
    const isSharedEntity = ((_b = entityConfig.access) == null ? void 0 : _b.shared) === true;
    const userIdToUse = isSharedEntity && rawUserId ? rawUserId : authResult.user.id;
    const teamValidation = await validateTeamContextWithBypass(request, authResult, authResult.user.id);
    if (!teamValidation.valid) {
      return teamValidation.error;
    }
    const teamId = teamValidation.teamId;
    if (!teamId) {
      const response2 = createApiError("Team context required for create operations. Include x-team-id header.", 400, void 0, "TEAM_CONTEXT_REQUIRED");
      return addCorsHeaders(response2);
    }
    if (idStrategy === "serial") {
      insertFields = ['"userId"', '"teamId"'];
      placeholders = ["$1", "$2"];
      values = [userIdToUse, teamId];
      paramCount = 3;
    } else {
      const newEntityId = globalThis.crypto.randomUUID();
      insertFields = ["id", '"userId"', '"teamId"'];
      placeholders = ["$1", "$2", "$3"];
      values = [newEntityId, userIdToUse, teamId];
      paramCount = 4;
    }
    const builderRequest = isBuilderRequest(request);
    const entityHasBuilder = ((_c = entityConfig.builder) == null ? void 0 : _c.enabled) === true;
    if (builderRequest && entityHasBuilder && "blocks" in validatedData) {
      const blocksValue = validatedData.blocks;
      insertFields.push('"blocks"');
      placeholders.push(`$${paramCount++}::jsonb`);
      values.push(JSON.stringify(blocksValue));
      delete validatedData.blocks;
    }
    Object.entries(validatedData).forEach(([key, value]) => {
      var _a2, _b2;
      if (key === "userId" || key === "teamId") return;
      const field = entityConfig.fields.find((f) => f.name === key);
      if (field && !((_a2 = field.api) == null ? void 0 : _a2.readOnly) && field.display.showInForm !== false) {
        const columnName = `"${key}"`;
        insertFields.push(columnName);
        if (field.type === "relation") {
          let relationId = null;
          if (Array.isArray(value) && value.length > 0) {
            const firstItem = value[0];
            relationId = typeof firstItem === "object" && firstItem && "id" in firstItem ? firstItem.id : firstItem;
          } else if (typeof value === "object" && value && "id" in value) {
            relationId = value.id;
          } else if (typeof value === "string") {
            relationId = value;
          }
          if (typeof relationId === "string" && relationId.trim() === "") {
            relationId = null;
          }
          placeholders.push(`$${paramCount++}`);
          values.push(relationId);
        } else if (field.type === "relation-multi") {
          placeholders.push(`$${paramCount++}::jsonb`);
          values.push(value);
        } else if (field.type === "tags") {
          placeholders.push(`$${paramCount++}::jsonb`);
          values.push(JSON.stringify(Array.isArray(value) ? value : []));
        } else if ((field.type === "multiselect" || field.type === "user") && value === null) {
          placeholders.push(`$${paramCount++}`);
          values.push(null);
        } else if (field.type === "user") {
          placeholders.push(`$${paramCount++}`);
          if (Array.isArray(value) && value.length > 0) {
            const userId = (_b2 = value[0]) == null ? void 0 : _b2.id;
            values.push(userId ? String(userId) : null);
          } else if (typeof value === "string") {
            values.push(value);
          } else {
            values.push(null);
          }
        } else if (field.type === "multiselect" || Array.isArray(value) || typeof value === "object" && value !== null) {
          placeholders.push(`$${paramCount++}::jsonb`);
          values.push(JSON.stringify(value));
        } else {
          placeholders.push(`$${paramCount++}`);
          values.push(value);
        }
      }
    });
    const insertQuery = `
      INSERT INTO "${tableName}" (${insertFields.join(", ")})
      VALUES (${placeholders.join(", ")}) RETURNING *
    `;
    const insertResult = await mutateWithRLS(insertQuery, values, authResult.user.id);
    const createdEntityId = String((_d = insertResult.rows[0]) == null ? void 0 : _d.id);
    const systemFields = ["id", "userId", "createdAt", "updatedAt"];
    if ((_e = entityConfig.builder) == null ? void 0 : _e.enabled) {
      systemFields.push("blocks");
    }
    const configFields = entityConfig.fields.map((field) => {
      const columnName = /[A-Z]/.test(field.name) ? `"${field.name}"` : field.name;
      return `t.${columnName}`;
    });
    const systemFieldsFormatted = systemFields.map((fieldName) => {
      const columnName = /[A-Z]/.test(fieldName) ? `"${fieldName}"` : fieldName;
      return `t.${columnName}`;
    });
    const fields = [...systemFieldsFormatted, ...configFields].join(", ");
    const selectQuery = `
      SELECT ${fields}
      FROM "${tableName}" t
      WHERE t.id = $1
    `;
    const createdItems = await queryWithRLS(selectQuery, [createdEntityId], authResult.user.id);
    const createdItem = createdItems[0];
    if ((_f = entityConfig.taxonomies) == null ? void 0 : _f.enabled) {
      await processTaxonomyRelations(entityConfig, createdEntityId, body, authResult.user.id, false);
    }
    const metadataWasProvided = metas && typeof metas === "object" && Object.keys(metas).length > 0;
    if (metadataWasProvided) {
      await processEntityMetadata(
        resolution.entityName,
        createdEntityId,
        metas,
        authResult.user.id
      );
    }
    let responseItem = createdItem;
    if ((_g = entityConfig.taxonomies) == null ? void 0 : _g.enabled) {
      const itemsWithTaxonomies = await includeTaxonomiesInData(
        entityConfig,
        [createdItem],
        authResult.user.id
      );
      responseItem = itemsWithTaxonomies[0] || createdItem;
    }
    const responseData = await handleEntityMetadataInResponse(
      resolution.entityName,
      responseItem,
      metadataWasProvided,
      authResult.user.id
    );
    try {
      await afterEntityCreate(entityConfig.slug, responseItem, authResult.user.id);
    } catch (hookError) {
      console.error(`[generic-handler] Error in afterEntityCreate hook for ${entityConfig.slug}:`, hookError);
    }
    const response = createApiResponse(responseData, { created: true }, 201);
    return addCorsHeaders(response);
  } catch (error) {
    console.error("Error in generic create handler:", error);
    const response = createApiError("Internal server error", 500);
    return addCorsHeaders(response);
  }
}
async function handleGenericRead(request, { params }) {
  var _a, _b, _c, _d;
  try {
    const { id } = await params;
    const resolution = await resolveEntityFromUrl(request.nextUrl.pathname);
    if (!resolution.isValidEntity || !resolution.entityConfig) {
      const response2 = createApiError("Entity not found", 404);
      return addCorsHeaders(response2);
    }
    if (!validateEntityOperation(resolution.entityConfig, "read")) {
      const response2 = createApiError("Read operation not supported for this entity", 405);
      return addCorsHeaders(response2);
    }
    const authResult = await authenticateRequest(request);
    let userId = null;
    let teamId = null;
    if (!authResult.success && ((_a = resolution.entityConfig.access) == null ? void 0 : _a.public)) {
      console.log(`[GenericHandler] Public access allowed for ${resolution.entityConfig.slug} read`);
    } else if (!authResult.success) {
      return NextResponse.json(
        { success: false, error: "Authentication required", code: "AUTHENTICATION_FAILED" },
        { status: 401 }
      );
    } else {
      if (authResult.rateLimitResponse) {
        return authResult.rateLimitResponse;
      }
      if (!hasRequiredScope(authResult, `${resolution.entityConfig.slug}:read`)) {
        const response2 = createApiError("Insufficient permissions", 403);
        return addCorsHeaders(response2);
      }
      userId = authResult.user.id;
      const teamValidation = await validateTeamContextWithBypass(request, authResult, userId);
      if (!teamValidation.valid) {
        return teamValidation.error;
      }
      teamId = teamValidation.teamId;
    }
    const entityConfig = resolution.entityConfig;
    const tableName = getTableName(entityConfig);
    const systemFields = ["id", "createdAt", "updatedAt"];
    if ((_b = entityConfig.builder) == null ? void 0 : _b.enabled) {
      systemFields.push("blocks");
    }
    const configFields = entityConfig.fields.map((field) => {
      const columnName = /[A-Z]/.test(field.name) ? `"${field.name}"` : field.name;
      return `t.${columnName}`;
    });
    const systemFieldsFormatted = systemFields.map((fieldName) => {
      const columnName = /[A-Z]/.test(fieldName) ? `"${fieldName}"` : fieldName;
      return `t.${columnName}`;
    });
    const fields = [...systemFieldsFormatted, ...configFields].join(", ");
    let query;
    let queryParams;
    let paramIndex = 1;
    query = `
      SELECT ${fields}
      FROM "${tableName}" t
      WHERE t.id = $${paramIndex++}
    `;
    queryParams = [id];
    if (teamId) {
      query += ` AND t."teamId" = $${paramIndex++}`;
      queryParams.push(teamId);
    }
    if (userId && !((_c = entityConfig.access) == null ? void 0 : _c.shared)) {
      query += ` AND t."userId" = $${paramIndex++}`;
      queryParams.push(userId);
    }
    const items = await queryWithRLS(query, queryParams, userId);
    if (!items[0]) {
      const response2 = createApiError("Item not found", 404);
      return addCorsHeaders(response2);
    }
    const item = items[0];
    const metaParams = parseMetaParams(request);
    let itemWithMeta = item;
    if (metaParams.includeMetadata && userId) {
      const itemsWithMeta = await includeEntityMetadata(
        resolution.entityName,
        [item],
        metaParams,
        userId
      );
      itemWithMeta = itemsWithMeta[0] || item;
    }
    const childParams = parseChildParams(request);
    let itemWithChild = itemWithMeta;
    if (childParams.includeChildren && userId) {
      const itemsWithChild = await includeEntityChildren(
        resolution.entityName,
        [itemWithMeta],
        childParams,
        userId,
        resolution.entityConfig
      );
      itemWithChild = itemsWithChild[0] || itemWithMeta;
    }
    let itemWithTaxonomies = itemWithChild;
    if ((_d = entityConfig.taxonomies) == null ? void 0 : _d.enabled) {
      const itemsWithTaxonomies = await includeTaxonomiesInData(
        entityConfig,
        [itemWithChild],
        userId
      );
      itemWithTaxonomies = itemsWithTaxonomies[0] || itemWithChild;
    }
    const response = createApiResponse(itemWithTaxonomies);
    return addCorsHeaders(response);
  } catch (error) {
    console.error("Error in generic read handler:", error);
    const response = createApiError("Internal server error", 500);
    return addCorsHeaders(response);
  }
}
async function handleGenericUpdate(request, { params }) {
  var _a, _b, _c, _d;
  try {
    const { id } = await params;
    const resolution = await resolveEntityFromUrl(request.nextUrl.pathname);
    if (!resolution.isValidEntity || !resolution.entityConfig) {
      const response2 = createApiError("Entity not found", 404);
      return addCorsHeaders(response2);
    }
    if (!validateEntityOperation(resolution.entityConfig, "update")) {
      const response2 = createApiError("Update operation not supported for this entity", 405);
      return addCorsHeaders(response2);
    }
    const authResult = await authenticateRequest(request);
    if (!authResult.success) {
      return NextResponse.json(
        { success: false, error: "Authentication required", code: "AUTHENTICATION_FAILED" },
        { status: 401 }
      );
    }
    if (authResult.rateLimitResponse) {
      return authResult.rateLimitResponse;
    }
    if (!hasRequiredScope(authResult, `${resolution.entityConfig.slug}:write`)) {
      const response2 = createApiError("Insufficient permissions", 403);
      return addCorsHeaders(response2);
    }
    const teamValidation = await validateTeamContextWithBypass(request, authResult, authResult.user.id);
    if (!teamValidation.valid) {
      return teamValidation.error;
    }
    const teamId = teamValidation.teamId;
    if (!teamId) {
      const response2 = createApiError("Team context required for update operations. Include x-team-id header.", 400, void 0, "TEAM_CONTEXT_REQUIRED");
      return addCorsHeaders(response2);
    }
    let body;
    try {
      body = await request.json();
    } catch {
      const response2 = createApiError("Invalid JSON body", 400);
      return addCorsHeaders(response2);
    }
    const { metas, ...entityData } = body;
    const entityConfig = resolution.entityConfig;
    const tableName = getTableName(entityConfig);
    const schemas = generateEntitySchemas(entityConfig);
    const validation = schemas.update.safeParse(entityData);
    if (!validation.success) {
      console.log(`[${entityConfig.slug}] Validation failed:`, {
        entityData,
        errors: validation.error.issues
      });
      const response2 = createApiError("Validation error", 400, validation.error.issues, "VALIDATION_ERROR");
      return addCorsHeaders(response2);
    }
    const validatedData = validation.data;
    const updates = [];
    const values = [];
    let paramCount = 1;
    const builderRequest = isBuilderRequest(request);
    const entityHasBuilder = ((_a = entityConfig.builder) == null ? void 0 : _a.enabled) === true;
    if (builderRequest && entityHasBuilder && "blocks" in entityData) {
      updates.push(`"blocks" = $${paramCount++}::jsonb`);
      values.push(JSON.stringify(entityData.blocks));
    }
    const originalKeys = Object.keys(entityData);
    const fieldsToUpdate = Object.entries(validatedData).filter(([key]) => originalKeys.includes(key));
    fieldsToUpdate.forEach(([key, value]) => {
      var _a2, _b2;
      if (key === "blocks") return;
      const field = entityConfig.fields.find((f) => f.name === key);
      if (field && !((_a2 = field.api) == null ? void 0 : _a2.readOnly) && field.display.showInForm !== false) {
        const columnName = `"${key}"`;
        if (field.type === "relation") {
          let relationId = null;
          if (Array.isArray(value) && value.length > 0) {
            const firstItem = value[0];
            relationId = typeof firstItem === "object" && firstItem && "id" in firstItem ? firstItem.id : firstItem;
          } else if (typeof value === "object" && value && "id" in value) {
            relationId = value.id;
          } else if (typeof value === "string") {
            relationId = value;
          }
          if (typeof relationId === "string" && relationId.trim() === "") {
            relationId = null;
          }
          updates.push(`${columnName} = $${paramCount++}`);
          values.push(relationId);
        } else if (field.type === "relation-multi") {
          updates.push(`${columnName} = $${paramCount++}::jsonb`);
          values.push(value);
        } else if (field.type === "tags") {
          updates.push(`${columnName} = $${paramCount++}::jsonb`);
          values.push(JSON.stringify(Array.isArray(value) ? value : []));
        } else if ((field.type === "multiselect" || field.type === "user") && value === null) {
          updates.push(`${columnName} = $${paramCount++}`);
          values.push(null);
        } else if (field.type === "user") {
          updates.push(`${columnName} = $${paramCount++}`);
          if (Array.isArray(value) && value.length > 0) {
            const userId = (_b2 = value[0]) == null ? void 0 : _b2.id;
            values.push(userId ? String(userId) : null);
          } else if (typeof value === "string") {
            values.push(value);
          } else {
            values.push(null);
          }
        } else if (field.type === "multiselect" || Array.isArray(value) || typeof value === "object" && value !== null) {
          updates.push(`${columnName} = $${paramCount++}::jsonb`);
          values.push(JSON.stringify(value));
        } else {
          updates.push(`${columnName} = $${paramCount++}`);
          values.push(value);
        }
      }
    });
    const metadataWasProvided = metas && typeof metas === "object" && Object.keys(metas).length > 0;
    if (updates.length === 0 && !metadataWasProvided) {
      const response2 = createApiError("No fields to update", 400);
      return addCorsHeaders(response2);
    }
    if (updates.length > 0) {
      updates.push(`"updatedAt" = CURRENT_TIMESTAMP`);
    }
    let updatedItem;
    if (updates.length > 0) {
      const whereConditions = [`id = $${paramCount++}`];
      values.push(id);
      if (teamId) {
        whereConditions.push(`"teamId" = $${paramCount++}`);
        values.push(teamId);
      }
      if (!((_b = entityConfig.access) == null ? void 0 : _b.shared)) {
        whereConditions.push(`"userId" = $${paramCount++}`);
        values.push(authResult.user.id);
      }
      const updateQuery = `
        UPDATE "${tableName}"
        SET ${updates.join(", ")}
        WHERE ${whereConditions.join(" AND ")}
        RETURNING *
      `;
      const result = await mutateWithRLS(updateQuery, values, authResult.user.id);
      if (!result.rows || result.rows.length === 0) {
        const response2 = createApiError("Item not found", 404);
        return addCorsHeaders(response2);
      }
      updatedItem = result.rows[0];
    } else {
      let selectQuery = `SELECT * FROM "${tableName}" WHERE id = $1`;
      const selectValues = [id];
      if (teamId) {
        selectQuery += ` AND "teamId" = $2`;
        selectValues.push(teamId);
      }
      const result = await queryWithRLS(selectQuery, selectValues, authResult.user.id);
      if (!result || result.length === 0) {
        const response2 = createApiError("Item not found", 404);
        return addCorsHeaders(response2);
      }
      updatedItem = result[0];
    }
    if ((_c = entityConfig.taxonomies) == null ? void 0 : _c.enabled) {
      await processTaxonomyRelations(entityConfig, id, body, authResult.user.id, true);
    }
    if (metadataWasProvided) {
      await processEntityMetadata(
        resolution.entityName,
        id,
        metas,
        authResult.user.id
      );
    }
    let responseItem = updatedItem;
    if ((_d = entityConfig.taxonomies) == null ? void 0 : _d.enabled) {
      const itemsWithTaxonomies = await includeTaxonomiesInData(
        entityConfig,
        [updatedItem],
        authResult.user.id
      );
      responseItem = itemsWithTaxonomies[0] || updatedItem;
    }
    const responseData = await handleEntityMetadataInResponse(
      resolution.entityName,
      responseItem,
      metadataWasProvided,
      authResult.user.id
    );
    try {
      await afterEntityUpdate(entityConfig.slug, id, responseItem, entityData, authResult.user.id);
    } catch (hookError) {
      console.error(`[generic-handler] Error in afterEntityUpdate hook for ${entityConfig.slug}:`, hookError);
    }
    const response = createApiResponse(responseData);
    return addCorsHeaders(response);
  } catch (error) {
    console.error("Error in generic update handler:", error);
    const response = createApiError("Internal server error", 500);
    return addCorsHeaders(response);
  }
}
async function handleGenericDelete(request, { params }) {
  var _a;
  try {
    const { id } = await params;
    const resolution = await resolveEntityFromUrl(request.nextUrl.pathname);
    if (!resolution.isValidEntity || !resolution.entityConfig) {
      const response2 = createApiError("Entity not found", 404);
      return addCorsHeaders(response2);
    }
    if (!validateEntityOperation(resolution.entityConfig, "delete")) {
      const response2 = createApiError("Delete operation not supported for this entity", 405);
      return addCorsHeaders(response2);
    }
    const authResult = await authenticateRequest(request);
    if (!authResult.success) {
      return NextResponse.json(
        { success: false, error: "Authentication required", code: "AUTHENTICATION_FAILED" },
        { status: 401 }
      );
    }
    if (authResult.rateLimitResponse) {
      return authResult.rateLimitResponse;
    }
    if (!hasRequiredScope(authResult, `${resolution.entityConfig.slug}:write`)) {
      const response2 = createApiError("Insufficient permissions", 403);
      return addCorsHeaders(response2);
    }
    const teamValidation = await validateTeamContextWithBypass(request, authResult, authResult.user.id);
    if (!teamValidation.valid) {
      return teamValidation.error;
    }
    const teamId = teamValidation.teamId;
    if (!teamId) {
      const response2 = createApiError("Team context required for delete operations. Include x-team-id header.", 400, void 0, "TEAM_CONTEXT_REQUIRED");
      return addCorsHeaders(response2);
    }
    const entityConfig = resolution.entityConfig;
    const tableName = getTableName(entityConfig);
    const whereConditions = ["id = $1"];
    const deleteParams = [id];
    let paramIndex = 2;
    if (teamId) {
      whereConditions.push(`"teamId" = $${paramIndex++}`);
      deleteParams.push(teamId);
    }
    if (!((_a = entityConfig.access) == null ? void 0 : _a.shared)) {
      whereConditions.push(`"userId" = $${paramIndex++}`);
      deleteParams.push(authResult.user.id);
    }
    const deleteQuery = `
      DELETE FROM "${tableName}"
      WHERE ${whereConditions.join(" AND ")}
      RETURNING id
    `;
    const result = await mutateWithRLS(deleteQuery, deleteParams, authResult.user.id);
    if (!result.rows || result.rows.length === 0) {
      const response2 = createApiError("Item not found", 404);
      return addCorsHeaders(response2);
    }
    try {
      await afterEntityDelete(entityConfig.slug, id, authResult.user.id);
    } catch (hookError) {
      console.error(`[generic-handler] Error in afterEntityDelete hook for ${entityConfig.slug}:`, hookError);
    }
    const response = createApiResponse({ success: true, id });
    return addCorsHeaders(response);
  } catch (error) {
    console.error("Error in generic delete handler:", error);
    const response = createApiError("Internal server error", 500);
    return addCorsHeaders(response);
  }
}
async function handleGenericOptions() {
  return handleCorsPreflightRequest();
}
async function handleDistinctJsonbField(entityConfig, fieldName, url, userId) {
  var _a;
  const tableName = getTableName(entityConfig);
  const parentId = url.searchParams.get("parentId");
  const limit = parseInt(url.searchParams.get("limit") || "50");
  let query;
  const queryParams = [];
  let paramIndex = 1;
  query = `
    SELECT DISTINCT
      elem.value as value,
      elem.value as label,
      '${entityConfig.slug}' as "entityType"
    FROM (
      SELECT jsonb_array_elements_text("${fieldName}") as value
      FROM "${tableName}"
      WHERE "${fieldName}" IS NOT NULL
      AND jsonb_array_length("${fieldName}") > 0
  `;
  if (parentId) {
    query += ` AND "parentId" = $${paramIndex++}`;
    queryParams.push(parentId);
  }
  if (userId && !((_a = entityConfig.access) == null ? void 0 : _a.shared)) {
    query += ` AND "userId" = $${paramIndex++}`;
    queryParams.push(userId);
  }
  query += `) as elem ORDER BY elem.value ASC LIMIT $${paramIndex++}`;
  queryParams.push(limit);
  const results = await queryWithRLS(query, queryParams, userId);
  return NextResponse.json({
    success: true,
    data: results,
    meta: {
      entityType: entityConfig.slug,
      field: fieldName,
      total: results.length,
      timestamp: (/* @__PURE__ */ new Date()).toISOString(),
      mode: "distinct-jsonb"
    }
  });
}
export {
  handleGenericCreate,
  handleGenericDelete,
  handleGenericList,
  handleGenericOptions,
  handleGenericRead,
  handleGenericUpdate
};
