# frozen_string_literal: true

# <%= modelName %> model class
class <%= modelName %>
  include Mongoid::Document
  include Mongoid::Timestamps

  <% 
// Collect all enum fields
const enumFields = fields.filter(field => (field.type === 'Enum' || (field.enum_values && field.enum_values.length > 0)) && !field.name.endsWith('_id'));
if (enumFields.length > 0) { 
-%>
  # Define enums
  ENUMS = {
<% enumFields.forEach(function(field, index) { -%>    <%= field.name %>: {
      values: %w[<%- field.enum_values ? field.enum_values.map(v => v.replace(/['"]/g, '').trim()).join(' ') : 'default' %>],
      default: '<%- field.default ? field.default.replace(/['"]/g, '') : (field.enum_values && field.enum_values.length > 0 ? field.enum_values[0].replace(/['"]/g, '') : 'default') %>'
    }<%= index < enumFields.length - 1 ? ',' : '' %>
<% }); -%>
  }.freeze
<% } -%>

  # Fields
<% 
// Find polymorphic fields
const polymorphicIdFields = fields.filter(field => field.is_polymorphic_id);
const polymorphicTypeFields = fields.filter(field => field.is_polymorphic_type);

// Process regular fields
fields.forEach(function(field) { 
  // Skip polymorphic fields as they'll be handled separately
  if (field.is_polymorphic_id || field.is_polymorphic_type) {
    return;
  }
  
  // Skip fields ending with _id or _type as they're managed by relationships
  if (field.name.endsWith('_id') || field.name.endsWith('_type')) {
    return;
  }
-%>
  field :<%= field.name %>, type: <%= (field.enum_values && field.enum_values.length > 0) ? 'String' : field.type %><% if (field.default !== undefined) { %><% if (field.enum_values && field.enum_values.length > 0) { %>, default: <%- "ENUMS[:" + field.name + "][:default]" %><% } else { %>, default: <%= field.default %><% } %><% } %>
<% }); -%>

<% 
// Process polymorphic fields
if (polymorphicIdFields.length > 0 || polymorphicTypeFields.length > 0) { 
-%>
  # Polymorphic fields
<% 
  // Process polymorphic ID fields
  polymorphicIdFields.forEach(function(field) { 
-%>  field :<%= field.name %>, type: BSON::ObjectId<% if (field.required) { %>, required: <%= field.required %><% } %>
<% }); -%>
<% 
  // Process polymorphic Type fields
  polymorphicTypeFields.forEach(function(field) { 
-%>  field :<%= field.name %>, type: String<% if (field.required) { %>, required: <%= field.required %><% } %>
<% }); -%>
<% } -%>

<% if (relationships && relationships.length > 0) { -%>
  # Relationships
<% 
  // Group relationships by type for better organization
  const belongsTo = relationships.filter(rel => rel.type === 'belongs_to');
  const hasMany = relationships.filter(rel => rel.type === 'has_many');
  const hasOne = relationships.filter(rel => rel.type === 'has_one');
  const other = relationships.filter(rel => !['belongs_to', 'has_many', 'has_one'].includes(rel.type));
  
  // Create a Set to track relationship names and prevent duplicates
  const addedRelationships = new Set();
  
  // Output belongs_to relationships first
  belongsTo.forEach(function(rel) { 
    // Use the model snake_case name for proper naming
    const modelName = rel.modelSnakeCase || rel.model.toLowerCase();
    
    // Check if this relationship has already been added
    const relationshipKey = `${rel.type}:${modelName}`;
    if (addedRelationships.has(relationshipKey)) {
      return; // Skip duplicate relationship
    }
    addedRelationships.add(relationshipKey);
    
    if (rel.polymorphic) {
-%>  <%= rel.type %> :<%= modelName %>, polymorphic: true
<% } else { -%>  <%= rel.type %> :<%= modelName %><% if (rel.foreign_key) { %>, foreign_key: '<%= rel.foreign_key %>'<% } %>
<% } -%>
<% }); -%>
<% 
  // Output has_many relationships
  hasMany.forEach(function(rel) { 
    // Use the pluralized model name from the relationship
    const pluralizedName = rel.pluralizedModel || utils.pluralize(rel.modelSnakeCase || rel.model.toLowerCase());
    
    // Check if this relationship has already been added
    const relationshipKey = `${rel.type}:${pluralizedName}`;
    if (addedRelationships.has(relationshipKey)) {
      return; // Skip duplicate relationship
    }
    addedRelationships.add(relationshipKey);
    
    if (rel.polymorphic) {
-%>  <%= rel.type %> :<%= pluralizedName %>, as: :<%= rel.as %>
<% } else { -%>  <%= rel.type %> :<%= pluralizedName %><% if (rel.foreign_key) { %>, foreign_key: '<%= rel.foreign_key %>'<% } %><% if (rel.dependent) { %>, dependent: :<%= rel.dependent %><% } %>
<% } -%>
<% }); -%>
<% 
  // Output has_one relationships
  hasOne.forEach(function(rel) { 
    // Use the model snake_case name for proper naming
    const modelName = rel.modelSnakeCase || rel.model.toLowerCase();
    
    // Check if this relationship has already been added
    const relationshipKey = `${rel.type}:${modelName}`;
    if (addedRelationships.has(relationshipKey)) {
      return; // Skip duplicate relationship
    }
    addedRelationships.add(relationshipKey);
    
    if (rel.polymorphic) {
-%>  <%= rel.type %> :<%= modelName %>, as: :<%= rel.as %>
<% } else { -%>  <%= rel.type %> :<%= modelName %><% if (rel.foreign_key) { %>, foreign_key: '<%= rel.foreign_key %>'<% } %><% if (rel.dependent) { %>, dependent: :<%= rel.dependent %><% } %>
<% } -%>
<% }); -%>
<% 
  // Output other relationship types
  other.forEach(function(rel) { 
    if (rel.type.includes('many')) {
      // Use the pluralized model name from the relationship
      const pluralizedName = rel.pluralizedModel || utils.pluralize(rel.modelSnakeCase || rel.model.toLowerCase());
      
      // Check if this relationship has already been added
      const relationshipKey = `${rel.type}:${pluralizedName}`;
      if (addedRelationships.has(relationshipKey)) {
        return; // Skip duplicate relationship
      }
      addedRelationships.add(relationshipKey);
      
      if (rel.polymorphic) {
-%>  <%= rel.type %> :<%= pluralizedName %>, as: :<%= rel.as %>
<%    } else { -%>  <%= rel.type %> :<%= pluralizedName %><% if (rel.foreign_key) { %>, foreign_key: '<%= rel.foreign_key %>'<% } %><% if (rel.dependent) { %>, dependent: :<%= rel.dependent %><% } %>
<%    } -%>
<%  } else { 
      // Use the model snake_case name for proper naming
      const modelName = rel.modelSnakeCase || rel.model.toLowerCase();
      
      // Check if this relationship has already been added
      const relationshipKey = `${rel.type}:${modelName}`;
      if (addedRelationships.has(relationshipKey)) {
        return; // Skip duplicate relationship
      }
      addedRelationships.add(relationshipKey);
      
      if (rel.polymorphic) {
-%>  <%= rel.type %> :<%= modelName %>, as: :<%= rel.as %>
<%    } else { -%>  <%= rel.type %> :<%= modelName %><% if (rel.foreign_key) { %>, foreign_key: '<%= rel.foreign_key %>'<% } %><% if (rel.dependent) { %>, dependent: :<%= rel.dependent %><% } %>
<%    } -%>
<%  } -%>
<% }); -%>
<% } -%>

  # Validations
<% fields.forEach(function(field) { -%>
<% if (field.name.endsWith('_id') || field.name.endsWith('_type')) {
  // Skip relationship fields
  return;
} -%>
<% if (field.validations) { -%>
<% if (field.validationStatements) { -%>
<% field.validationStatements.forEach(statement => { -%>  <%- statement %>
<% }); -%>
<% } -%>
<% } -%>
<% }); -%>

<% if (enumFields.length > 0) { -%>  # Generate enum helper methods
  ENUMS.each do |field, config|
    validates field, inclusion: { in: config[:values] }

    config[:values].each do |value|
      define_method("#{value}?") { send(field) == value }
      define_method("mark_as_#{value}!") do
        update!(field => value)
      end
    end
  end
<% } -%>
end 