import mongoose, { Schema, Document, Model } from "mongoose";
import {
  ChatMessage,
  Conversation,
  CreateEventDTO,
  UpdateEventDTO,
  ProposedEventChange,
  ConflictingEvent,
} from "@calchat/shared";
import { IdVirtual } from "./types";

export interface ChatMessageDocument extends Omit<ChatMessage, "id">, Document {
  toJSON(): ChatMessage;
}
export interface ConversationDocument
  extends Omit<Conversation, "id">, Document {
  toJSON(): Conversation;
}

const EventSchema = new Schema<CreateEventDTO>(
  {
    title: { type: String, required: true },
    description: { type: String },
    startTime: { type: Date, required: true },
    endTime: { type: Date, required: true },
    note: { type: String },
    recurrenceRule: { type: String },
    exceptionDates: { type: [String] },
  },
  { _id: false },
);

const UpdatesSchema = new Schema<UpdateEventDTO>(
  {
    title: { type: String },
    description: { type: String },
    startTime: { type: Date },
    endTime: { type: Date },
    note: { type: String },
    recurrenceRule: { type: String },
  },
  { _id: false },
);

const ConflictingEventSchema = new Schema<ConflictingEvent>(
  {
    title: { type: String, required: true },
    startTime: { type: Date, required: true },
    endTime: { type: Date, required: true },
  },
  { _id: false },
);

const ProposedChangeSchema = new Schema<ProposedEventChange>(
  {
    id: { type: String, required: true },
    action: {
      type: String,
      enum: ["create", "update", "delete"],
      required: true,
    },
    eventId: { type: String },
    event: { type: EventSchema },
    updates: { type: UpdatesSchema },
    respondedAction: {
      type: String,
      enum: ["confirm", "reject"],
    },
    deleteMode: {
      type: String,
      enum: ["single", "future", "all"],
    },
    occurrenceDate: { type: String },
    conflictingEvents: { type: [ConflictingEventSchema] },
  },
  { _id: false },
);

const ChatMessageSchema = new Schema<
  ChatMessageDocument,
  Model<ChatMessageDocument, {}, {}, IdVirtual>,
  {},
  {},
  IdVirtual
>(
  {
    conversationId: {
      type: String,
      required: true,
    },
    sender: {
      type: String,
      enum: ["user", "assistant"],
      required: true,
    },
    content: {
      type: String,
      required: true,
    },
    proposedChanges: {
      type: [ProposedChangeSchema],
      default: undefined,
    },
  },
  {
    timestamps: true,
    virtuals: {
      id: {
        get() {
          return this._id.toString();
        },
      },
    },
    toJSON: {
      virtuals: true,
      transform: (_, ret: Record<string, unknown>) => {
        delete ret._id;
        delete ret.__v;
        return ret;
      },
    },
  },
);

const ConversationSchema = new Schema<
  ConversationDocument,
  Model<ConversationDocument, {}, {}, IdVirtual>,
  {},
  {},
  IdVirtual
>(
  {
    userId: {
      type: String,
      required: true,
      index: true,
    },
  },
  {
    timestamps: true,
    virtuals: {
      id: {
        get() {
          return this._id.toString();
        },
      },
    },
    toJSON: {
      virtuals: true,
      transform: (_, ret: Record<string, unknown>) => {
        delete ret._id;
        delete ret.__v;
        return ret;
      },
    },
  },
);

export const ChatMessageModel = mongoose.model<ChatMessageDocument>(
  "ChatMessage",
  ChatMessageSchema,
);
export const ConversationModel = mongoose.model<ConversationDocument>(
  "Conversation",
  ConversationSchema,
);
