"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.OnboardingService = 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 OnboardingService = class OnboardingService {
    constructor(db, notificationsService) {
        this.db = db;
        this.notificationsService = notificationsService;
    }
    async seedDefaultTemplates(ownerId, force = false) {
        try {
            if (!ownerId)
                return;
            const hasCommon = await this.db.onboarding_templates.findFirst({
                where: { owner_id: ownerId, title: 'Common Onboarding' },
            });
            const hasDefault = await this.db.onboarding_templates.findFirst({
                where: { owner_id: ownerId, is_default: true },
            });
            if (!force && hasCommon && hasDefault)
                return;
            if (force || !hasCommon) {
                const existingTemplates = await this.db.onboarding_templates.findMany({
                    where: { owner_id: ownerId },
                });
                for (const tpl of existingTemplates) {
                    const usedInCases = await this.db.onboarding_cases.count({
                        where: { template_id: tpl.id },
                    });
                    if (usedInCases === 0) {
                        await this.db.onboarding_templates.delete({
                            where: { id: tpl.id },
                        });
                    }
                }
            }
            const templatesToSeed = [
                {
                    title: 'Common Onboarding',
                    description: 'Standard company-wide onboarding process for all new employees.',
                    is_default: true,
                    is_active: true,
                    tasks: [
                        {
                            title: 'Complete Personal Information & Emergency Contacts',
                            description: 'Update profile details in HRMS',
                            owner_type: entities_1.TaskOwnerTypeEnum.employee,
                            priority: 'high',
                            relative_due_days: 2,
                        },
                        {
                            title: 'Sign Non-Disclosure Agreement (NDA) & Employment Contract',
                            description: 'Review and sign official company agreements',
                            owner_type: entities_1.TaskOwnerTypeEnum.employee,
                            priority: 'high',
                            relative_due_days: 3,
                        },
                        {
                            title: 'IT Hardware & Workstation Setup',
                            description: 'Provide laptop, monitor, and company email credentials',
                            owner_type: entities_1.TaskOwnerTypeEnum.it,
                            priority: 'critical',
                            relative_due_days: 1,
                        },
                        {
                            title: 'Manager Welcome & Team Introduction',
                            description: 'Schedule 1-on-1 welcome session and introduce team members',
                            owner_type: entities_1.TaskOwnerTypeEnum.manager,
                            priority: 'medium',
                            relative_due_days: 1,
                        },
                        {
                            title: '30-Day Probation Check-in & Review Survey',
                            description: 'Conduct first 30-day feedback meeting and complete review survey',
                            owner_type: entities_1.TaskOwnerTypeEnum.hr,
                            priority: 'medium',
                            relative_due_days: 30,
                        },
                    ],
                },
                {
                    title: 'Engineering Onboarding',
                    description: 'Technical onboarding process for software engineers and developers.',
                    is_default: false,
                    is_active: true,
                    tasks: [
                        {
                            title: 'Development Environment & Repository Access',
                            description: 'Set up local dev environment, clone repositories, and request GitHub access',
                            owner_type: entities_1.TaskOwnerTypeEnum.it,
                            priority: 'high',
                            relative_due_days: 2,
                        },
                        {
                            title: 'Engineering Architecture & Codebase Overview',
                            description: 'Review system architecture documentation and tech stack overview',
                            owner_type: entities_1.TaskOwnerTypeEnum.manager,
                            priority: 'medium',
                            relative_due_days: 4,
                        },
                        {
                            title: 'Complete First Good First Issue / Pull Request',
                            description: 'Pick a beginner task, create a pull request, and pass code review',
                            owner_type: entities_1.TaskOwnerTypeEnum.employee,
                            priority: 'medium',
                            relative_due_days: 7,
                        },
                        {
                            title: 'CI/CD Pipeline & Deployment Process Walkthrough',
                            description: 'Learn deployment workflows, staging environments, and monitoring tools',
                            owner_type: entities_1.TaskOwnerTypeEnum.it,
                            priority: 'medium',
                            relative_due_days: 10,
                        },
                    ],
                },
                {
                    title: 'UI/UX Design Onboarding',
                    description: 'Design onboarding workflow for Product Designers, UI/UX, and Graphics team.',
                    is_default: false,
                    is_active: true,
                    tasks: [
                        {
                            title: 'Figma Workspace & Design Tools Access',
                            description: 'Grant access to Figma organization, Adobe Creative Cloud, and Font licenses',
                            owner_type: entities_1.TaskOwnerTypeEnum.it,
                            priority: 'high',
                            relative_due_days: 1,
                        },
                        {
                            title: 'Brand Style Guide & Design System Review',
                            description: 'Study existing UI component library, design tokens, and accessibility standards',
                            owner_type: entities_1.TaskOwnerTypeEnum.employee,
                            priority: 'medium',
                            relative_due_days: 3,
                        },
                        {
                            title: 'First UX Research & Design Component Task',
                            description: 'Collaborate with Product Manager to deliver first design asset / wireframe',
                            owner_type: entities_1.TaskOwnerTypeEnum.employee,
                            priority: 'medium',
                            relative_due_days: 7,
                        },
                    ],
                },
                {
                    title: 'Marketing Onboarding',
                    description: 'Onboarding process for Marketing Specialists, Content Creators, and SEO Leads.',
                    is_default: false,
                    is_active: true,
                    tasks: [
                        {
                            title: 'Marketing Tools & Analytics Platform Access',
                            description: 'Grant access to Google Analytics, HubSpot, Social Accounts, and CRM',
                            owner_type: entities_1.TaskOwnerTypeEnum.it,
                            priority: 'high',
                            relative_due_days: 2,
                        },
                        {
                            title: 'Brand Strategy & Content Calendar Review',
                            description: 'Review target personas, content roadmap, and quarterly marketing KPIs',
                            owner_type: entities_1.TaskOwnerTypeEnum.manager,
                            priority: 'medium',
                            relative_due_days: 4,
                        },
                        {
                            title: 'First Campaign Launch & Copywriting Task',
                            description: 'Draft and publish first social media / newsletter campaign',
                            owner_type: entities_1.TaskOwnerTypeEnum.employee,
                            priority: 'medium',
                            relative_due_days: 7,
                        },
                    ],
                },
            ];
            for (const tplData of templatesToSeed) {
                const { tasks, ...templateFields } = tplData;
                const template = await this.db.onboarding_templates.create({
                    data: {
                        ...templateFields,
                        owner_id: ownerId,
                    },
                });
                if (tasks && tasks.length > 0) {
                    for (let i = 0; i < tasks.length; i++) {
                        const t = tasks[i];
                        await this.db.onboarding_template_tasks.create({
                            data: {
                                template_id: template.id,
                                title: t.title,
                                description: t.description,
                                owner_type: t.owner_type,
                                priority: t.priority,
                                relative_due_days: t.relative_due_days,
                                order_index: i,
                            },
                        });
                    }
                }
            }
        }
        catch (error) {
            config_1.logger.error('Failed to seed default onboarding templates', error);
        }
    }
    async resetDefaultTemplates(ownerId) {
        await this.seedDefaultTemplates(ownerId, true);
        return this.getTemplates(ownerId);
    }
    async createTemplate(data, ownerId) {
        try {
            if (data.is_default) {
                await this.db.onboarding_templates.updateMany({
                    where: { owner_id: ownerId },
                    data: { is_default: false },
                });
            }
            const template = await this.db.onboarding_templates.create({
                data: {
                    title: data.title,
                    description: data.description,
                    is_active: data.is_active ?? true,
                    is_default: data.is_default ?? false,
                    owner_id: ownerId,
                },
            });
            if (data.tasks && data.tasks.length > 0) {
                for (let i = 0; i < data.tasks.length; i++) {
                    const t = data.tasks[i];
                    await this.db.onboarding_template_tasks.create({
                        data: {
                            template_id: template.id,
                            title: t.title,
                            description: t.description,
                            owner_type: t.owner_type,
                            priority: t.priority,
                            relative_due_days: t.relative_due_days,
                            order_index: t.order_index ?? i,
                        },
                    });
                }
            }
            return this.getTemplateById(template.id, ownerId);
        }
        catch (error) {
            config_1.logger.error('Failed to create onboarding template', error);
            throw error;
        }
    }
    async getTemplates(ownerId) {
        try {
            await this.seedDefaultTemplates(ownerId);
            return await this.db.onboarding_templates.findMany({
                where: { owner_id: ownerId },
                include: { tasks: true },
                orderBy: { is_default: 'desc', created_at: 'desc' },
            });
        }
        catch (error) {
            config_1.logger.error('Failed to fetch onboarding templates', error);
            throw error;
        }
    }
    async getDefaultTemplate(ownerId) {
        await this.seedDefaultTemplates(ownerId);
        let template = await this.db.onboarding_templates.findFirst({
            where: { owner_id: ownerId, is_default: true, is_active: true },
            include: { tasks: true },
        });
        if (!template) {
            template = await this.db.onboarding_templates.findFirst({
                where: { owner_id: ownerId, is_active: true },
                include: { tasks: true },
                orderBy: { created_at: 'asc' },
            });
        }
        return template;
    }
    async setDefaultTemplate(id, ownerId) {
        await this.getTemplateById(id, ownerId);
        await this.db.onboarding_templates.updateMany({
            where: { owner_id: ownerId },
            data: { is_default: false },
        });
        await this.db.onboarding_templates.update({
            where: { id, owner_id: ownerId },
            data: { is_default: true },
        });
        return this.getTemplateById(id, ownerId);
    }
    async getTemplateById(id, ownerId) {
        const template = await this.db.onboarding_templates.findFirst({
            where: { id, owner_id: ownerId },
            include: { tasks: true },
        });
        if (!template) {
            throw (0, utils_1.createGeneralError)('Onboarding template not found', 'general', common_1.HttpStatus.NOT_FOUND);
        }
        return template;
    }
    async updateTemplate(id, data, ownerId) {
        await this.getTemplateById(id, ownerId);
        if (data.is_default) {
            await this.db.onboarding_templates.updateMany({
                where: { owner_id: ownerId },
                data: { is_default: false },
            });
        }
        const { tasks, ...templateData } = data;
        await this.db.onboarding_templates.update({
            where: { id, owner_id: ownerId },
            data: templateData,
        });
        return this.getTemplateById(id, ownerId);
    }
    async deleteTemplate(id, ownerId) {
        await this.getTemplateById(id, ownerId);
        await this.db.onboarding_templates.delete({ where: { id } });
        return { message: 'Template deleted successfully' };
    }
    async createCase(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 existingCase = await this.db.onboarding_cases.findFirst({
                where: {
                    member_id: data.member_id,
                    status: entities_1.OnboardingCaseStatusEnum.in_progress,
                },
            });
            if (existingCase) {
                throw (0, utils_1.createGeneralError)('Active onboarding case already exists for this member', 'general', common_1.HttpStatus.CONFLICT);
            }
            const startDate = data.start_date
                ? new Date(data.start_date)
                : new Date();
            const targetDate = data.target_completion_date
                ? new Date(data.target_completion_date)
                : new Date(startDate.getTime() + 30 * 24 * 60 * 60 * 1000);
            const onboardingCase = await this.db.runInTransaction(async (manager) => {
                const caseRepo = manager.getRepository('onboarding_cases');
                const taskRepo = manager.getRepository('onboarding_tasks');
                const docRepo = manager.getRepository('onboarding_documents');
                const provRepo = manager.getRepository('provisioning_items');
                const surveyRepo = manager.getRepository('onboarding_surveys');
                const probationRepo = manager.getRepository('probations');
                const newCase = caseRepo.create({
                    member_id: data.member_id,
                    job_application_id: data.job_application_id || null,
                    template_id: data.template_id || null,
                    status: entities_1.OnboardingCaseStatusEnum.in_progress,
                    start_date: startDate,
                    target_completion_date: targetDate,
                    notes: data.notes || null,
                    owner_id: ownerId,
                });
                const savedCase = await caseRepo.save(newCase);
                const caseId = savedCase.id;
                let tasksToInsert = [];
                if (data.template_id) {
                    const tpl = await this.db.onboarding_templates.findFirst({
                        where: { id: data.template_id, owner_id: ownerId },
                        include: { tasks: true },
                    });
                    if (tpl && tpl.tasks && tpl.tasks.length > 0) {
                        tasksToInsert = tpl.tasks.map((t, idx) => ({
                            onboarding_case_id: caseId,
                            title: t.title,
                            description: t.description,
                            owner_type: t.owner_type,
                            due_date: new Date(startDate.getTime() +
                                (t.relative_due_days || 7) * 24 * 60 * 60 * 1000),
                            priority: t.priority,
                            status: entities_1.TaskStatusEnum.pending,
                            order_index: t.order_index ?? idx,
                        }));
                    }
                }
                if (tasksToInsert.length === 0) {
                    tasksToInsert = [
                        {
                            onboarding_case_id: caseId,
                            title: 'Complete Personal Information & Emergency Contacts',
                            description: 'Update profile details in HRMS',
                            owner_type: entities_1.TaskOwnerTypeEnum.employee,
                            due_date: new Date(startDate.getTime() + 2 * 24 * 60 * 60 * 1000),
                            priority: 'high',
                            status: entities_1.TaskStatusEnum.pending,
                            order_index: 0,
                        },
                        {
                            onboarding_case_id: caseId,
                            title: 'Sign Non-Disclosure Agreement (NDA)',
                            description: 'Review and sign company NDA',
                            owner_type: entities_1.TaskOwnerTypeEnum.employee,
                            due_date: new Date(startDate.getTime() + 3 * 24 * 60 * 60 * 1000),
                            priority: 'high',
                            status: entities_1.TaskStatusEnum.pending,
                            order_index: 1,
                        },
                        {
                            onboarding_case_id: caseId,
                            title: 'IT Hardware & Workstation Setup',
                            description: 'Provide laptop, monitor, and company credentials',
                            owner_type: entities_1.TaskOwnerTypeEnum.it,
                            due_date: new Date(startDate.getTime() + 1 * 24 * 60 * 60 * 1000),
                            priority: 'critical',
                            status: entities_1.TaskStatusEnum.pending,
                            order_index: 2,
                        },
                        {
                            onboarding_case_id: caseId,
                            title: 'Manager Welcome & Team Introduction',
                            description: '1-on-1 meeting and introduction to team workflows',
                            owner_type: entities_1.TaskOwnerTypeEnum.manager,
                            due_date: new Date(startDate.getTime() + 5 * 24 * 60 * 60 * 1000),
                            priority: 'medium',
                            status: entities_1.TaskStatusEnum.pending,
                            order_index: 3,
                        },
                    ];
                }
                await taskRepo.save(taskRepo.create(tasksToInsert));
                const docsToInsert = [
                    {
                        onboarding_case_id: caseId,
                        title: 'Non-Disclosure Agreement (NDA)',
                        document_type: 'nda',
                        is_required: true,
                        status: entities_1.DocumentSigningStatusEnum.pending,
                    },
                    {
                        onboarding_case_id: caseId,
                        title: 'Employment Contract',
                        document_type: 'contract',
                        is_required: true,
                        status: entities_1.DocumentSigningStatusEnum.pending,
                    },
                    {
                        onboarding_case_id: caseId,
                        title: 'Code of Ethics & Conduct Policy',
                        document_type: 'policy',
                        is_required: true,
                        status: entities_1.DocumentSigningStatusEnum.pending,
                    },
                ];
                await docRepo.save(docRepo.create(docsToInsert));
                const provToInsert = [
                    {
                        onboarding_case_id: caseId,
                        item_name: 'Workplace Laptop / Workstation',
                        item_type: 'hardware',
                        description: 'Primary work computer',
                        owner_type: entities_1.TaskOwnerTypeEnum.it,
                        status: entities_1.ProvisioningStatusEnum.pending,
                    },
                    {
                        onboarding_case_id: caseId,
                        item_name: 'Company Email & SSO Account',
                        item_type: 'access',
                        description: 'Work email address & active directory account',
                        owner_type: entities_1.TaskOwnerTypeEnum.it,
                        status: entities_1.ProvisioningStatusEnum.pending,
                    },
                    {
                        onboarding_case_id: caseId,
                        item_name: 'Employee ID Card & Building Pass',
                        item_type: 'access',
                        description: 'Physical access card',
                        owner_type: entities_1.TaskOwnerTypeEnum.hr,
                        status: entities_1.ProvisioningStatusEnum.pending,
                    },
                ];
                await provRepo.save(provRepo.create(provToInsert));
                const surveysToInsert = [30, 60, 90].map((days) => ({
                    onboarding_case_id: caseId,
                    member_id: data.member_id,
                    title: `${days}-Day Onboarding Check-in Survey`,
                    interval_days: days,
                    status: 'scheduled',
                }));
                await surveyRepo.save(surveyRepo.create(surveysToInsert));
                const calcEnd = new Date(startDate);
                calcEnd.setMonth(calcEnd.getMonth() + 3);
                const probationRecord = probationRepo.create({
                    member_id: data.member_id,
                    onboarding_case_id: caseId,
                    start_date: startDate,
                    duration_months: 3,
                    calculated_end_date: calcEnd,
                    current_end_date: calcEnd,
                    status: entities_1.ProbationStatusEnum.pending,
                    manager_id: member.reporting_manager_id || null,
                    review_due_date: new Date(calcEnd.getTime() - 7 * 24 * 60 * 60 * 1000),
                    owner_id: ownerId,
                });
                await probationRepo.save(probationRecord);
                return savedCase;
            });
            try {
                await this.notificationsService.sendNotification({
                    owner_id: ownerId,
                    title: 'Onboarding Initiated',
                    message: `Onboarding process started for ${member.first_name} ${member.last_name}`,
                    type: 'RECRUITMENT',
                    member_id: data.member_id,
                    reference_id: onboardingCase.id,
                });
            }
            catch (err) {
                config_1.logger.warn('Failed to send onboarding notification', err);
            }
            return this.getCaseById(onboardingCase.id, ownerId);
        }
        catch (error) {
            config_1.logger.error('Failed to create onboarding case', error);
            throw error;
        }
    }
    async getCasesByFilter(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;
            }
            console.log(where);
            const total = await this.db.onboarding_cases.count({ where });
            const items = await this.db.onboarding_cases.findMany({
                where,
                include: {
                    member: {
                        include: { department: true, designation: true },
                    },
                    tasks: true,
                    documents: true,
                    provisioning_items: true,
                    buddies: { include: { buddy_member: true } },
                },
                orderBy: { created_at: 'desc' },
                skip,
                take: limit,
            });
            const formattedItems = items.map((c) => {
                const totalTasks = c.tasks?.length || 0;
                const completedTasks = (c.tasks || []).filter((t) => t.status === entities_1.TaskStatusEnum.completed || t.status === 'completed').length;
                const completion_percentage = totalTasks > 0 ? Math.round((completedTasks / totalTasks) * 100) : 0;
                return {
                    ...c,
                    total_tasks: totalTasks,
                    completed_tasks: completedTasks,
                    completion_percentage,
                };
            });
            return {
                data: formattedItems,
                pagination: {
                    total,
                    page,
                    limit,
                    totalPages: Math.ceil(total / limit),
                },
            };
        }
        catch (error) {
            config_1.logger.error('Failed to fetch onboarding cases', error);
            throw error;
        }
    }
    async getCaseById(id, ownerId) {
        const onboardingCase = await this.db.onboarding_cases.findFirst({
            where: { id, owner_id: ownerId },
            include: {
                member: {
                    include: {
                        department: true,
                        designation: true,
                        reporting_manager: true,
                    },
                },
                tasks: { include: { assigned_member: true } },
                documents: true,
                provisioning_items: true,
                buddies: { include: { buddy_member: true } },
                surveys: true,
            },
        });
        if (!onboardingCase) {
            throw (0, utils_1.createGeneralError)('Onboarding case not found', 'general', common_1.HttpStatus.NOT_FOUND);
        }
        return onboardingCase;
    }
    async updateCase(id, data, ownerId) {
        const currentCase = await this.getCaseById(id, ownerId);
        const updatePayload = { ...data };
        if (data.status === entities_1.OnboardingCaseStatusEnum.completed &&
            currentCase.status !== entities_1.OnboardingCaseStatusEnum.completed) {
            const unsignedRequiredDocs = (currentCase.documents || []).filter((doc) => doc.is_required && doc.status !== entities_1.DocumentSigningStatusEnum.signed);
            if (unsignedRequiredDocs.length > 0) {
                throw (0, utils_1.createGeneralError)(`Cannot complete onboarding because ${unsignedRequiredDocs.length} required document(s) are unsigned`, 'general', common_1.HttpStatus.BAD_REQUEST);
            }
            updatePayload.completed_at = new Date();
            if (currentCase.member_id) {
                await this.db.members.update({
                    where: { id: currentCase.member_id },
                    data: {
                        status: 'active',
                        role: 'member',
                        date_of_joining: currentCase.member?.date_of_joining || new Date(),
                    },
                });
            }
        }
        await this.db.onboarding_cases.update({
            where: { id },
            data: updatePayload,
        });
        return this.getCaseById(id, ownerId);
    }
    async deleteCase(id, ownerId) {
        await this.getCaseById(id, ownerId);
        await this.db.onboarding_cases.delete({ where: { id } });
        return { message: 'Onboarding case deleted successfully' };
    }
    async addTask(caseId, data, ownerId) {
        await this.getCaseById(caseId, ownerId);
        const task = await this.db.onboarding_tasks.create({
            data: {
                onboarding_case_id: caseId,
                title: data.title,
                description: data.description,
                owner_type: data.owner_type,
                assigned_member_id: data.assigned_member_id || null,
                due_date: data.due_date ? new Date(data.due_date) : null,
                priority: data.priority,
                status: entities_1.TaskStatusEnum.pending,
                order_index: data.order_index ?? 0,
                notes: data.notes || null,
            },
        });
        return task;
    }
    async updateTask(taskId, data, ownerId, currentMemberId) {
        const task = await this.db.onboarding_tasks.findFirst({
            where: { id: taskId },
            include: { onboarding_case: true },
        });
        if (!task || task.onboarding_case.owner_id !== ownerId) {
            throw (0, utils_1.createGeneralError)('Onboarding task not found', 'general', common_1.HttpStatus.NOT_FOUND);
        }
        const updatePayload = { ...data };
        if (data.status === entities_1.TaskStatusEnum.completed &&
            task.status !== entities_1.TaskStatusEnum.completed) {
            updatePayload.completed_at = new Date();
            updatePayload.completed_by_id = currentMemberId || null;
        }
        await this.db.onboarding_tasks.update({
            where: { id: taskId },
            data: updatePayload,
        });
        return this.db.onboarding_tasks.findFirst({ where: { id: taskId } });
    }
    async signDocument(documentId, data, memberId, ownerId) {
        const document = await this.db.onboarding_documents.findFirst({
            where: { id: documentId },
            include: { onboarding_case: true },
        });
        if (!document || document.onboarding_case.owner_id !== ownerId) {
            throw (0, utils_1.createGeneralError)('Document assignment not found', 'general', common_1.HttpStatus.NOT_FOUND);
        }
        if (document.status === entities_1.DocumentSigningStatusEnum.signed) {
            throw (0, utils_1.createGeneralError)('Document is already signed and locked', 'general', common_1.HttpStatus.BAD_REQUEST);
        }
        const signedAt = new Date();
        const metadata = {
            signed_at: signedAt,
            signed_by_id: memberId,
            ...(data.signature_metadata || {}),
        };
        await this.db.onboarding_documents.update({
            where: { id: documentId },
            data: {
                status: entities_1.DocumentSigningStatusEnum.signed,
                signed_at: signedAt,
                signed_by_id: memberId,
                file_url: data.file_url || document.file_url,
                signature_metadata: metadata,
                notes: data.notes || document.notes,
            },
        });
        return this.db.onboarding_documents.findFirst({
            where: { id: documentId },
        });
    }
    async addProvisioningItem(caseId, data, ownerId) {
        await this.getCaseById(caseId, ownerId);
        return await this.db.provisioning_items.create({
            data: {
                onboarding_case_id: caseId,
                item_name: data.item_name,
                item_type: data.item_type,
                description: data.description,
                owner_type: data.owner_type,
                assigned_member_id: data.assigned_member_id || null,
                serial_number: data.serial_number || null,
                status: entities_1.ProvisioningStatusEnum.pending,
                notes: data.notes || null,
            },
        });
    }
    async updateProvisioningItem(itemId, data, ownerId) {
        const item = await this.db.provisioning_items.findFirst({
            where: { id: itemId },
            include: { onboarding_case: true },
        });
        if (!item || item.onboarding_case.owner_id !== ownerId) {
            throw (0, utils_1.createGeneralError)('Provisioning item not found', 'general', common_1.HttpStatus.NOT_FOUND);
        }
        const updatePayload = {
            status: data.status,
            notes: data.notes || item.notes,
        };
        if (data.serial_number)
            updatePayload.serial_number = data.serial_number;
        if (data.status === entities_1.ProvisioningStatusEnum.provisioned &&
            !item.provisioned_at) {
            updatePayload.provisioned_at = new Date();
        }
        if (data.status === entities_1.ProvisioningStatusEnum.confirmed &&
            !item.confirmed_at) {
            updatePayload.confirmed_at = new Date();
        }
        await this.db.provisioning_items.update({
            where: { id: itemId },
            data: updatePayload,
        });
        return this.db.provisioning_items.findFirst({ where: { id: itemId } });
    }
    async assignBuddy(caseId, data, assignedById, ownerId) {
        const onboardingCase = await this.getCaseById(caseId, ownerId);
        if (onboardingCase.member_id === data.buddy_member_id) {
            throw (0, utils_1.createGeneralError)('An employee cannot be assigned as their own buddy', 'general', common_1.HttpStatus.BAD_REQUEST);
        }
        const buddyMember = await this.db.members.findFirst({
            where: { id: data.buddy_member_id, owner_id: ownerId },
        });
        if (!buddyMember) {
            throw (0, utils_1.createGeneralError)('Buddy employee not found', 'general', common_1.HttpStatus.NOT_FOUND);
        }
        await this.db.buddy_assignments.update({
            where: { onboarding_case_id: caseId, status: 'active' },
            data: { status: 'replaced', end_date: new Date() },
        });
        const assignment = await this.db.buddy_assignments.create({
            data: {
                onboarding_case_id: caseId,
                member_id: onboardingCase.member_id,
                buddy_member_id: data.buddy_member_id,
                assigned_by_id: assignedById,
                start_date: data.start_date ? new Date(data.start_date) : new Date(),
                end_date: data.end_date ? new Date(data.end_date) : null,
                status: 'active',
                notes: data.notes || null,
            },
        });
        return assignment;
    }
    async getMyWelcomePortal(memberId, ownerId) {
        let onboardingCase = await this.db.onboarding_cases.findFirst({
            where: { member_id: memberId, owner_id: ownerId },
            include: {
                member: {
                    include: {
                        department: true,
                        designation: true,
                        reporting_manager: true,
                    },
                },
                tasks: true,
                documents: true,
                provisioning_items: true,
                buddies: {
                    include: { buddy_member: true },
                    where: { status: 'active' },
                },
            },
        });
        if (!onboardingCase) {
            onboardingCase = await this.db.onboarding_cases.findFirst({
                where: { owner_id: ownerId },
                orderBy: { created_at: 'desc' },
                include: {
                    member: {
                        include: {
                            department: true,
                            designation: true,
                            reporting_manager: true,
                        },
                    },
                    tasks: true,
                    documents: true,
                    provisioning_items: true,
                    buddies: {
                        include: { buddy_member: true },
                        where: { status: 'active' },
                    },
                },
            });
        }
        if (!onboardingCase) {
            return null;
        }
        let teamMembers = [];
        if (onboardingCase.member?.department_id) {
            teamMembers = await this.db.members.findMany({
                where: {
                    department_id: onboardingCase.member.department_id,
                    owner_id: ownerId,
                    status: 'active',
                },
                take: 10,
            });
        }
        return {
            onboarding_case: onboardingCase,
            tasks: onboardingCase.tasks || [],
            documents: onboardingCase.documents || [],
            provisioning: onboardingCase.provisioning_items || [],
            manager: onboardingCase.member?.reporting_manager || null,
            buddy: onboardingCase.buddies?.[0]?.buddy_member || null,
            team_members: teamMembers.filter((m) => m.id !== memberId),
            welcome_message: `Welcome to the team, ${onboardingCase.member?.first_name || 'New Hire'}! We are thrilled to have you join us.`,
        };
    }
    async getDashboardStats(ownerId) {
        const activeCases = await this.db.onboarding_cases.count({
            where: {
                owner_id: ownerId,
                status: entities_1.OnboardingCaseStatusEnum.in_progress,
            },
        });
        const completedCases = await this.db.onboarding_cases.count({
            where: { owner_id: ownerId, status: entities_1.OnboardingCaseStatusEnum.completed },
        });
        const pendingDocs = await this.db.onboarding_documents.count({
            where: { status: entities_1.DocumentSigningStatusEnum.pending },
        });
        const pendingProvisioning = await this.db.provisioning_items.count({
            where: { status: entities_1.ProvisioningStatusEnum.pending },
        });
        return {
            active_cases: activeCases,
            completed_cases: completedCases,
            pending_documents: pendingDocs,
            pending_provisioning: pendingProvisioning,
        };
    }
};
exports.OnboardingService = OnboardingService;
exports.OnboardingService = OnboardingService = __decorate([
    (0, common_1.Injectable)(),
    __metadata("design:paramtypes", [config_1.DatabaseService,
        notifications_service_1.NotificationsService])
], OnboardingService);
//# sourceMappingURL=onboarding.service.js.map