import mongoose, { Schema, models, model } from "mongoose";

export const TODO_STATUSES = ["open", "in_progress", "done"] as const;
export type TodoStatus = (typeof TODO_STATUSES)[number];

export const TODO_PRIORITIES = ["low", "normal", "high"] as const;
export type TodoPriority = (typeof TODO_PRIORITIES)[number];

export const TODO_RECURRENCES = ["none", "daily", "weekly", "monthly"] as const;
export type TodoRecurrence = (typeof TODO_RECURRENCES)[number];

export interface TodoNoteDoc {
  _id: string;
  authorId: mongoose.Types.ObjectId;
  text: string;
  createdAt: Date;
}

const todoNoteSchema = new Schema<TodoNoteDoc>(
  {
    authorId: { type: Schema.Types.ObjectId, ref: "Client", required: true },
    text: { type: String, required: true, trim: true, maxlength: 2000 },
  },
  { timestamps: { createdAt: true, updatedAt: false } }
);

export interface TodoSubtaskDoc {
  _id: string;
  text: string;
  done: boolean;
  doneAt: Date | null;
}

const todoSubtaskSchema = new Schema<TodoSubtaskDoc>(
  {
    text: { type: String, required: true, trim: true, maxlength: 300 },
    done: { type: Boolean, default: false },
    doneAt: { type: Date, default: null },
  },
  { _id: true }
);

export interface TodoActivityDoc {
  _id: string;
  type: string;
  actorId: mongoose.Types.ObjectId;
  text: string;
  createdAt: Date;
}

const todoActivitySchema = new Schema<TodoActivityDoc>(
  {
    type: { type: String, required: true },
    actorId: { type: Schema.Types.ObjectId, ref: "Client", required: true },
    text: { type: String, required: true, trim: true, maxlength: 500 },
  },
  { timestamps: { createdAt: true, updatedAt: false } }
);

export interface TodoAttachmentDoc {
  filename: string;
  storedName: string;
  size: number;
  mimeType: string;
  uploadedAt: Date;
}

const todoAttachmentSchema = new Schema<TodoAttachmentDoc>(
  {
    filename: { type: String, required: true },
    storedName: { type: String, required: true },
    size: { type: Number, required: true },
    mimeType: { type: String, required: true },
    uploadedAt: { type: Date, default: Date.now },
  },
  { _id: false }
);

export interface TodoDoc {
  _id: string;
  title: string;
  description: string;
  attachments: TodoAttachmentDoc[];
  assignedToId: mongoose.Types.ObjectId;
  // Zusätzliche Personen, die an der Aufgabe mitarbeiten (dürfen bearbeiten
  // wie der Haupt-Zuständige). `watcherIds` bekommen nur Benachrichtigungen.
  additionalAssigneeIds: mongoose.Types.ObjectId[];
  watcherIds: mongoose.Types.ObjectId[];
  activity: TodoActivityDoc[];
  createdById: mongoose.Types.ObjectId;
  status: TodoStatus;
  priority: TodoPriority;
  dueDate: Date | null;
  // Optionaler Bezug zu einem Auftrag, für den das ToDo anfällt — rein
  // informativ, kein Zwang, jedes ToDo an einen Auftrag zu hängen.
  orderId: mongoose.Types.ObjectId | null;
  // Freitext-Labels (z. B. "Vorbereitung", "Marketing") — filterbar im Board,
  // Farbe wird clientseitig aus dem Namen abgeleitet.
  labels: string[];
  // Optionale Bündelung mehrerer ToDos unter einem Projekt/einer Liste
  // (Freitext, z. B. "DoKomi 2027" oder "Website-Relaunch").
  project: string;
  // Unteraufgaben / Checkliste innerhalb des ToDos.
  subtasks: TodoSubtaskDoc[];
  notes: TodoNoteDoc[];
  completedAt: Date | null;
  // "none" = einmalige Aufgabe (Standard). Bei jeder anderen Stufe wird beim
  // Erledigen automatisch eine neue Instanz mit verschobenem Fälligkeitsdatum
  // erzeugt (siehe actions/todos.ts updateTodoStatusAction) — ein simples
  // "erzeugt beim Abhaken die nächste" statt eines eigenen Cron-Jobs mit
  // Dedup-Logik.
  recurrence: TodoRecurrence;
  // Wiederholungs-Details: alle N Einheiten (interval), bei "weekly"
  // optional an bestimmten Wochentagen (0=So … 6=Sa), optional bis zu
  // einem Enddatum (danach wird keine neue Instanz mehr erzeugt).
  recurrenceInterval: number;
  recurrenceWeekdays: number[];
  recurrenceEndDate: Date | null;
  // Verhindert doppelte Erinnerungsmails für dasselbe Fälligkeitsdatum;
  // wird beim Ändern des Datums zurückgesetzt.
  dueReminderSentAt: Date | null;
  // Idempotenz-Schlüssel für automatisch erzeugte ToDos (z. B.
  // "shoot-prep:<orderId>" oder "conv:<convId>:<staffId>") — leer bei
  // manuell angelegten.
  autoKey: string;
  createdAt: Date;
  updatedAt: Date;
}

const todoSchema = new Schema<TodoDoc>(
  {
    title: { type: String, required: true, trim: true, maxlength: 200 },
    description: { type: String, default: "", trim: true, maxlength: 4000 },
    assignedToId: { type: Schema.Types.ObjectId, ref: "Client", required: true, index: true },
    additionalAssigneeIds: { type: [Schema.Types.ObjectId], ref: "Client", default: [] },
    watcherIds: { type: [Schema.Types.ObjectId], ref: "Client", default: [] },
    activity: { type: [todoActivitySchema], default: [] },
    createdById: { type: Schema.Types.ObjectId, ref: "Client", required: true },
    status: { type: String, enum: TODO_STATUSES, default: "open", index: true },
    priority: { type: String, enum: TODO_PRIORITIES, default: "normal" },
    dueDate: { type: Date, default: null },
    orderId: { type: Schema.Types.ObjectId, ref: "Order", default: null },
    labels: { type: [String], default: [] },
    project: { type: String, default: "", trim: true, maxlength: 80 },
    subtasks: { type: [todoSubtaskSchema], default: [] },
    attachments: { type: [todoAttachmentSchema], default: [] },
    notes: { type: [todoNoteSchema], default: [] },
    completedAt: { type: Date, default: null },
    recurrence: { type: String, enum: TODO_RECURRENCES, default: "none" },
    recurrenceInterval: { type: Number, default: 1, min: 1, max: 52 },
    recurrenceWeekdays: { type: [Number], default: [] },
    recurrenceEndDate: { type: Date, default: null },
    dueReminderSentAt: { type: Date, default: null },
    autoKey: { type: String, default: "", index: true },
  },
  { timestamps: true }
);

export const Todo = (models.Todo as mongoose.Model<TodoDoc>) || model<TodoDoc>("Todo", todoSchema);
