"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.FeesController = void 0;
const common_1 = require("@nestjs/common");
const platform_express_1 = require("@nestjs/platform-express");
const throttler_1 = require("@nestjs/throttler");
const fees_service_1 = require("./fees.service");
const create_fee_structure_dto_1 = require("./dto/create-fee-structure.dto");
const update_fee_structure_dto_1 = require("./dto/update-fee-structure.dto");
const record_payment_dto_1 = require("./dto/record-payment.dto");
const filter_assignments_dto_1 = require("./dto/filter-assignments.dto");
const verify_fee_payment_dto_1 = require("./dto/verify-fee-payment.dto");
const create_order_dto_1 = require("./dto/create-order.dto");
const duplicate_fee_structure_dto_1 = require("./dto/duplicate-fee-structure.dto");
const apply_discount_dto_1 = require("./dto/apply-discount.dto");
const update_discount_dto_1 = require("./dto/update-discount.dto");
const jwt_auth_guard_1 = require("../common/guards/jwt-auth.guard");
const roles_guard_1 = require("../common/guards/roles.guard");
const roles_decorator_1 = require("../common/decorators/roles.decorator");
const role_enum_1 = require("../common/roles/role.enum");
const current_user_decorator_1 = require("../common/decorators/current-user.decorator");
const public_decorator_1 = require("../common/decorators/public.decorator");
const mongo_id_pipe_1 = require("../common/pipes/mongo-id.pipe");
function verifyReceiptMagic(buf, declaredMime) {
    if (!buf || buf.length < 4)
        return false;
    const b = buf;
    const isJpeg = b[0] === 0xff && b[1] === 0xd8 && b[2] === 0xff;
    const isPng = b[0] === 0x89 && b[1] === 0x50 && b[2] === 0x4e && b[3] === 0x47;
    const isWebp = b.length >= 12 &&
        b[0] === 0x52 && b[1] === 0x49 && b[2] === 0x46 && b[3] === 0x46 &&
        b[8] === 0x57 && b[9] === 0x45 && b[10] === 0x42 && b[11] === 0x50;
    const isPdf = b[0] === 0x25 && b[1] === 0x50 && b[2] === 0x44 && b[3] === 0x46;
    switch (declaredMime) {
        case 'image/jpeg': return isJpeg;
        case 'image/png': return isPng;
        case 'image/webp': return isWebp;
        case 'application/pdf': return isPdf;
        default: return false;
    }
}
let FeesController = class FeesController {
    feesService;
    constructor(feesService) {
        this.feesService = feesService;
    }
    createStructure(dto) {
        return this.feesService.createStructure(dto);
    }
    getStructures(academicYearId, classId, activeOnly, ayHeader) {
        return this.feesService.getStructures(academicYearId ?? ayHeader, classId, activeOnly === 'true');
    }
    duplicateStructure(id, dto) {
        return this.feesService.duplicateStructure(id, dto.targetAcademicYearId);
    }
    getStructure(id) {
        return this.feesService.getStructure(id);
    }
    updateStructure(id, dto) {
        return this.feesService.updateStructure(id, dto);
    }
    deleteStructure(id) {
        return this.feesService.deleteStructure(id);
    }
    regenerateUnpaid(id) {
        return this.feesService.regenerateUnpaidAssignments(id);
    }
    getAssignments(filter, ayHeader) {
        if (!filter.academicYearId && ayHeader)
            filter.academicYearId = ayHeader;
        return this.feesService.getAssignments(filter);
    }
    syncAssignments(structureId, ayHeader) {
        return this.feesService.syncAssignments(structureId, ayHeader);
    }
    applyDiscount(id, dto, adminId) {
        return this.feesService.applyDiscount(id, dto, adminId);
    }
    updateDiscount(id, dto, adminId) {
        return this.feesService.updateDiscount(id, dto, adminId);
    }
    removeDiscount(id) {
        return this.feesService.removeDiscount(id);
    }
    recordOfflinePayment(id, dto, adminId, receipt) {
        if (receipt) {
            if (!receipt.size || receipt.buffer.length === 0) {
                throw new common_1.BadRequestException('Receipt file is empty');
            }
            const allowedMimes = ['image/jpeg', 'image/png', 'image/webp', 'application/pdf'];
            if (!allowedMimes.includes(receipt.mimetype)) {
                throw new common_1.BadRequestException('Receipt must be JPEG, PNG, WebP, or PDF');
            }
            if (receipt.size > 5 * 1024 * 1024) {
                throw new common_1.BadRequestException('Receipt file must not exceed 5MB');
            }
            if (!verifyReceiptMagic(receipt.buffer, receipt.mimetype)) {
                throw new common_1.BadRequestException('Receipt file content does not match its declared type');
            }
        }
        return this.feesService.recordOfflinePayment(id, dto, adminId, receipt);
    }
    getStudentDashboardAdmin(studentId, academicYearId, ayHeader) {
        return this.feesService.getStudentDashboard(studentId, academicYearId ?? ayHeader);
    }
    getMyDashboard(studentId, academicYearId, ayHeader) {
        return this.feesService.getStudentDashboard(studentId, academicYearId ?? ayHeader);
    }
    createOrder(id, studentId, dto) {
        return this.feesService.createRazorpayOrder(id, studentId, dto.amount);
    }
    verifyPayment(id, studentId, body) {
        return this.feesService.verifyRazorpayPayment(id, studentId, body);
    }
    getPaymentHistory(id, userId, role) {
        const studentId = role === role_enum_1.Role.STUDENT ? userId : undefined;
        return this.feesService.getPaymentHistory(id, studentId);
    }
    async verifyReceipt(receipt) {
        if (!receipt || typeof receipt !== 'string' || receipt.length > 50) {
            throw new common_1.BadRequestException('Invalid receipt number');
        }
        const result = await this.feesService.verifyReceipt(receipt.trim());
        if (!result)
            throw new common_1.NotFoundException('Receipt not found');
        return result;
    }
    handleWebhook(req) {
        const signature = req.headers['x-razorpay-signature'];
        if (!req.rawBody) {
            throw new common_1.BadRequestException('Raw body not available — ensure rawBody: true is set in NestJS bootstrap.');
        }
        return this.feesService.handleWebhook(signature, req.rawBody, req.body);
    }
};
exports.FeesController = FeesController;
__decorate([
    (0, common_1.Post)('structures'),
    (0, roles_decorator_1.Roles)(role_enum_1.Role.ADMIN),
    (0, throttler_1.Throttle)({ default: { limit: 10, ttl: 60000 } }),
    __param(0, (0, common_1.Body)()),
    __metadata("design:type", Function),
    __metadata("design:paramtypes", [create_fee_structure_dto_1.CreateFeeStructureDto]),
    __metadata("design:returntype", void 0)
], FeesController.prototype, "createStructure", null);
__decorate([
    (0, common_1.Get)('structures'),
    (0, roles_decorator_1.Roles)(role_enum_1.Role.ADMIN),
    __param(0, (0, common_1.Query)('academicYearId')),
    __param(1, (0, common_1.Query)('classId')),
    __param(2, (0, common_1.Query)('activeOnly')),
    __param(3, (0, common_1.Headers)('x-academic-year-id')),
    __metadata("design:type", Function),
    __metadata("design:paramtypes", [String, String, String, String]),
    __metadata("design:returntype", void 0)
], FeesController.prototype, "getStructures", null);
__decorate([
    (0, common_1.Post)('structures/:id/duplicate'),
    (0, roles_decorator_1.Roles)(role_enum_1.Role.ADMIN),
    (0, throttler_1.Throttle)({ default: { limit: 10, ttl: 60000 } }),
    __param(0, (0, common_1.Param)('id', mongo_id_pipe_1.MongoIdPipe)),
    __param(1, (0, common_1.Body)()),
    __metadata("design:type", Function),
    __metadata("design:paramtypes", [String, duplicate_fee_structure_dto_1.DuplicateFeeStructureDto]),
    __metadata("design:returntype", void 0)
], FeesController.prototype, "duplicateStructure", null);
__decorate([
    (0, common_1.Get)('structures/:id'),
    (0, roles_decorator_1.Roles)(role_enum_1.Role.ADMIN),
    __param(0, (0, common_1.Param)('id', mongo_id_pipe_1.MongoIdPipe)),
    __metadata("design:type", Function),
    __metadata("design:paramtypes", [String]),
    __metadata("design:returntype", void 0)
], FeesController.prototype, "getStructure", null);
__decorate([
    (0, common_1.Put)('structures/:id'),
    (0, roles_decorator_1.Roles)(role_enum_1.Role.ADMIN),
    __param(0, (0, common_1.Param)('id', mongo_id_pipe_1.MongoIdPipe)),
    __param(1, (0, common_1.Body)()),
    __metadata("design:type", Function),
    __metadata("design:paramtypes", [String, update_fee_structure_dto_1.UpdateFeeStructureDto]),
    __metadata("design:returntype", void 0)
], FeesController.prototype, "updateStructure", null);
__decorate([
    (0, common_1.Delete)('structures/:id'),
    (0, roles_decorator_1.Roles)(role_enum_1.Role.ADMIN),
    __param(0, (0, common_1.Param)('id', mongo_id_pipe_1.MongoIdPipe)),
    __metadata("design:type", Function),
    __metadata("design:paramtypes", [String]),
    __metadata("design:returntype", void 0)
], FeesController.prototype, "deleteStructure", null);
__decorate([
    (0, common_1.Post)('structures/:id/regenerate-unpaid'),
    (0, roles_decorator_1.Roles)(role_enum_1.Role.ADMIN),
    (0, throttler_1.Throttle)({ default: { limit: 5, ttl: 60000 } }),
    __param(0, (0, common_1.Param)('id', mongo_id_pipe_1.MongoIdPipe)),
    __metadata("design:type", Function),
    __metadata("design:paramtypes", [String]),
    __metadata("design:returntype", void 0)
], FeesController.prototype, "regenerateUnpaid", null);
__decorate([
    (0, common_1.Get)('assignments'),
    (0, roles_decorator_1.Roles)(role_enum_1.Role.ADMIN),
    __param(0, (0, common_1.Query)()),
    __param(1, (0, common_1.Headers)('x-academic-year-id')),
    __metadata("design:type", Function),
    __metadata("design:paramtypes", [filter_assignments_dto_1.FilterAssignmentsDto, String]),
    __metadata("design:returntype", void 0)
], FeesController.prototype, "getAssignments", null);
__decorate([
    (0, common_1.Post)('sync-assignments'),
    (0, roles_decorator_1.Roles)(role_enum_1.Role.ADMIN),
    (0, throttler_1.Throttle)({ default: { limit: 2, ttl: 60000 } }),
    __param(0, (0, common_1.Query)('structureId')),
    __param(1, (0, common_1.Headers)('x-academic-year-id')),
    __metadata("design:type", Function),
    __metadata("design:paramtypes", [String, String]),
    __metadata("design:returntype", void 0)
], FeesController.prototype, "syncAssignments", null);
__decorate([
    (0, common_1.Post)('assignments/:id/apply-discount'),
    (0, roles_decorator_1.Roles)(role_enum_1.Role.ADMIN),
    (0, throttler_1.Throttle)({ default: { limit: 20, ttl: 60000 } }),
    __param(0, (0, common_1.Param)('id', mongo_id_pipe_1.MongoIdPipe)),
    __param(1, (0, common_1.Body)()),
    __param(2, (0, current_user_decorator_1.CurrentUser)('id')),
    __metadata("design:type", Function),
    __metadata("design:paramtypes", [String, apply_discount_dto_1.ApplyDiscountDto, String]),
    __metadata("design:returntype", void 0)
], FeesController.prototype, "applyDiscount", null);
__decorate([
    (0, common_1.Put)('assignments/:id/update-discount'),
    (0, roles_decorator_1.Roles)(role_enum_1.Role.ADMIN),
    (0, throttler_1.Throttle)({ default: { limit: 20, ttl: 60000 } }),
    __param(0, (0, common_1.Param)('id', mongo_id_pipe_1.MongoIdPipe)),
    __param(1, (0, common_1.Body)()),
    __param(2, (0, current_user_decorator_1.CurrentUser)('id')),
    __metadata("design:type", Function),
    __metadata("design:paramtypes", [String, update_discount_dto_1.UpdateDiscountDto, String]),
    __metadata("design:returntype", void 0)
], FeesController.prototype, "updateDiscount", null);
__decorate([
    (0, common_1.Delete)('assignments/:id/discount'),
    (0, roles_decorator_1.Roles)(role_enum_1.Role.ADMIN),
    (0, throttler_1.Throttle)({ default: { limit: 20, ttl: 60000 } }),
    __param(0, (0, common_1.Param)('id', mongo_id_pipe_1.MongoIdPipe)),
    __metadata("design:type", Function),
    __metadata("design:paramtypes", [String]),
    __metadata("design:returntype", void 0)
], FeesController.prototype, "removeDiscount", null);
__decorate([
    (0, common_1.Post)('assignments/:id/record-payment'),
    (0, roles_decorator_1.Roles)(role_enum_1.Role.ADMIN),
    (0, throttler_1.Throttle)({ default: { limit: 20, ttl: 60000 } }),
    (0, common_1.UseInterceptors)((0, platform_express_1.FileInterceptor)('receipt')),
    __param(0, (0, common_1.Param)('id', mongo_id_pipe_1.MongoIdPipe)),
    __param(1, (0, common_1.Body)()),
    __param(2, (0, current_user_decorator_1.CurrentUser)('id')),
    __param(3, (0, common_1.UploadedFile)()),
    __metadata("design:type", Function),
    __metadata("design:paramtypes", [String, record_payment_dto_1.RecordPaymentDto, String, Object]),
    __metadata("design:returntype", void 0)
], FeesController.prototype, "recordOfflinePayment", null);
__decorate([
    (0, common_1.Get)('student/:studentId/dashboard'),
    (0, roles_decorator_1.Roles)(role_enum_1.Role.ADMIN),
    __param(0, (0, common_1.Param)('studentId', mongo_id_pipe_1.MongoIdPipe)),
    __param(1, (0, common_1.Query)('academicYearId')),
    __param(2, (0, common_1.Headers)('x-academic-year-id')),
    __metadata("design:type", Function),
    __metadata("design:paramtypes", [String, String, String]),
    __metadata("design:returntype", void 0)
], FeesController.prototype, "getStudentDashboardAdmin", null);
__decorate([
    (0, common_1.Get)('my-dashboard'),
    (0, roles_decorator_1.Roles)(role_enum_1.Role.STUDENT),
    __param(0, (0, current_user_decorator_1.CurrentUser)('id')),
    __param(1, (0, common_1.Query)('academicYearId')),
    __param(2, (0, common_1.Headers)('x-academic-year-id')),
    __metadata("design:type", Function),
    __metadata("design:paramtypes", [String, String, String]),
    __metadata("design:returntype", void 0)
], FeesController.prototype, "getMyDashboard", null);
__decorate([
    (0, common_1.Post)('assignments/:id/create-order'),
    (0, roles_decorator_1.Roles)(role_enum_1.Role.STUDENT),
    (0, throttler_1.Throttle)({ default: { limit: 5, ttl: 60000 } }),
    __param(0, (0, common_1.Param)('id', mongo_id_pipe_1.MongoIdPipe)),
    __param(1, (0, current_user_decorator_1.CurrentUser)('id')),
    __param(2, (0, common_1.Body)()),
    __metadata("design:type", Function),
    __metadata("design:paramtypes", [String, String, create_order_dto_1.CreateOrderDto]),
    __metadata("design:returntype", void 0)
], FeesController.prototype, "createOrder", null);
__decorate([
    (0, common_1.Post)('assignments/:id/verify-payment'),
    (0, roles_decorator_1.Roles)(role_enum_1.Role.STUDENT),
    (0, throttler_1.Throttle)({ default: { limit: 10, ttl: 60000 } }),
    __param(0, (0, common_1.Param)('id', mongo_id_pipe_1.MongoIdPipe)),
    __param(1, (0, current_user_decorator_1.CurrentUser)('id')),
    __param(2, (0, common_1.Body)()),
    __metadata("design:type", Function),
    __metadata("design:paramtypes", [String, String, verify_fee_payment_dto_1.VerifyFeePaymentDto]),
    __metadata("design:returntype", void 0)
], FeesController.prototype, "verifyPayment", null);
__decorate([
    (0, common_1.Get)('assignments/:id/payments'),
    (0, roles_decorator_1.Roles)(role_enum_1.Role.ADMIN, role_enum_1.Role.STUDENT),
    __param(0, (0, common_1.Param)('id', mongo_id_pipe_1.MongoIdPipe)),
    __param(1, (0, current_user_decorator_1.CurrentUser)('id')),
    __param(2, (0, current_user_decorator_1.CurrentUser)('role')),
    __metadata("design:type", Function),
    __metadata("design:paramtypes", [String, String, String]),
    __metadata("design:returntype", void 0)
], FeesController.prototype, "getPaymentHistory", null);
__decorate([
    (0, common_1.Get)('verify-receipt'),
    (0, public_decorator_1.Public)(),
    (0, throttler_1.Throttle)({ default: { limit: 10, ttl: 60000 } }),
    __param(0, (0, common_1.Query)('receipt')),
    __metadata("design:type", Function),
    __metadata("design:paramtypes", [String]),
    __metadata("design:returntype", Promise)
], FeesController.prototype, "verifyReceipt", null);
__decorate([
    (0, common_1.Post)('webhook'),
    (0, public_decorator_1.Public)(),
    (0, throttler_1.Throttle)({ default: { limit: 60, ttl: 60000 } }),
    __param(0, (0, common_1.Req)()),
    __metadata("design:type", Function),
    __metadata("design:paramtypes", [Object]),
    __metadata("design:returntype", void 0)
], FeesController.prototype, "handleWebhook", null);
exports.FeesController = FeesController = __decorate([
    (0, common_1.UseGuards)(jwt_auth_guard_1.JwtAuthGuard, roles_guard_1.RolesGuard),
    (0, common_1.Controller)('fees'),
    __metadata("design:paramtypes", [fees_service_1.FeesService])
], FeesController);
//# sourceMappingURL=fees.controller.js.map