import { Prop, Schema, SchemaFactory } from '@nestjs/mongoose';
import { HydratedDocument, Types } from 'mongoose';
import { resolveManagedFileUrl } from '../../../common/utils/public-url.util';
import { User } from '../../users/schemas/user.schema';

export type MessageDocument = HydratedDocument<Message>;

@Schema({ _id: false, versionKey: false })
export class MessageDeliveryReceipt {
  @Prop({ type: Types.ObjectId, ref: User.name, required: true })
  userId!: Types.ObjectId;

  @Prop({ type: Date, required: true })
  deliveredAt!: Date;
}

export const MessageDeliveryReceiptSchema = SchemaFactory.createForClass(MessageDeliveryReceipt);

@Schema({ timestamps: true, versionKey: false })
export class Message {
  @Prop({ type: Types.ObjectId, required: true, index: true })
  conversationId!: Types.ObjectId;

  @Prop({ type: Types.ObjectId, ref: User.name, required: true, index: true })
  senderId!: Types.ObjectId;

  @Prop({ required: false, default: '', maxlength: 4000 })
  content!: string;

  @Prop({ enum: ['text', 'image', 'video', 'audio'], default: 'text', index: true })
  messageType!: 'text' | 'image' | 'video' | 'audio';

  @Prop({ required: false, default: '' })
  mediaUrl!: string;

  @Prop({ type: Types.ObjectId, ref: 'Message', default: null, index: true })
  replyToMessageId?: Types.ObjectId | null;

  @Prop({ type: Map, of: String, default: {} })
  reactionsByUser!: Map<string, string>;

  @Prop({ type: [Types.ObjectId], ref: User.name, default: [] })
  seenBy!: Types.ObjectId[];

  @Prop({ type: [MessageDeliveryReceiptSchema], default: [] })
  deliveredBy!: MessageDeliveryReceipt[];

  @Prop({ type: [Types.ObjectId], ref: User.name, default: [], index: true })
  deletedForUserIds!: Types.ObjectId[];

  @Prop({ default: false, index: true })
  isUnsent!: boolean;

}

export const MessageSchema = SchemaFactory.createForClass(Message);
MessageSchema.index({ conversationId: 1, createdAt: -1 });
MessageSchema.index({ conversationId: 1, isUnsent: 1, createdAt: -1 });

const transformManagedMessageFiles = (_doc: unknown, ret: any) => {
  ret.mediaUrl = resolveManagedFileUrl(ret.mediaUrl);
  return ret;
};

MessageSchema.set('toJSON', { transform: transformManagedMessageFiles });
MessageSchema.set('toObject', { transform: transformManagedMessageFiles });
