"use strict";
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
    var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
    if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
    else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
    return c > 3 && r && Object.defineProperty(target, key, r), r;
};
var __metadata = (this && this.__metadata) || function (k, v) {
    if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.EventsService = void 0;
const common_1 = require("@nestjs/common");
const config_1 = require("../../config");
const utils_1 = require("../../utils");
const events_dto_1 = require("./events.dto");
let EventsService = class EventsService {
    constructor(db, uploadService) {
        this.db = db;
        this.uploadService = uploadService;
    }
    async moveEventImage(image) {
        if (!image ||
            typeof image !== 'object' ||
            typeof image.file_name !== 'string' ||
            image.file_name.trim() === '') {
            return undefined;
        }
        const moved = await this.uploadService.moveImage(image, 'events');
        return {
            file_name: moved.file_name,
            original_name: moved.original_name,
            file_size: moved.file_size,
            mime_type: moved.mime_type,
        };
    }
    includeMembers() {
        return {
            members: {
                select: {
                    id: true,
                    employee_id: true,
                    first_name: true,
                    last_name: true,
                    nickname: true,
                    image: true,
                },
            },
        };
    }
    async ensureMembersExist(memberIds, owner_id) {
        if (memberIds.length === 0) {
            return;
        }
        const count = await this.db.members.count({
            where: {
                owner_id,
                id: {
                    in: memberIds,
                },
            },
        });
        if (count !== memberIds.length) {
            throw (0, utils_1.createGeneralError)('One or more members are invalid', 'member_ids', common_1.HttpStatus.BAD_REQUEST);
        }
    }
    async createEvent(data, owner_id) {
        try {
            const memberIds = data.member_ids ?? [];
            await this.ensureMembersExist(memberIds, owner_id);
            const image = await this.moveEventImage(data.image);
            const event = await this.db.events.create({
                data: {
                    title: data.title,
                    category: data.category ?? 'meeting',
                    ...(image ? { image } : {}),
                    date: data.date,
                    start_time: data.start_time,
                    end_time: data.end_time,
                    attendees: memberIds.length,
                    ...(data.location ? { location: data.location } : {}),
                    ...(data.event_owner ? { event_owner: data.event_owner } : {}),
                    ...(data.description ? { description: data.description } : {}),
                    ...(memberIds.length > 0
                        ? {
                            members: {
                                connect: memberIds.map((id) => ({ id })),
                            },
                        }
                        : {}),
                    owner: {
                        connect: {
                            id: owner_id,
                        },
                    },
                },
                include: this.includeMembers(),
            });
            const { data: parsedEvent } = events_dto_1.eventResponseSchema.safeParse(event);
            return {
                data: parsedEvent,
                message: 'Event created successfully',
                status: common_1.HttpStatus.CREATED,
                details: null,
            };
        }
        catch (error) {
            config_1.logger.error(`Error in createEvent: ${String(error)}`);
            if (error instanceof config_1.ErrorResponse) {
                throw error;
            }
            throw (0, utils_1.createGeneralError)(String(error), 'root', common_1.HttpStatus.BAD_REQUEST);
        }
    }
    async getEvents(query, owner_id) {
        try {
            const page = query.page ?? 1;
            const limit = query.limit ?? 10;
            const skip = (page - 1) * limit;
            const where = { owner_id };
            if (query.category) {
                where.category = query.category;
            }
            if (query.search) {
                where.OR = [
                    {
                        title: {
                            contains: query.search,
                        },
                    },
                    {
                        location: {
                            contains: query.search,
                        },
                    },
                    {
                        event_owner: {
                            contains: query.search,
                        },
                    },
                    {
                        description: {
                            contains: query.search,
                        },
                    },
                ];
            }
            if (query.from || query.to) {
                where.date = {
                    ...(query.from ? { gte: query.from } : {}),
                    ...(query.to ? { lte: query.to } : {}),
                };
            }
            const [events, total] = await Promise.all([
                this.db.events.findMany({
                    where,
                    include: this.includeMembers(),
                    orderBy: {
                        date: 'asc',
                    },
                    skip,
                    take: limit,
                }),
                this.db.events.count({ where }),
            ]);
            const { data: parsedEvents } = events_dto_1.eventsResponseSchema.safeParse(events);
            const totalPages = Math.ceil(total / limit);
            return {
                data: parsedEvents,
                message: 'Events retrieved successfully',
                status: common_1.HttpStatus.OK,
                details: {
                    pagination: {
                        total_items: total,
                        total_pages: totalPages,
                        current_page: page,
                        items_per_page: limit,
                        has_next_page: page < totalPages,
                        has_previous_page: page > 1,
                        next_page: page < totalPages ? page + 1 : null,
                        previous_page: page > 1 ? page - 1 : null,
                    },
                },
            };
        }
        catch (error) {
            config_1.logger.error(`Error in getEvents: ${String(error)}`);
            if (error instanceof config_1.ErrorResponse) {
                throw error;
            }
            throw (0, utils_1.createGeneralError)(String(error), 'root', common_1.HttpStatus.BAD_REQUEST);
        }
    }
    async getEventById(id, owner_id) {
        try {
            const event = await this.db.events.findUnique({
                where: { id, owner_id },
                include: this.includeMembers(),
            });
            if (!event) {
                throw (0, utils_1.createGeneralError)('Event not found', 'event', common_1.HttpStatus.NOT_FOUND);
            }
            const { data: parsedEvent } = events_dto_1.eventResponseSchema.safeParse(event);
            return {
                data: parsedEvent,
                message: 'Event retrieved successfully',
                status: common_1.HttpStatus.OK,
                details: null,
            };
        }
        catch (error) {
            config_1.logger.error(`Error in getEventById: ${String(error)}`);
            if (error instanceof config_1.ErrorResponse) {
                throw error;
            }
            throw (0, utils_1.createGeneralError)(String(error), 'root', common_1.HttpStatus.BAD_REQUEST);
        }
    }
    async updateEvent(id, data, owner_id) {
        try {
            const existingEvent = await this.db.events.findUnique({
                where: { id, owner_id },
                include: {
                    members: {
                        select: { id: true },
                    },
                },
            });
            if (!existingEvent) {
                throw (0, utils_1.createGeneralError)('Event not found', 'event', common_1.HttpStatus.NOT_FOUND);
            }
            if (data.member_ids) {
                await this.ensureMembersExist(data.member_ids, owner_id);
            }
            const nextImage = data.image === null
                ? {}
                : data.image
                    ? await this.moveEventImage(data.image)
                    : undefined;
            const updatedEvent = await this.db.events.update({
                where: { id },
                data: {
                    ...(data.title ? { title: data.title } : {}),
                    ...(nextImage !== undefined ? { image: nextImage } : {}),
                    ...(data.category ? { category: data.category } : {}),
                    ...(data.date ? { date: data.date } : {}),
                    ...(data.start_time ? { start_time: data.start_time } : {}),
                    ...(data.end_time ? { end_time: data.end_time } : {}),
                    ...(data.location !== undefined ? { location: data.location } : {}),
                    ...(data.event_owner !== undefined
                        ? { event_owner: data.event_owner }
                        : {}),
                    ...(data.description !== undefined
                        ? { description: data.description }
                        : {}),
                    ...(data.member_ids
                        ? {
                            attendees: data.member_ids.length,
                            members: {
                                set: data.member_ids.map((memberId) => ({ id: memberId })),
                            },
                        }
                        : {}),
                },
                include: this.includeMembers(),
            });
            const { data: parsedEvent } = events_dto_1.eventResponseSchema.safeParse(updatedEvent);
            return {
                data: parsedEvent,
                message: 'Event updated successfully',
                status: common_1.HttpStatus.OK,
                details: null,
            };
        }
        catch (error) {
            config_1.logger.error(`Error in updateEvent: ${String(error)}`);
            if (error instanceof config_1.ErrorResponse) {
                throw error;
            }
            throw (0, utils_1.createGeneralError)(String(error), 'root', common_1.HttpStatus.BAD_REQUEST);
        }
    }
    async deleteEvent(id, owner_id) {
        try {
            const existingEvent = await this.db.events.findUnique({
                where: { id, owner_id },
            });
            if (!existingEvent) {
                throw (0, utils_1.createGeneralError)('Event not found', 'event', common_1.HttpStatus.NOT_FOUND);
            }
            await this.db.events.delete({
                where: { id },
            });
            return {
                data: null,
                message: 'Event deleted successfully',
                status: common_1.HttpStatus.OK,
                details: null,
            };
        }
        catch (error) {
            config_1.logger.error(`Error in deleteEvent: ${String(error)}`);
            if (error instanceof config_1.ErrorResponse) {
                throw error;
            }
            throw (0, utils_1.createGeneralError)(String(error), 'root', common_1.HttpStatus.BAD_REQUEST);
        }
    }
};
exports.EventsService = EventsService;
exports.EventsService = EventsService = __decorate([
    (0, common_1.Injectable)(),
    __metadata("design:paramtypes", [config_1.DatabaseService,
        config_1.UploadService])
], EventsService);
//# sourceMappingURL=events.service.js.map