import { NextResponse } from "next/server";
import { z } from "zod";
import { getEntityConfig } from "./registry.js";
import { executeEntityHooks } from "./hooks.js";
import { auth } from "../auth.js";
function generateEntityAPI(entityName, options = {}) {
  const entityConfig = getEntityConfig(entityName);
  if (!entityConfig) {
    throw new Error(`Entity configuration not found: ${entityName}`);
  }
  const {
    enableAuth = true,
    enableChildEntities = true,
    customValidation = {},
    customMiddleware = []
  } = options;
  return {
    GET: createGETHandler(entityConfig, { enableAuth, enableChildEntities, customMiddleware }),
    POST: createPOSTHandler(entityConfig, { enableAuth, enableChildEntities, customValidation, customMiddleware }),
    PATCH: createPATCHHandler(entityConfig, { enableAuth, enableChildEntities, customValidation, customMiddleware }),
    DELETE: createDELETEHandler(entityConfig, { enableAuth, customMiddleware })
  };
}
function createGETHandler(entityConfig, options) {
  return async (request, context) => {
    var _a;
    try {
      let user = null;
      if (options.enableAuth) {
        const session = await auth.api.getSession({ headers: request.headers });
        if (!session) {
          return NextResponse.json({ error: "Authentication required" }, { status: 401 });
        }
        user = session.user;
      }
      for (const middleware of options.customMiddleware) {
        await middleware.execute(request, {
          entityName: entityConfig.slug,
          entityConfig,
          user,
          action: "read"
        });
      }
      const { searchParams } = new URL(request.url);
      const id = (_a = context == null ? void 0 : context.params) == null ? void 0 : _a.id;
      const hookContext = {
        entityName: entityConfig.slug,
        operation: "query",
        user: user ? { id: user.id, role: user.role } : { id: "", role: "member" },
        data: { id, searchParams: Object.fromEntries(searchParams) }
      };
      await executeEntityHooks(entityConfig.slug, "beforeQuery", hookContext);
      let result;
      if (id) {
        result = await handleSingleItemGet(entityConfig, id, searchParams, options.enableChildEntities);
      } else {
        result = await handleListGet(entityConfig, searchParams, options.enableChildEntities);
      }
      await executeEntityHooks(entityConfig.slug, "afterQuery", { ...hookContext, data: result });
      return NextResponse.json(result);
    } catch (error) {
      console.error(`GET ${entityConfig.slug} error:`, error);
      return NextResponse.json(
        { error: "Internal server error" },
        { status: 500 }
      );
    }
  };
}
async function handleSingleItemGet(entityConfig, id, searchParams, enableChildEntities) {
  throw new Error(`Generic single item retrieval not implemented for ${entityConfig.slug}. Use specific API endpoint: /api/v1/${entityConfig.slug}/${id}`);
}
async function handleListGet(entityConfig, searchParams, enableChildEntities) {
  throw new Error(`Generic list retrieval not implemented for ${entityConfig.slug}. Use specific API endpoint: /api/v1/${entityConfig.slug}`);
}
function createPOSTHandler(entityConfig, options) {
  return async (request) => {
    try {
      let user = null;
      if (options.enableAuth) {
        const session = await auth.api.getSession({ headers: request.headers });
        if (!session) {
          return NextResponse.json({ error: "Authentication required" }, { status: 401 });
        }
        user = session.user;
      }
      const body = await request.json();
      const schema = generateCreateSchema(entityConfig, options.customValidation);
      const validation = schema.safeParse(body);
      if (!validation.success) {
        return NextResponse.json({
          error: "Validation failed",
          validationErrors: validation.error.flatten().fieldErrors
        }, { status: 400 });
      }
      const validatedData = validation.data;
      for (const middleware of options.customMiddleware) {
        await middleware.execute(request, {
          entityName: entityConfig.slug,
          entityConfig,
          user,
          action: "create",
          data: validatedData
        });
      }
      const hookContext = {
        entityName: entityConfig.slug,
        operation: "create",
        user: user ? { id: user.id, role: user.role } : { id: "", role: "member" },
        data: validatedData
      };
      await executeEntityHooks(entityConfig.slug, "beforeCreate", hookContext);
      throw new Error(`Generic entity creation not implemented for ${entityConfig.slug}. Use specific API endpoint.`);
    } catch (error) {
      console.error(`POST ${entityConfig.slug} error:`, error);
      return NextResponse.json(
        { error: "Internal server error" },
        { status: 500 }
      );
    }
  };
}
function createPATCHHandler(entityConfig, options) {
  return async (request, context) => {
    var _a;
    try {
      let user = null;
      if (options.enableAuth) {
        const session = await auth.api.getSession({ headers: request.headers });
        if (!session) {
          return NextResponse.json({ error: "Authentication required" }, { status: 401 });
        }
        user = session.user;
      }
      const id = (_a = context == null ? void 0 : context.params) == null ? void 0 : _a.id;
      if (!id) {
        return NextResponse.json({ error: "ID required" }, { status: 400 });
      }
      const body = await request.json();
      const schema = generateUpdateSchema(entityConfig, options.customValidation);
      const validation = schema.safeParse(body);
      if (!validation.success) {
        return NextResponse.json({
          error: "Validation failed",
          validationErrors: validation.error.flatten().fieldErrors
        }, { status: 400 });
      }
      const validatedData = validation.data;
      const existingItem = await mockDatabaseGet();
      if (!existingItem) {
        return NextResponse.json(
          { error: `${entityConfig.names.singular} not found` },
          { status: 404 }
        );
      }
      for (const middleware of options.customMiddleware) {
        await middleware.execute(request, {
          entityName: entityConfig.slug,
          entityConfig,
          user,
          action: "update",
          data: { ...validatedData, id, existing: existingItem }
        });
      }
      const hookContext = {
        entityName: entityConfig.slug,
        operation: "update",
        user: user ? { id: user.id, role: user.role } : { id: "", role: "member" },
        data: { ...validatedData, id, existing: existingItem }
      };
      await executeEntityHooks(entityConfig.slug, "beforeUpdate", hookContext);
      const updatedItem = await mockDatabaseUpdate();
      let childrenResult = {};
      if (options.enableChildEntities && validatedData.children && entityConfig.childEntities) {
        childrenResult = await updateChildEntities(
          entityConfig,
          id,
          validatedData.children,
          user
        );
      }
      await executeEntityHooks(entityConfig.slug, "afterUpdate", {
        ...hookContext,
        data: { ...updatedItem, children: childrenResult }
      });
      const result = {
        data: updatedItem
      };
      if (Object.keys(childrenResult).length > 0) {
        result.children = childrenResult;
      }
      return NextResponse.json(result);
    } catch (error) {
      console.error(`PATCH ${entityConfig.slug} error:`, error);
      return NextResponse.json(
        { error: "Internal server error" },
        { status: 500 }
      );
    }
  };
}
function createDELETEHandler(entityConfig, options) {
  return async (request, context) => {
    var _a;
    try {
      let user = null;
      if (options.enableAuth) {
        const session = await auth.api.getSession({ headers: request.headers });
        if (!session) {
          return NextResponse.json({ error: "Authentication required" }, { status: 401 });
        }
        user = session.user;
      }
      const id = (_a = context == null ? void 0 : context.params) == null ? void 0 : _a.id;
      if (!id) {
        return NextResponse.json({ error: "ID required" }, { status: 400 });
      }
      const existingItem = await mockDatabaseGet();
      if (!existingItem) {
        return NextResponse.json(
          { error: `${entityConfig.names.singular} not found` },
          { status: 404 }
        );
      }
      for (const middleware of options.customMiddleware) {
        await middleware.execute(request, {
          entityName: entityConfig.slug,
          entityConfig,
          user,
          action: "delete",
          data: { id, existing: existingItem }
        });
      }
      const hookContext = {
        entityName: entityConfig.slug,
        operation: "delete",
        user: user ? { id: user.id, role: user.role } : { id: "", role: "member" },
        data: { id, existing: existingItem }
      };
      await executeEntityHooks(entityConfig.slug, "beforeDelete", hookContext);
      if (entityConfig.childEntities) {
        await deleteAllChildEntities(entityConfig, id);
      }
      await mockDatabaseDelete();
      await executeEntityHooks(entityConfig.slug, "afterDelete", hookContext);
      return NextResponse.json({ success: true });
    } catch (error) {
      console.error(`DELETE ${entityConfig.slug} error:`, error);
      return NextResponse.json(
        { error: "Internal server error" },
        { status: 500 }
      );
    }
  };
}
function generateCreateSchema(entityConfig, customValidation = {}) {
  const fields = {};
  entityConfig.fields.forEach((field) => {
    if (field.api.readOnly) return;
    let zodField;
    if (customValidation[field.name]) {
      zodField = customValidation[field.name];
    } else {
      switch (field.type) {
        case "text":
        case "textarea":
          zodField = z.string();
          break;
        case "email":
          zodField = z.string().email();
          break;
        case "url":
          zodField = z.string().url();
          break;
        case "number":
          zodField = z.number();
          break;
        case "boolean":
          zodField = z.boolean();
          break;
        case "date":
        case "datetime":
          zodField = z.string().datetime();
          break;
        case "select":
          if (field.options && field.options.length > 0) {
            const values = field.options.map((opt) => opt.value);
            zodField = z.enum(values);
          } else {
            zodField = z.string();
          }
          break;
        case "multiselect":
          zodField = z.array(z.string());
          break;
        case "json":
          zodField = z.unknown();
          break;
        default:
          zodField = z.unknown();
      }
    }
    if (!field.required) {
      zodField = zodField.optional();
    }
    fields[field.name] = zodField;
  });
  if (entityConfig.childEntities) {
    const childrenFields = {};
    Object.entries(entityConfig.childEntities).forEach(([childName, childConfig]) => {
      childrenFields[childName] = z.array(generateChildEntitySchema(childConfig)).optional();
    });
    if (Object.keys(childrenFields).length > 0) {
      fields.children = z.object(childrenFields).optional();
    }
  }
  return z.object(fields);
}
function generateUpdateSchema(entityConfig, customValidation = {}) {
  const createSchema = generateCreateSchema(entityConfig, customValidation);
  return createSchema.partial();
}
function generateChildEntitySchema(childConfig) {
  const fields = {};
  childConfig.fields.forEach((field) => {
    let zodField;
    switch (field.type) {
      case "text":
      case "textarea":
        zodField = z.string();
        break;
      case "email":
        zodField = z.string().email();
        break;
      case "url":
        zodField = z.string().url();
        break;
      case "number":
        zodField = z.number();
        break;
      case "boolean":
        zodField = z.boolean();
        break;
      case "date":
      case "datetime":
        zodField = z.string().datetime();
        break;
      case "json":
        zodField = z.unknown();
        break;
      default:
        zodField = z.unknown();
    }
    if (!field.required) {
      zodField = zodField.optional();
    }
    fields[field.name] = zodField;
  });
  return z.object(fields);
}
async function getChildEntitiesForItem(entityConfig, parentId, childNames) {
  const result = {};
  if (!entityConfig.childEntities) return result;
  for (const childName of childNames) {
    if (entityConfig.childEntities[childName]) {
      result[childName] = await mockGetChildEntities();
    }
  }
  return result;
}
async function createChildEntities(entityConfig, parentId, childrenData, user) {
  const result = {};
  if (!entityConfig.childEntities) return result;
  for (const [childName, childItems] of Object.entries(childrenData)) {
    if (entityConfig.childEntities[childName] && Array.isArray(childItems)) {
      result[childName] = [];
      for (const childData of childItems) {
        const createdChild = await mockCreateChildEntity();
        result[childName].push(createdChild);
      }
    }
  }
  return result;
}
async function updateChildEntities(entityConfig, parentId, childrenData, user) {
  const result = {};
  if (!entityConfig.childEntities) return result;
  for (const [childName, childItems] of Object.entries(childrenData)) {
    if (entityConfig.childEntities[childName] && Array.isArray(childItems)) {
      result[childName] = [];
      for (const childData of childItems) {
        const childDataRecord = childData;
        let updatedChild;
        if (childDataRecord.id) {
          updatedChild = await mockUpdateChildEntity();
        } else {
          updatedChild = await mockCreateChildEntity();
        }
        result[childName].push(updatedChild);
      }
    }
  }
  return result;
}
async function deleteAllChildEntities(entityConfig, parentId) {
  if (!entityConfig.childEntities) return;
  for (const childName of Object.keys(entityConfig.childEntities)) {
    await mockDeleteAllChildEntities();
  }
}
async function mockDatabaseGet() {
  throw new Error("mockDatabaseGet removed - use specific entity endpoints");
}
async function mockDatabaseList() {
  throw new Error("mockDatabaseList removed - use specific entity endpoints");
}
async function mockDatabaseCreate() {
  throw new Error("mockDatabaseCreate removed - use specific entity endpoints");
}
async function mockDatabaseUpdate() {
  throw new Error("mockDatabaseUpdate removed - use specific entity endpoints");
}
async function mockDatabaseDelete() {
  throw new Error("mockDatabaseDelete removed - use specific entity endpoints");
}
async function mockGetChildEntities() {
  throw new Error("mockGetChildEntities removed - use specific entity endpoints");
}
async function mockCreateChildEntity() {
  throw new Error("mockCreateChildEntity removed - use specific entity endpoints");
}
async function mockUpdateChildEntity() {
  throw new Error("mockUpdateChildEntity removed - use specific entity endpoints");
}
async function mockDeleteAllChildEntities() {
  throw new Error("mockDeleteAllChildEntities removed - use specific entity endpoints");
}
export {
  generateEntityAPI
};
