function generateEntityMigration(entityConfig, options = {}) {
  const {
    includeRLS = true,
    includeIndexes = true,
    includeChildEntities = true,
    includeConstraints = true,
    includeComments = true,
    softDelete = false,
    // Default to hard delete unless specified
    timestamps = true
    // Default to including timestamps (created_at, updated_at)
  } = options;
  const tableDef = generateTableDefinition(entityConfig, {
    softDelete,
    timestamps,
    includeIndexes,
    includeConstraints,
    includeRLS,
    includeComments
  });
  let upSQL = generateCreateTableSQL(tableDef);
  let downSQL = generateDropTableSQL(tableDef.tableName);
  if (includeChildEntities && entityConfig.childEntities) {
    const childMigrations = generateChildEntityMigrations(entityConfig, options);
    childMigrations.forEach((childMigration) => {
      upSQL += "\n\n" + childMigration.up;
      downSQL = childMigration.down + "\n\n" + downSQL;
    });
  }
  const timestamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[-:]/g, "").split(".")[0];
  const filename = `${timestamp}_create_${entityConfig.slug}_entity.sql`;
  return {
    up: upSQL,
    down: downSQL,
    filename,
    description: `Create ${entityConfig.names.singular} entity with related tables and policies`,
    dependencies: []
  };
}
function generateTableDefinition(entityConfig, options) {
  const tableName = entityConfig.tableName || entityConfig.slug;
  const primaryKey = "id";
  const columns = [];
  columns.push({
    name: primaryKey,
    type: "UUID",
    nullable: false,
    primaryKey: true,
    defaultValue: "gen_random_uuid()",
    comment: options.includeComments ? `Primary key for ${entityConfig.names.singular}` : void 0
  });
  entityConfig.fields.forEach((field) => {
    if (field.name !== primaryKey) {
      const column = generateColumnFromField(field, options.includeComments);
      columns.push(column);
    }
  });
  if (options.timestamps) {
    columns.push({
      name: "created_at",
      type: "TIMESTAMPTZ",
      nullable: false,
      defaultValue: "CURRENT_TIMESTAMP",
      comment: options.includeComments ? "When the record was created" : void 0
    });
    columns.push({
      name: "updated_at",
      type: "TIMESTAMPTZ",
      nullable: false,
      defaultValue: "CURRENT_TIMESTAMP",
      comment: options.includeComments ? "When the record was last updated" : void 0
    });
  }
  if (options.softDelete) {
    columns.push({
      name: "deleted_at",
      type: "TIMESTAMPTZ",
      nullable: true,
      comment: options.includeComments ? "When the record was deleted (NULL if not deleted)" : void 0
    });
    columns.push({
      name: "deleted_by",
      type: "UUID",
      nullable: true,
      comment: options.includeComments ? "User who deleted the record" : void 0
    });
  }
  const hasUserField = entityConfig.fields.some((f) => f.name === "userId" || f.name === "user_id");
  if (hasUserField && !columns.some((c) => c.name === "user_id")) {
    columns.push({
      name: "user_id",
      type: "UUID",
      nullable: false,
      comment: options.includeComments ? "User who owns this record" : void 0
    });
  }
  const indexes = [];
  if (options.includeIndexes) {
    indexes.push(...generateIndexes(entityConfig, tableName, options.includeComments, options.softDelete));
  }
  const constraints = [];
  if (options.includeConstraints) {
    constraints.push(...generateConstraints(entityConfig, tableName, hasUserField, primaryKey));
  }
  const rlsPolicies = [];
  if (options.includeRLS) {
    rlsPolicies.push(...generateRLSPolicies(entityConfig, tableName, options.includeComments));
  }
  return {
    tableName,
    columns,
    indexes,
    constraints,
    rlsPolicies
  };
}
function generateColumnFromField(field, includeComments) {
  let sqlType;
  let defaultValue;
  switch (field.type) {
    case "text":
      sqlType = "VARCHAR(255)";
      break;
    case "textarea":
      sqlType = "TEXT";
      break;
    case "email":
      sqlType = "VARCHAR(255)";
      break;
    case "url":
      sqlType = "TEXT";
      break;
    case "number":
      sqlType = "DECIMAL";
      break;
    case "boolean":
      sqlType = "BOOLEAN";
      if (field.defaultValue !== void 0) {
        defaultValue = field.defaultValue ? "TRUE" : "FALSE";
      }
      break;
    case "date":
      sqlType = "DATE";
      break;
    case "datetime":
      sqlType = "TIMESTAMPTZ";
      break;
    case "select":
      if (field.options && field.options.length > 0) {
        const enumValues = field.options.map((opt) => `'${opt.value}'`).join(", ");
        sqlType = `VARCHAR(100) CHECK (${field.name} IN (${enumValues}))`;
      } else {
        sqlType = "VARCHAR(100)";
      }
      break;
    case "multiselect":
      sqlType = "TEXT[]";
      break;
    case "json":
      sqlType = "JSONB";
      break;
    default:
      sqlType = "TEXT";
  }
  return {
    name: field.name,
    type: sqlType,
    nullable: !field.required,
    defaultValue,
    unique: false,
    // Default to false for unique constraint
    comment: includeComments ? field.display.description || field.display.label : void 0
  };
}
function generateIndexes(entityConfig, tableName, includeComments, softDelete) {
  const indexes = [];
  entityConfig.fields.forEach((field) => {
    if (field.api.searchable && (field.type === "text" || field.type === "textarea")) {
      indexes.push({
        name: `idx_${tableName}_${field.name}_search`,
        columns: [field.name],
        method: "gin",
        comment: includeComments ? `GIN index for text search on ${field.name}` : void 0
      });
    }
    if (field.api.sortable && !indexes.some((idx) => idx.columns.includes(field.name))) {
      indexes.push({
        name: `idx_${tableName}_${field.name}`,
        columns: [field.name],
        comment: includeComments ? `Index for sorting on ${field.name}` : void 0
      });
    }
    if (field.name.endsWith("_id") || field.name.endsWith("Id")) {
      indexes.push({
        name: `idx_${tableName}_${field.name}`,
        columns: [field.name],
        comment: includeComments ? `Foreign key index on ${field.name}` : void 0
      });
    }
  });
  const userIdField = entityConfig.fields.find((f) => f.name === "userId" || f.name === "user_id");
  if (userIdField) {
    indexes.push({
      name: `idx_${tableName}_user_created`,
      columns: ["user_id", "created_at"],
      comment: includeComments ? "Composite index for user's items ordered by creation date" : void 0
    });
    if (softDelete) {
      indexes.push({
        name: `idx_${tableName}_user_active`,
        columns: ["user_id"],
        partial: "deleted_at IS NULL",
        comment: includeComments ? "Partial index for user's non-deleted items" : void 0
      });
    }
  }
  if (softDelete) {
    indexes.push({
      name: `idx_${tableName}_deleted_at`,
      columns: ["deleted_at"],
      comment: includeComments ? "Index for soft delete filtering" : void 0
    });
  }
  return indexes;
}
function generateConstraints(entityConfig, tableName, hasUserField, primaryKey = "id") {
  const constraints = [];
  constraints.push({
    name: `pk_${tableName}`,
    type: "PRIMARY KEY",
    definition: `(${primaryKey})`
  });
  if (hasUserField) {
    constraints.push({
      name: `fk_${tableName}_user`,
      type: "FOREIGN KEY",
      definition: '(user_id) REFERENCES "user"(id) ON DELETE CASCADE'
    });
  }
  return constraints;
}
function generateRLSPolicies(entityConfig, tableName, includeComments) {
  const policies = [];
  const hasUserField = entityConfig.fields.some((f) => f.name === "userId" || f.name === "user_id");
  policies.push({
    name: "enable_rls",
    action: "ALL",
    using: "TRUE",
    // This will be converted to ALTER TABLE statement
    comment: includeComments ? "Enable Row Level Security" : void 0
  });
  if (hasUserField) {
    policies.push({
      name: `${tableName}_owner_access`,
      action: "ALL",
      using: "auth.uid() = user_id",
      comment: includeComments ? "Users can access their own records" : void 0
    });
  }
  policies.push({
    name: `${tableName}_admin_access`,
    action: "ALL",
    role: "service_role",
    using: "TRUE",
    comment: includeComments ? "Service role has full access" : void 0
  });
  return policies;
}
function generateChildEntityMigrations(parentEntityConfig, options) {
  const migrations = [];
  if (!parentEntityConfig.childEntities) {
    return migrations;
  }
  Object.entries(parentEntityConfig.childEntities).forEach(([childName, childConfig]) => {
    const migration = generateChildEntityMigration(
      parentEntityConfig.slug,
      childName,
      childConfig,
      options
    );
    migrations.push(migration);
  });
  return migrations;
}
function generateChildEntityMigration(parentEntityName, childName, childConfig, options) {
  const tableName = childConfig.table;
  const columns = [];
  columns.push({
    name: "id",
    type: "UUID",
    nullable: false,
    primaryKey: true,
    defaultValue: "gen_random_uuid()"
  });
  columns.push({
    name: `${parentEntityName}_id`,
    type: "UUID",
    nullable: false,
    comment: options.includeComments ? `Reference to parent ${parentEntityName}` : void 0
  });
  childConfig.fields.forEach((field) => {
    const column = generateColumnFromField(field, options.includeComments || false);
    columns.push(column);
  });
  if (options.timestamps !== false) {
    columns.push({
      name: "created_at",
      type: "TIMESTAMPTZ",
      nullable: false,
      defaultValue: "CURRENT_TIMESTAMP"
    });
    columns.push({
      name: "updated_at",
      type: "TIMESTAMPTZ",
      nullable: false,
      defaultValue: "CURRENT_TIMESTAMP"
    });
  }
  if (options.softDelete !== false) {
    columns.push({
      name: "deleted_at",
      type: "TIMESTAMPTZ",
      nullable: true
    });
  }
  columns.push({
    name: "created_by",
    type: "UUID",
    nullable: true
  });
  const constraints = [
    {
      name: `pk_${tableName}`,
      type: "PRIMARY KEY",
      definition: "(id)"
    },
    {
      name: `fk_${tableName}_${parentEntityName}`,
      type: "FOREIGN KEY",
      definition: `(${parentEntityName}_id) REFERENCES "${parentEntityName}"(id) ON DELETE CASCADE`
    }
  ];
  const indexes = [
    {
      name: `idx_${tableName}_${parentEntityName}_id`,
      columns: [`${parentEntityName}_id`]
    }
  ];
  if (options.softDelete !== false) {
    indexes.push({
      name: `idx_${tableName}_deleted_at`,
      columns: ["deleted_at"]
    });
  }
  const tableDef = {
    tableName,
    columns,
    indexes,
    constraints,
    rlsPolicies: []
  };
  const upSQL = generateCreateTableSQL(tableDef);
  const downSQL = generateDropTableSQL(tableName);
  const timestamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[-:]/g, "").split(".")[0];
  const filename = `${timestamp}_create_${childName}_child_entity.sql`;
  return {
    up: upSQL,
    down: downSQL,
    filename,
    description: `Create ${childName} child entity for ${parentEntityName}`,
    dependencies: [`*_create_${parentEntityName}_entity.sql`]
  };
}
function generateCreateTableSQL(tableDef) {
  const { tableName, columns, indexes, constraints, rlsPolicies } = tableDef;
  let sql = `-- Create ${tableName} table
`;
  sql += `CREATE TABLE "${tableName}" (
`;
  const columnDefs = columns.map((col) => {
    let def = `  "${col.name}" ${col.type}`;
    if (col.primaryKey) {
      def += " PRIMARY KEY";
    } else if (!col.nullable) {
      def += " NOT NULL";
    }
    if (col.defaultValue) {
      def += ` DEFAULT ${col.defaultValue}`;
    }
    if (col.unique && !col.primaryKey) {
      def += " UNIQUE";
    }
    return def;
  });
  sql += columnDefs.join(",\n");
  sql += "\n);\n\n";
  columns.forEach((col) => {
    if (col.comment) {
      sql += `COMMENT ON COLUMN "${tableName}"."${col.name}" IS '${col.comment}';
`;
    }
  });
  if (columns.some((col) => col.comment)) {
    sql += "\n";
  }
  constraints.forEach((constraint) => {
    if (constraint.type !== "PRIMARY KEY") {
      sql += `ALTER TABLE "${tableName}" ADD CONSTRAINT "${constraint.name}" ${constraint.type} ${constraint.definition};
`;
    }
  });
  if (constraints.length > 1) {
    sql += "\n";
  }
  indexes.forEach((index) => {
    const uniqueKeyword = index.unique ? "UNIQUE " : "";
    const methodClause = index.method ? ` USING ${index.method}` : "";
    const partialClause = index.partial ? ` WHERE ${index.partial}` : "";
    sql += `CREATE ${uniqueKeyword}INDEX "${index.name}" ON "${tableName}"${methodClause} (${index.columns.map((c) => `"${c}"`).join(", ")})${partialClause};
`;
  });
  if (indexes.length > 0) {
    sql += "\n";
  }
  if (rlsPolicies.length > 0) {
    sql += `-- Enable Row Level Security
`;
    sql += `ALTER TABLE "${tableName}" ENABLE ROW LEVEL SECURITY;

`;
    rlsPolicies.forEach((policy) => {
      if (policy.name === "enable_rls") return;
      sql += `CREATE POLICY "${policy.name}" ON "${tableName}"
`;
      sql += `  FOR ${policy.action}`;
      if (policy.role) {
        sql += ` TO ${policy.role}`;
      }
      if (policy.using) {
        sql += `
  USING (${policy.using})`;
      }
      if (policy.withCheck) {
        sql += `
  WITH CHECK (${policy.withCheck})`;
      }
      sql += ";\n";
      if (policy.comment) {
        sql += `COMMENT ON POLICY "${policy.name}" ON "${tableName}" IS '${policy.comment}';
`;
      }
      sql += "\n";
    });
  }
  return sql.trim();
}
function generateDropTableSQL(tableName) {
  return `-- Drop ${tableName} table
DROP TABLE IF EXISTS "${tableName}" CASCADE;`;
}
function generateMigrationBoilerplate(entityName) {
  const timestamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[-:]/g, "").split(".")[0];
  const filename = `${timestamp}_create_${entityName}_entity.sql`;
  return `-- Migration: ${filename}
-- Description: Create ${entityName} entity
-- Generated: ${(/* @__PURE__ */ new Date()).toISOString()}

-- Up Migration
BEGIN;

-- Create ${entityName} table
CREATE TABLE "${entityName}" (
  "id" UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  "created_at" TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
  "updated_at" TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
  "deleted_at" TIMESTAMPTZ
);

-- Add indexes
CREATE INDEX "idx_${entityName}_created_at" ON "${entityName}" ("created_at");
CREATE INDEX "idx_${entityName}_deleted_at" ON "${entityName}" ("deleted_at");

-- Enable Row Level Security
ALTER TABLE "${entityName}" ENABLE ROW LEVEL SECURITY;

-- Create RLS policies
CREATE POLICY "${entityName}_admin_access" ON "${entityName}"
  FOR ALL TO service_role
  USING (TRUE);

COMMIT;

-- Down Migration (commented out for safety)
-- BEGIN;
-- DROP TABLE IF EXISTS "${entityName}" CASCADE;
-- COMMIT;
`;
}
function validateEntityForMigration(entityConfig) {
  var _a;
  const errors = [];
  const warnings = [];
  if (!entityConfig.slug) {
    errors.push("Entity slug is required (used to derive table name)");
  }
  if (!((_a = entityConfig.names) == null ? void 0 : _a.singular)) {
    errors.push("Entity singular name is required");
  }
  entityConfig.fields.forEach((field) => {
    if (!field.name) {
      errors.push(`Field name is required`);
    }
    if (!field.type) {
      errors.push(`Field type is required for field: ${field.name}`);
    }
    if (field.name && !/^[a-zA-Z_][a-zA-Z0-9_]*$/.test(field.name)) {
      errors.push(`Invalid field name: ${field.name}. Must be valid SQL identifier`);
    }
  });
  if (entityConfig.childEntities) {
    Object.entries(entityConfig.childEntities).forEach(([childName, childConfig]) => {
      if (!childConfig.table) {
        errors.push(`Child entity ${childName} missing table name`);
      }
      if (!childConfig.fields || childConfig.fields.length === 0) {
        warnings.push(`Child entity ${childName} has no fields defined`);
      }
    });
  }
  return {
    valid: errors.length === 0,
    errors,
    warnings
  };
}
export {
  generateEntityMigration,
  generateMigrationBoilerplate,
  validateEntityForMigration
};
