import { Schema, model } from 'mongoose';

import {
  IProjectDoc,
  IProjectModel,
} from '@/modules/project/project.interface';
import { paginate, toJSON } from '@/shared/utils/plugins';

const projectSchema = new Schema<IProjectDoc>(
  {
    projectName: {
      type: String,
      required: true,
      trim: true,
    },
    propertyType: {
      type: Schema.Types.ObjectId,
      ref: 'Category',
      validate: {
        validator: function (value) {
          if (this.isDraft) return true;
          return value && value !== null;
        },
        message: 'Property type is required for complete projects',
      },
    },
    subCategory: {
      type: Schema.Types.ObjectId,
      ref: 'SubCategory',
    },
    amenities: [
      {
        type: Schema.Types.ObjectId,
        ref: 'Amenities',
        validate: {
          validator: function (value) {
            if (this.isDraft) return true;
            return Array.isArray(value) && value.length > 0;
          },
          message: 'Amenities are required for complete projects',
        },
      },
    ],
    status: {
      type: String,
      enum: [
        'under_construction',
        'possession_soon',
        'ready_possession',
        'launch',
      ],
      default: 'under_construction',
    },
    locality: {
      type: Schema.Types.ObjectId,
      ref: 'Area',
      validate: {
        validator: function (value) {
          if (this.isDraft) return true;
          return value && value !== null;
        },
        message: 'Locality is required for complete project',
      },
    },
    city: {
      type: Schema.Types.ObjectId,
      ref: 'City',
      validate: {
        validator: function (value) {
          if (this.isDraft) return true;
          return value && value !== null;
        },
        message: 'City is required for complete projects',
      },
    },
    state: {
      type: Schema.Types.ObjectId,
      ref: 'State',
      validate: {
        validator: function (value) {
          if (this.isDraft) return true;
          return value && value !== null;
        },
        message: 'State is required for complete projects',
      },
    },
    pincode: {
      type: Number,
      default: 0,
      validate: {
        validator: function (value) {
          if (this.isDraft) return true;
          return value && value > 0;
        },
        message: 'Pincode is required for complete projects',
      },
    },
    pricePerSqYard: {
      type: Number,
      default: 0,
      validate: {
        validator: function (value) {
          if (this.isDraft) return true;
          return value && value > 0;
        },
        message: 'Price is required for complete projects',
      },
    },
    reraId: {
      type: String,
      trim: true,
      validate: {
        validator: function (value) {
          if (this.isDraft) return true;
          return value && value !== null;
        },
        message: 'Rera Id is required for complete projects',
      },
    },
    possessionDate: { type: Date },
    landmark: {
      type: String,
      trim: true,
    },
    normalizedName: {
      type: String,
      lowercase: true,
      default: '',
    },
    description: {
      type: String,
      trim: true,
    },
    createdBy: {
      type: Schema.Types.ObjectId,
      ref: 'User',
      required: true,
    },
    updatedBy: {
      type: Schema.Types.ObjectId,
      ref: 'User',
    },
    isSystemGenerated: {
      type: Boolean,
      default: false,
    },
    searchCount: {
      type: Number,
      default: 0,
    },
    isDraft: {
      type: Boolean,
      default: false,
    },
    companyId: {
      type: Schema.Types.ObjectId,
      ref: 'Company',
    },
    team: {
      type: Schema.Types.ObjectId,
      ref: 'Team',
    },
    creationMethod: {
      type: String,
      enum: ['search', 'form'],
      default: 'search',
    },
    mediaUrls: [{ type: String }],
    hasBlockLayout: {
      type: Boolean,
      default: false,
    },
    visibleToUsers: [{ type: Schema.Types.ObjectId, ref: 'User' }],
    visibleToTeams: [{ type: Schema.Types.ObjectId, ref: 'Team' }],
    isPublicVisibility: { type: Boolean, default: true },
  },
  {
    timestamps: true,
  },
);

projectSchema.virtual('units', {
  ref: 'Unit',
  localField: '_id',
  foreignField: 'project',
});

projectSchema.virtual('files', {
  ref: 'File',
  localField: '_id',
  foreignField: 'project',
});
projectSchema.virtual('paymentTerms', {
  ref: 'PaymentTerm',
  localField: '_id',
  foreignField: 'project',
});
projectSchema.virtual('timelines', {
  ref: 'Timeline',
  localField: '_id',
  foreignField: 'project',
});

projectSchema.index({ name: 'text', description: 'text' });
projectSchema.index({ createdBy: 1 });
projectSchema.index({ isDraft: 1 });

projectSchema.pre('save', function (next) {
  this.normalizedName = this.projectName.toLowerCase().trim();

  if (this.creationMethod === 'search') this.isDraft = true;

  next();
});

projectSchema.methods.convertToFullProject = function (updateData) {
  this.isDraft = false;
  this.creationMethod = 'form';
  Object.assign(this, updateData);
  return this.save();
};

projectSchema.plugin(toJSON);
projectSchema.plugin(paginate);

// Add virtual field for timelines
projectSchema.virtual('timelines', {
  ref: 'Timeline',
  localField: '_id',
  foreignField: 'project',
});

const Project = model<IProjectDoc, IProjectModel>('Project', projectSchema);

export default Project;
export { Project };
