"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);
};
var __param = (this && this.__param) || function (paramIndex, decorator) {
    return function (target, key) { decorator(target, key, paramIndex); }
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.DashboardService = void 0;
const common_1 = require("@nestjs/common");
const mongoose_1 = require("@nestjs/mongoose");
const mongoose_2 = require("mongoose");
const student_schema_1 = require("../students/schemas/student.schema");
const teacher_schema_1 = require("../teachers/schemas/teacher.schema");
const class_schema_1 = require("../classes/schemas/class.schema");
const section_schema_1 = require("../sections/schemas/section.schema");
const attendance_schema_1 = require("../attendance/schemas/attendance.schema");
const enrollment_schema_1 = require("../students/schemas/enrollment.schema");
const academic_year_schema_1 = require("../academic-year/academic-year.schema");
let DashboardService = class DashboardService {
    studentModel;
    teacherModel;
    classModel;
    sectionModel;
    academicYearModel;
    attendanceModel;
    enrollmentModel;
    constructor(studentModel, teacherModel, classModel, sectionModel, academicYearModel, attendanceModel, enrollmentModel) {
        this.studentModel = studentModel;
        this.teacherModel = teacherModel;
        this.classModel = classModel;
        this.sectionModel = sectionModel;
        this.academicYearModel = academicYearModel;
        this.attendanceModel = attendanceModel;
        this.enrollmentModel = enrollmentModel;
    }
    async getAdminOverview(academicYearId) {
        const [teachers, classes, sections, activeAY] = await Promise.all([
            this.teacherModel.countDocuments(),
            this.classModel.countDocuments(),
            this.sectionModel.countDocuments(),
            this.academicYearModel.findOne({ isActive: true }).lean(),
        ]);
        if (academicYearId) {
            const totalStudents = await this.enrollmentModel
                .countDocuments({ academicYearId })
                .exec();
            const genderAgg = await this.enrollmentModel
                .aggregate([
                { $match: { academicYearId } },
                {
                    $lookup: {
                        from: 'students',
                        let: { sid: '$studentId' },
                        pipeline: [
                            {
                                $match: {
                                    $expr: { $eq: ['$_id', { $toObjectId: '$$sid' }] },
                                },
                            },
                            { $project: { gender: 1 } },
                        ],
                        as: 'stu',
                    },
                },
                { $unwind: '$stu' },
                {
                    $group: {
                        _id: { $toLower: '$stu.gender' },
                        count: { $sum: 1 },
                    },
                },
            ])
                .exec();
            const gender = { male: 0, female: 0 };
            for (const g of genderAgg) {
                if (g._id === 'male')
                    gender.male = g.count;
                if (g._id === 'female')
                    gender.female = g.count;
            }
            const selectedAY = await this.academicYearModel.findById(academicYearId).lean();
            return {
                scope: { academicYearId },
                totalStudents,
                totalTeachers: teachers,
                totalClasses: classes,
                totalSections: sections,
                activeAcademicYear: selectedAY?.name || activeAY?.name || 'None',
                genderBreakdown: gender,
            };
        }
        const [students, maleCount, femaleCount] = await Promise.all([
            this.studentModel.countDocuments(),
            this.studentModel.countDocuments({ gender: { $regex: /^male$/i } }),
            this.studentModel.countDocuments({ gender: { $regex: /^female$/i } }),
        ]);
        return {
            scope: { academicYearId: null },
            totalStudents: students,
            totalTeachers: teachers,
            totalClasses: classes,
            totalSections: sections,
            activeAcademicYear: activeAY?.name || 'None',
            genderBreakdown: { male: maleCount, female: femaleCount },
        };
    }
    async getTeacherOverview(teacherId, academicYearId) {
        const sections = await this.sectionModel.find({ assignedTeacherId: teacherId }).lean();
        const sectionIdsStr = sections.map((s) => String(s._id));
        const classIdsStr = [...new Set(sections.map((s) => String(s.classId)))].filter(Boolean);
        const classMap = new Map();
        if (classIdsStr.length) {
            const cls = await this.classModel
                .find({ _id: { $in: classIdsStr.map((id) => new mongoose_2.Types.ObjectId(id)) } })
                .lean();
            for (const c of cls)
                classMap.set(String(c._id), c.name);
        }
        if (academicYearId) {
            const total = await this.enrollmentModel.countDocuments({
                academicYearId,
                sectionId: { $in: sectionIdsStr },
            });
            const genderAgg = await this.enrollmentModel
                .aggregate([
                { $match: { academicYearId, sectionId: { $in: sectionIdsStr } } },
                {
                    $lookup: {
                        from: 'students',
                        let: { sid: '$studentId' },
                        pipeline: [
                            { $match: { $expr: { $eq: ['$_id', { $toObjectId: '$$sid' }] } } },
                            { $project: { gender: 1 } },
                        ],
                        as: 'stu',
                    },
                },
                { $unwind: '$stu' },
                { $group: { _id: { $toLower: '$stu.gender' }, count: { $sum: 1 } } },
            ])
                .exec();
            const gender = { male: 0, female: 0 };
            for (const g of genderAgg) {
                if (g._id === 'male')
                    gender.male = g.count;
                if (g._id === 'female')
                    gender.female = g.count;
            }
            return {
                scope: { academicYearId },
                totalAssignedSections: sections.length,
                assignedSections: sections.map((s) => ({
                    sectionId: String(s._id),
                    name: s.name,
                    classId: String(s.classId),
                    className: classMap.get(String(s.classId)) || null,
                })),
                totalStudentsInAssignedSections: total,
                genderBreakdown: gender,
            };
        }
        const [studentCount, maleCount, femaleCount] = await Promise.all([
            this.studentModel.countDocuments({ sectionId: { $in: sectionIdsStr } }),
            this.studentModel.countDocuments({
                sectionId: { $in: sectionIdsStr },
                gender: { $regex: /^male$/i },
            }),
            this.studentModel.countDocuments({
                sectionId: { $in: sectionIdsStr },
                gender: { $regex: /^female$/i },
            }),
        ]);
        return {
            scope: { academicYearId: null },
            totalAssignedSections: sections.length,
            assignedSections: sections.map((s) => ({
                sectionId: String(s._id),
                name: s.name,
                classId: String(s.classId),
                className: classMap.get(String(s.classId)) || null,
            })),
            totalStudentsInAssignedSections: studentCount,
            genderBreakdown: { male: maleCount, female: femaleCount },
        };
    }
    async getStudentOverview(studentId, academicYearId) {
        const student = await this.studentModel.findById(studentId, { password: 0 }).lean();
        if (!student)
            throw new common_1.NotFoundException('Student not found');
        let classId = student.classId;
        let sectionId = student.sectionId;
        let ayId = student.academicYearId;
        if (academicYearId) {
            ayId = academicYearId;
            const enr = await this.enrollmentModel.findOne({ studentId: String(studentId), academicYearId }).lean();
            if (enr) {
                classId = enr.classId;
                sectionId = enr.sectionId;
            }
        }
        const [classData, sectionData, academicYearData] = await Promise.all([
            classId ? this.classModel.findById(classId).lean() : null,
            sectionId ? this.sectionModel.findById(sectionId).lean() : null,
            ayId ? this.academicYearModel.findById(ayId).lean() : null,
        ]);
        const match = { studentId: String(studentId) };
        if (academicYearId)
            match.academicYearId = academicYearId;
        const summaryAgg = await this.attendanceModel
            .aggregate([
            { $match: match },
            { $group: { _id: '$status', count: { $sum: 1 } } },
        ])
            .exec();
        const summary = { present: 0, absent: 0, total: 0 };
        for (const row of summaryAgg) {
            if (row._id === 'present')
                summary.present = row.count;
            if (row._id === 'absent')
                summary.absent = row.count;
        }
        summary.total = summary.present + summary.absent;
        return {
            scope: { academicYearId: academicYearId || null },
            name: student.name,
            email: student.email,
            rollNumber: student.rollNumber,
            gender: student.gender,
            guardianName: student.guardianName,
            phone: student.phone,
            class: classData?.name || 'N/A',
            section: sectionData?.name || 'N/A',
            academicYear: academicYearData?.name || 'N/A',
            attendanceSummary: summary,
        };
    }
};
exports.DashboardService = DashboardService;
exports.DashboardService = DashboardService = __decorate([
    (0, common_1.Injectable)(),
    __param(0, (0, mongoose_1.InjectModel)(student_schema_1.Student.name)),
    __param(1, (0, mongoose_1.InjectModel)(teacher_schema_1.Teacher.name)),
    __param(2, (0, mongoose_1.InjectModel)(class_schema_1.Class.name)),
    __param(3, (0, mongoose_1.InjectModel)(section_schema_1.Section.name)),
    __param(4, (0, mongoose_1.InjectModel)(academic_year_schema_1.AcademicYear.name)),
    __param(5, (0, mongoose_1.InjectModel)(attendance_schema_1.Attendance.name)),
    __param(6, (0, mongoose_1.InjectModel)(enrollment_schema_1.Enrollment.name)),
    __metadata("design:paramtypes", [mongoose_2.Model,
        mongoose_2.Model,
        mongoose_2.Model,
        mongoose_2.Model,
        mongoose_2.Model,
        mongoose_2.Model,
        mongoose_2.Model])
], DashboardService);
//# sourceMappingURL=dashboard.service.js.map