import { getRegistry } from '{{PATH_TO_SOURCE_DIR}}main';
{{#if HAS_CUSTOM_SCHEMA}}
import * as CS from '{{PATH_TO_SOURCE_DIR}}common/custom.schema';
{{/if}}
import {
  _FileAttributeSchemaFields,
  _ItemTagsSchemaFields,
  _ItemUpdateSchemaFields,
  _UserSnapshotSchemaFields,
  _AddressSchemaFields,
  _LocationSchemaFields,
} from "jsm-core";
import { ensureIndexes, getTrackUsedFieldsDBMiddleware } from "jsm-utilities/dist/node";
import { model, models, Schema } from "mongoose";
import fuzzySearching from "mongoose-fuzzy-searching";

const cache = getRegistry().cache;
const trackUsedFieldsDBMiddleware = getTrackUsedFieldsDBMiddleware(cache);


/**
 * Aliasing the typings for the {{SUB_MODULE_ENTITY_CAMELCASED_CAPITALIZED_SINGULAR}} entity and model.
 */
type _Entity = {{ENTITY_TYPING_ALIAS}};
type _Model = {{MONGOOSE_MODEL_TYPING_ALIAS}};
type _Document = {{MONGOOSE_DOCUMENT_TYPING_ALIAS}};
type DeepStrictSchemaDefinition<T = undefined> =
  Jsm.Core.Utils.Mongodb.DeepStrictSchemaDefinition<T>;

{{#ifHasEmbeddedSchema ENTITY_META}}
/**
 * Represents the embedded objects of the {{SUB_MODULE_ENTITY_CAMELCASED_CAPITALIZED_SINGULAR}}Schema.
 */
const EmbeddedObjects: DeepStrictSchemaDefinition<
  Pick<_Entity, {{modelGetEmbeddedProperties ENTITY_META}}>
> = {
  {{toEmbeddedSchemaProperties ENTITY_META}}
};
{{/ifHasEmbeddedSchema}}

/**
 * Represents the fields of the {{SUB_MODULE_ENTITY_CAMELCASED_CAPITALIZED_SINGULAR}} Schema.
 */
const {{SUB_MODULE_ENTITY_CAMELCASED_CAPITALIZED_SINGULAR}}SchemaFields: DeepStrictSchemaDefinition<
  Omit<_Entity, "_id" | "created_at" | "updated_at">
> = {
  {{#if ENTITY_META.is_creatable}}
  /**
   * Inherited from ICreatable
   */
  app: { type: String, required: false, default: null },
  company: { type: String, default: null },
  created_by: { type: Schema.Types.String, required: false, default: null },
  created_by_original_user: {
    type: _UserSnapshotSchemaFields,
    default: null,
  },
  is_deleted: { type: Boolean, default: false },
  deleted_at: { type: Date, default: null },
  tags: _ItemTagsSchemaFields,
  updates: [_ItemUpdateSchemaFields],
  {{/if}}
  {{nl}}
  {{#if ENTITY_META.has_search_meta}}
  /**
   * Inherited from IHasSearchMeta
   */
  search_meta: { type: String },
  {{/if}}
  
  {{#if ENTITY_META.is_importable}}
  /**
   * Inherited from IHasSearchMeta
   */
  import_status: { type: String }, 
  import_id: { type: String }, 
  import_tracking_id: { type: String }, 
  import_index: { type: Number },
  {{/if}}

  {{#ifHasEmbeddedSchema ENTITY_META}}
  /**
   * Inject the embedded objects
   */
  ...EmbeddedObjects,
  {{/ifHasEmbeddedSchema}}

  /**
   * Specific to Entity
   */
  {{toSchemaProperties ENTITY.interface_properties ENTITY_META "_id,created_at,updated_at"}}
  
};

/**
 * The Mongoose schema for the {{SUB_MODULE_ENTITY_CAMELCASED_CAPITALIZED_SINGULAR}} model.
 *
 * @remarks
 * This schema defines the fields and their types for the {{SUB_MODULE_ENTITY_CAMELCASED_CAPITALIZED_SINGULAR}} model.
 *
 */
const {{SUB_MODULE_ENTITY_CAMELCASED_CAPITALIZED_SINGULAR}}Schema = new Schema<_Document>({{SUB_MODULE_ENTITY_CAMELCASED_CAPITALIZED_SINGULAR}}SchemaFields, {
  timestamps: {
    createdAt: "created_at",
    updatedAt: "updated_at",
  },
});

/**
 * Build indexes
 */
{{#if ENTITY_META.indexes}}
{{#each ENTITY_META.indexes}}
{{../SUB_MODULE_ENTITY_CAMELCASED_CAPITALIZED_SINGULAR}}Schema.index({{this.key}}, { {{#if this.unique}}unique: true,{{/if}} {{#if this.partialFilterExpression}} partialFilterExpression: {{this.partialFilterExpression}}{{/if}} });
{{/each}}
{{/if}}

/**
 * Track the used fields in the database.
 *
 * @param next - The next middleware function.
 */
// Apply the middleware to the schema before any `find` operation
{{SUB_MODULE_ENTITY_CAMELCASED_CAPITALIZED_SINGULAR}}Schema.pre("find", trackUsedFieldsDBMiddleware);
{{SUB_MODULE_ENTITY_CAMELCASED_CAPITALIZED_SINGULAR}}Schema.pre("findOne", trackUsedFieldsDBMiddleware);
{{SUB_MODULE_ENTITY_CAMELCASED_CAPITALIZED_SINGULAR}}Schema.pre("findOneAndUpdate", trackUsedFieldsDBMiddleware);

/**
 * The Mongoose fuzzy search plugin for the {{SUB_MODULE_ENTITY_CAMELCASED_CAPITALIZED_SINGULAR}}Schema.
 */
{{#if ENTITY_META.has_search_meta}}
{{SUB_MODULE_ENTITY_CAMELCASED_CAPITALIZED_SINGULAR}}Schema.plugin(fuzzySearching, {
  fields: [
    {
      name: "search_meta",
    },
  ],
});
{{else}}
// This model does not have search meta
{{/if}}

/**
 * The Mongoose model for the {{SUB_MODULE_ENTITY_CAMELCASED_CAPITALIZED_SINGULAR}} model.
 *
 * @remarks
 * This model is used to perform CRUD operations on the {{SUB_MODULE_ENTITY_CAMELCASED_CAPITALIZED_SINGULAR}} model.
 *
 */
const {{SUB_MODULE_ENTITY_CAMELCASED_CAPITALIZED_SINGULAR}}: _Model =
  models?.{{SUB_MODULE_ENTITY_CAMELCASED_CAPITALIZED_SINGULAR}} || model<_Document>("{{SUB_MODULE_ENTITY_CAMELCASED_CAPITALIZED_SINGULAR}}", {{SUB_MODULE_ENTITY_CAMELCASED_CAPITALIZED_SINGULAR}}Schema);

/**
 * The {{SUB_MODULE_ENTITY_CAMELCASED_CAPITALIZED_SINGULAR}} model and its associated Schema.
 */
export { {{SUB_MODULE_ENTITY_CAMELCASED_CAPITALIZED_SINGULAR}}, {{SUB_MODULE_ENTITY_CAMELCASED_CAPITALIZED_SINGULAR}}Schema, {{SUB_MODULE_ENTITY_CAMELCASED_CAPITALIZED_SINGULAR}}SchemaFields };

/**
 * Ensure indexes
 */
ensureIndexes<typeof cache>({{SUB_MODULE_ENTITY_CAMELCASED_CAPITALIZED_SINGULAR}} as any, cache);
