import {
    FindSchedulesParams,
    ISchedulesAdapter,
    ISchedule,
    CreateScheduleParams,
    UpdateScheduleParams,
    PaginateSchedulesParams,
    PaginateSchedulesResults,
} from "./Schedules.Interface";
import { Document, Model, Schema, model } from "mongoose";

export interface IScheduleDocument extends Omit<ISchedule, "id">, Document {}

export class SchedulesAdapterMongoose implements ISchedulesAdapter {
    schema: Schema;
    schedulesList: Model<IScheduleDocument>;

    constructor() {
        this.schema = new Schema({
            employeeId: { type: Schema.Types.ObjectId, required: true, ref: "Employee" },
            companyId: { type: Schema.Types.ObjectId, required: true, ref: "Companie" },
            schedules: { type: Array, required: true },
            weekDay: { type: Number, required: true },
            creationDate: { type: Date, required: true, default: Date.now },
        });

        this.schedulesList = model<IScheduleDocument>("Schedule", this.schema);
    }

    public async create(data: CreateScheduleParams): Promise<ISchedule> {
        return await this.schedulesList.create(data);
    }

    public async update(data: UpdateScheduleParams): Promise<void> {
        const updateSchedule = await this.schedulesList.findOne({
            companyId: data.companyId,
            employeeId: data.employeeId,
            weekDay: data.weekDay,
        });

        if (!updateSchedule) {
            throw new Error("Schedule not found");
        }

        if (data.schedules) {
            updateSchedule.schedules = data.schedules;
        }

        updateSchedule.save();
    }

    public async delete(id: string): Promise<void> {
        await this.schedulesList.deleteOne({ _id: id }).exec();
    }

    public async find(filters: FindSchedulesParams): Promise<IScheduleDocument[]> {
        return this.schedulesList.find(filters).exec();
    }

    public async findOne(filters: FindSchedulesParams): Promise<IScheduleDocument | null> {
        return this.schedulesList.findOne(filters).exec();
    }

    public async paginate(filters: PaginateSchedulesParams): Promise<PaginateSchedulesResults> {
        const { page, limit, ...findFilters } = filters; //Extract page and limit from filters
        const count = await this.schedulesList.countDocuments(findFilters).exec();
        const skip = (page - 1) * limit;

        const results = await this.schedulesList
            .find(findFilters)
            .skip(skip)
            .limit(filters.limit)
            .exec();

        return {
            data: results,
            page: filters.page,
            pages: Math.ceil(count / filters.limit),
        };
    }
}
