"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.ProbationService = void 0;
const common_1 = require("@nestjs/common");
const config_1 = require("../../config");
const entities_1 = require("../../config/database/entities");
const utils_1 = require("../../utils");
const notifications_service_1 = require("../notifications/notifications.service");
let ProbationService = class ProbationService {
    constructor(db, notificationsService) {
        this.db = db;
        this.notificationsService = notificationsService;
    }
    async createProbation(data, ownerId) {
        try {
            const member = await this.db.members.findFirst({
                where: { id: data.member_id, owner_id: ownerId },
            });
            if (!member) {
                throw (0, utils_1.createGeneralError)('Member not found', 'general', common_1.HttpStatus.NOT_FOUND);
            }
            const startDate = data.start_date ? new Date(data.start_date) : new Date();
            const months = data.duration_months || 3;
            const calcEnd = new Date(startDate);
            calcEnd.setMonth(calcEnd.getMonth() + months);
            const reviewDue = new Date(calcEnd.getTime() - 7 * 24 * 60 * 60 * 1000);
            const probation = await this.db.probations.create({
                data: {
                    member_id: data.member_id,
                    onboarding_case_id: data.onboarding_case_id || null,
                    start_date: startDate,
                    duration_months: months,
                    calculated_end_date: calcEnd,
                    current_end_date: calcEnd,
                    status: entities_1.ProbationStatusEnum.pending,
                    manager_id: data.manager_id || member.reporting_manager_id || null,
                    review_due_date: reviewDue,
                    notes: data.notes || null,
                    owner_id: ownerId,
                },
            });
            return this.getProbationById(probation.id, ownerId);
        }
        catch (error) {
            config_1.logger.error('Failed to create probation record', error);
            throw error;
        }
    }
    async getProbationsByFilter(query, ownerId) {
        try {
            const page = query.page || 1;
            const limit = query.limit || 10;
            const skip = (page - 1) * limit;
            const where = { owner_id: ownerId };
            if (query.status)
                where.status = query.status;
            if (query.member_id)
                where.member_id = query.member_id;
            const total = await this.db.probations.count({ where });
            const items = await this.db.probations.findMany({
                where,
                include: {
                    member: { include: { department: true, designation: true } },
                    manager: true,
                    reviews: true,
                },
                orderBy: { created_at: 'desc' },
                skip,
                take: limit,
            });
            return {
                data: items,
                pagination: {
                    total,
                    page,
                    limit,
                    totalPages: Math.ceil(total / limit),
                },
            };
        }
        catch (error) {
            config_1.logger.error('Failed to fetch probation records', error);
            throw error;
        }
    }
    async getProbationById(id, ownerId) {
        const probation = await this.db.probations.findFirst({
            where: { id, owner_id: ownerId },
            include: {
                member: { include: { department: true, designation: true, reporting_manager: true } },
                manager: true,
                reviews: true,
            },
        });
        if (!probation) {
            throw (0, utils_1.createGeneralError)('Probation record not found', 'general', common_1.HttpStatus.NOT_FOUND);
        }
        return probation;
    }
    async reviewProbation(id, data, reviewerId, ownerId) {
        const probation = await this.getProbationById(id, ownerId);
        const now = new Date();
        if (data.outcome === entities_1.ProbationOutcomeEnum.pass) {
            await this.db.probations.update({
                where: { id },
                data: {
                    status: entities_1.ProbationStatusEnum.passed,
                    final_outcome: entities_1.ProbationOutcomeEnum.pass,
                    reviewed_at: now,
                    notes: data.comments || probation.notes,
                },
            });
            try {
                await this.notificationsService.sendNotification({
                    owner_id: ownerId,
                    title: 'Probation Passed',
                    message: `Congratulations! ${probation.member?.first_name} ${probation.member?.last_name} has successfully passed probation.`,
                    type: 'RECRUITMENT',
                    member_id: probation.member_id,
                    reference_id: id,
                });
            }
            catch (e) {
                config_1.logger.warn('Failed to send probation pass notification', e);
            }
        }
        else if (data.outcome === entities_1.ProbationOutcomeEnum.extend) {
            const extMonths = data.extension_months || 1;
            const prevEnd = new Date(probation.current_end_date);
            const newEnd = new Date(prevEnd);
            newEnd.setMonth(newEnd.getMonth() + extMonths);
            const reviewDue = new Date(newEnd.getTime() - 7 * 24 * 60 * 60 * 1000);
            await this.db.probation_reviews.create({
                data: {
                    probation_id: id,
                    previous_end_date: prevEnd,
                    extension_months: extMonths,
                    new_end_date: newEnd,
                    review_date: now,
                    reviewer_id: reviewerId,
                    outcome: entities_1.ProbationOutcomeEnum.extend,
                    comments: data.comments || null,
                },
            });
            await this.db.probations.update({
                where: { id },
                data: {
                    status: entities_1.ProbationStatusEnum.extended,
                    current_end_date: newEnd,
                    review_due_date: reviewDue,
                    reviewed_at: now,
                    notes: data.comments || probation.notes,
                },
            });
        }
        else if (data.outcome === entities_1.ProbationOutcomeEnum.fail) {
            await this.db.probations.update({
                where: { id },
                data: {
                    status: entities_1.ProbationStatusEnum.failed,
                    final_outcome: entities_1.ProbationOutcomeEnum.fail,
                    reviewed_at: now,
                    notes: data.comments || probation.notes,
                },
            });
        }
        return this.getProbationById(id, ownerId);
    }
};
exports.ProbationService = ProbationService;
exports.ProbationService = ProbationService = __decorate([
    (0, common_1.Injectable)(),
    __metadata("design:paramtypes", [config_1.DatabaseService,
        notifications_service_1.NotificationsService])
], ProbationService);
//# sourceMappingURL=probation.service.js.map