"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); }
};
var ReportsService_1;
Object.defineProperty(exports, "__esModule", { value: true });
exports.ReportsService = void 0;
const common_1 = require("@nestjs/common");
const typeorm_1 = require("@nestjs/typeorm");
const typeorm_2 = require("typeorm");
const payment_entity_1 = require("../database/entities/payment.entity");
const wifi_session_entity_1 = require("../database/entities/wifi-session.entity");
const customer_entity_1 = require("../database/entities/customer.entity");
const package_entity_1 = require("../database/entities/package.entity");
const router_entity_1 = require("../database/entities/router.entity");
const business_entity_1 = require("../database/entities/business.entity");
const transaction_entity_1 = require("../database/entities/transaction.entity");
const commission_entity_1 = require("../database/entities/commission.entity");
const report_filter_dto_1 = require("./dto/report-filter.dto");
const sync_1 = require("csv-stringify/sync");
const PDFKit = require("pdfkit");
let ReportsService = ReportsService_1 = class ReportsService {
    constructor(paymentRepo, wifiSessionRepo, customerRepo, packageRepo, routerRepo, businessRepo, transactionRepo, commissionRepo, dataSource) {
        this.paymentRepo = paymentRepo;
        this.wifiSessionRepo = wifiSessionRepo;
        this.customerRepo = customerRepo;
        this.packageRepo = packageRepo;
        this.routerRepo = routerRepo;
        this.businessRepo = businessRepo;
        this.transactionRepo = transactionRepo;
        this.commissionRepo = commissionRepo;
        this.dataSource = dataSource;
        this.logger = new common_1.Logger(ReportsService_1.name);
        const dbType = (process.env.DB_TYPE || dataSource.options?.type || 'mysql').toString().toLowerCase();
        this.isPostgres = dbType.includes('postgres') || dbType.includes('pg');
    }
    getTruncExpr(alias, field, groupBy) {
        const col = `${alias}.${field}`;
        switch (groupBy) {
            case report_filter_dto_1.GroupBy.WEEKLY:
                return this.isPostgres ? `DATE_TRUNC('week', ${col})` : `DATE_FORMAT(${col}, '%Y-%u-1')`;
            case report_filter_dto_1.GroupBy.MONTHLY:
                return this.isPostgres ? `DATE_TRUNC('month', ${col})` : `DATE_FORMAT(${col}, '%Y-%m-01')`;
            case report_filter_dto_1.GroupBy.YEARLY:
                return this.isPostgres ? `DATE_TRUNC('year', ${col})` : `DATE_FORMAT(${col}, '%Y-01-01')`;
            default:
                return this.isPostgres ? `DATE_TRUNC('day', ${col})` : `DATE(${col})`;
        }
    }
    castNumeric(expr) {
        return this.isPostgres ? `${expr}::numeric` : expr;
    }
    castInt(expr) {
        return this.isPostgres ? `${expr}::int` : expr;
    }
    buildBaseQuery(businessId, filters) {
        const { startDate, endDate } = filters;
        return {
            businessId,
            startDate: new Date(startDate),
            endDate: new Date(endDate),
        };
    }
    async getRevenueReport(businessId, filters) {
        const { groupBy = report_filter_dto_1.GroupBy.DAILY } = filters;
        const truncExpr = this.getTruncExpr('payment', 'createdAt', groupBy);
        const query = this.paymentRepo
            .createQueryBuilder('payment')
            .select([
            `${truncExpr} AS period`,
            'COUNT(payment.id) AS totalTransactions',
            `${this.castNumeric('SUM(payment.amount)')} AS totalRevenue`,
            `${this.castNumeric('AVG(payment.amount)')} AS averageTransaction`,
        ])
            .where('payment.businessId = :businessId', { businessId })
            .andWhere('payment.status = :status', { status: payment_entity_1.PaymentStatus.SUCCESSFUL })
            .andWhere('payment.createdAt BETWEEN :startDate AND :endDate', {
            startDate: new Date(filters.startDate),
            endDate: new Date(filters.endDate),
        })
            .groupBy('period')
            .orderBy('period', 'ASC');
        const rows = await query.getRawMany();
        const totals = rows.reduce((acc, row) => ({
            totalRevenue: acc.totalRevenue + Number(row.totalRevenue || 0),
            totalTransactions: acc.totalTransactions + Number(row.totalTransactions || 0),
        }), { totalRevenue: 0, totalTransactions: 0 });
        const previousStart = new Date(filters.startDate);
        const previousEnd = new Date(filters.endDate);
        const diffMs = previousEnd.getTime() - previousStart.getTime();
        previousStart.setTime(previousStart.getTime() - diffMs);
        previousEnd.setTime(previousEnd.getTime() - diffMs);
        const previousQuery = this.paymentRepo
            .createQueryBuilder('payment')
            .select(`${this.castNumeric('SUM(payment.amount)')}`, 'prevRevenue')
            .where('payment.businessId = :businessId', { businessId })
            .andWhere('payment.status = :status', { status: payment_entity_1.PaymentStatus.SUCCESSFUL })
            .andWhere('payment.createdAt BETWEEN :prevStart AND :prevEnd', {
            prevStart: previousStart,
            prevEnd: previousEnd,
        });
        const prevResult = await previousQuery.getRawOne();
        const prevRevenue = Number(prevResult?.prevRevenue || 0);
        const trend = totals.totalRevenue > 0 && prevRevenue > 0
            ? ((totals.totalRevenue - prevRevenue) / prevRevenue) * 100
            : 0;
        return {
            data: rows,
            totals,
            trend: Math.round(trend * 100) / 100,
            groupBy,
        };
    }
    async getPackageSalesReport(businessId, filters) {
        const { packageId } = filters;
        const query = this.paymentRepo
            .createQueryBuilder('payment')
            .leftJoin('payment.package', 'pkg')
            .select([
            'pkg.id AS "packageId"',
            'pkg.name AS "packageName"',
            `${this.castInt('COUNT(payment.id)')} AS "saleCount"`,
            `${this.castNumeric('SUM(payment.amount)')} AS "totalRevenue"`,
        ])
            .where('payment.businessId = :businessId', { businessId })
            .andWhere('payment.status = :status', { status: payment_entity_1.PaymentStatus.SUCCESSFUL })
            .andWhere('payment.createdAt BETWEEN :startDate AND :endDate', {
            startDate: new Date(filters.startDate),
            endDate: new Date(filters.endDate),
        });
        if (packageId) {
            query.andWhere('pkg.id = :packageId', { packageId });
        }
        query.groupBy('pkg.id, pkg.name').orderBy('totalRevenue', 'DESC');
        const rows = await query.getRawMany();
        const totals = rows.reduce((acc, row) => ({
            totalRevenue: acc.totalRevenue + Number(row.totalRevenue || 0),
            totalSales: acc.totalSales + Number(row.saleCount || 0),
        }), { totalRevenue: 0, totalSales: 0 });
        return { data: rows, totals };
    }
    async getRouterReport(businessId, filters) {
        const { routerId } = filters;
        const sessionQuery = this.wifiSessionRepo
            .createQueryBuilder('session')
            .leftJoin('session.router', 'router')
            .select([
            'router.id AS "routerId"',
            'router.name AS "routerName"',
            `${this.castInt('COUNT(session.id)')} AS "totalSessions"`,
            `${this.castNumeric('SUM(session.dataUsedMb)')} AS "totalDataUsedMb"`,
        ])
            .where('session.businessId = :businessId', { businessId })
            .andWhere('session.createdAt BETWEEN :startDate AND :endDate', {
            startDate: new Date(filters.startDate),
            endDate: new Date(filters.endDate),
        });
        if (routerId) {
            sessionQuery.andWhere('router.id = :routerId', { routerId });
        }
        sessionQuery.groupBy('router.id, router.name');
        const revenueQuery = this.paymentRepo
            .createQueryBuilder('payment')
            .select([
            'payment.routerId AS "routerId"',
            `${this.castNumeric('SUM(payment.amount)')} AS "totalRevenue"`,
        ])
            .where('payment.businessId = :businessId', { businessId })
            .andWhere('payment.status = :status', { status: payment_entity_1.PaymentStatus.SUCCESSFUL })
            .andWhere('payment.createdAt BETWEEN :startDate AND :endDate', {
            startDate: new Date(filters.startDate),
            endDate: new Date(filters.endDate),
        });
        if (routerId) {
            revenueQuery.andWhere('payment.routerId = :routerId', { routerId });
        }
        revenueQuery.andWhere('payment.routerId IS NOT NULL').groupBy('payment.routerId');
        const [sessions, revenues] = await Promise.all([
            sessionQuery.getRawMany(),
            revenueQuery.getRawMany(),
        ]);
        const revenueMap = new Map();
        for (const r of revenues) {
            revenueMap.set(r.routerId, Number(r.totalRevenue || 0));
        }
        const rows = sessions.map((s) => ({
            ...s,
            totalRevenue: revenueMap.get(s.routerId) || 0,
        }));
        return { data: rows };
    }
    async getLocationReport(businessId, filters) {
        const { locationId } = filters;
        const sessionQuery = this.wifiSessionRepo
            .createQueryBuilder('session')
            .leftJoin('session.router', 'router')
            .leftJoin('router.location', 'location')
            .select([
            'location.id AS "locationId"',
            'location.name AS "locationName"',
            `${this.castInt('COUNT(session.id)')} AS "totalSessions"`,
            `${this.castNumeric('SUM(session.dataUsedMb)')} AS "totalDataUsedMb"`,
        ])
            .where('session.businessId = :businessId', { businessId })
            .andWhere('session.createdAt BETWEEN :startDate AND :endDate', {
            startDate: new Date(filters.startDate),
            endDate: new Date(filters.endDate),
        });
        if (locationId) {
            sessionQuery.andWhere('location.id = :locationId', { locationId });
        }
        sessionQuery.groupBy('location.id, location.name');
        const revenueQuery = this.paymentRepo
            .createQueryBuilder('payment')
            .leftJoin('payment.business', 'business')
            .leftJoin('business.locations', 'location')
            .select([
            'location.id AS "locationId"',
            `${this.castNumeric('SUM(payment.amount)')} AS "totalRevenue"`,
        ])
            .where('payment.businessId = :businessId', { businessId })
            .andWhere('payment.status = :status', { status: payment_entity_1.PaymentStatus.SUCCESSFUL })
            .andWhere('payment.createdAt BETWEEN :startDate AND :endDate', {
            startDate: new Date(filters.startDate),
            endDate: new Date(filters.endDate),
        });
        if (locationId) {
            revenueQuery.andWhere('location.id = :locationId', { locationId });
        }
        revenueQuery.groupBy('location.id');
        const [sessions, revenues] = await Promise.all([
            sessionQuery.getRawMany(),
            revenueQuery.getRawMany(),
        ]);
        const revenueMap = new Map();
        for (const r of revenues) {
            revenueMap.set(r.locationId, Number(r.totalRevenue || 0));
        }
        const rows = sessions.map((s) => ({
            ...s,
            totalRevenue: revenueMap.get(s.locationId) || 0,
        }));
        return { data: rows };
    }
    async getCustomerReport(businessId, filters) {
        const { groupBy = report_filter_dto_1.GroupBy.DAILY } = filters;
        const truncExpr = this.getTruncExpr('customer', 'createdAt', groupBy);
        const newCustomersQuery = this.customerRepo
            .createQueryBuilder('customer')
            .select([
            `${truncExpr} AS period`,
            `${this.castInt('COUNT(customer.id)')} AS newCustomers`,
        ])
            .where('customer.businessId = :businessId', { businessId })
            .andWhere('customer.createdAt BETWEEN :startDate AND :endDate', {
            startDate: new Date(filters.startDate),
            endDate: new Date(filters.endDate),
        })
            .groupBy('period')
            .orderBy('period', 'ASC');
        const returningQuery = this.wifiSessionRepo
            .createQueryBuilder('session')
            .select([
            `${truncExpr} AS period`,
            `${this.castInt('COUNT(DISTINCT session.customerId)')} AS returningCustomers`,
        ])
            .where('session.businessId = :businessId', { businessId })
            .andWhere('session.createdAt BETWEEN :startDate AND :endDate', {
            startDate: new Date(filters.startDate),
            endDate: new Date(filters.endDate),
        })
            .groupBy('period')
            .orderBy('period', 'ASC');
        const clvQuery = this.customerRepo
            .createQueryBuilder('customer')
            .select([
            `${this.castInt('COUNT(customer.id)')} AS totalCustomers`,
            `${this.castNumeric('AVG(customer.totalPayments)')} AS averageLifetimeValue`,
            `${this.castNumeric('SUM(customer.totalPayments)')} AS totalCustomerValue`,
        ])
            .where('customer.businessId = :businessId', { businessId });
        const [newCustomers, returning, clv] = await Promise.all([
            newCustomersQuery.getRawMany(),
            returningQuery.getRawMany(),
            clvQuery.getRawOne(),
        ]);
        const periodMap = new Map();
        for (const row of newCustomers) {
            const key = row.period instanceof Date ? row.period.toISOString().split('T')[0] : String(row.period);
            periodMap.set(key, { newCustomers: Number(row.newCustomers || 0), returningCustomers: 0 });
        }
        for (const row of returning) {
            const key = row.period instanceof Date ? row.period.toISOString().split('T')[0] : String(row.period);
            const existing = periodMap.get(key);
            if (existing) {
                existing.returningCustomers = Number(row.returningCustomers || 0);
            }
            else {
                periodMap.set(key, { newCustomers: 0, returningCustomers: Number(row.returningCustomers || 0) });
            }
        }
        const data = Array.from(periodMap.entries())
            .map(([period, values]) => ({ period, ...values }))
            .sort((a, b) => a.period.localeCompare(b.period));
        return {
            data,
            customerLifetimeValue: {
                totalCustomers: Number(clv?.totalCustomers || 0),
                averageLifetimeValue: Number(clv?.averageLifetimeValue || 0),
                totalCustomerValue: Number(clv?.totalCustomerValue || 0),
            },
        };
    }
    async getDataUsageReport(businessId, filters) {
        const { groupBy = report_filter_dto_1.GroupBy.DAILY, packageId, routerId } = filters;
        const truncExpr = this.getTruncExpr('session', 'createdAt', groupBy);
        const query = this.wifiSessionRepo
            .createQueryBuilder('session')
            .select([
            `${truncExpr} AS period`,
            `${this.castNumeric('SUM(session.dataUsedMb)')} AS totalDataMb`,
            `${this.castNumeric('AVG(session.dataUsedMb)')} AS avgSessionMb`,
            `${this.castInt('COUNT(session.id)')} AS sessionCount`,
        ])
            .where('session.businessId = :businessId', { businessId })
            .andWhere('session.createdAt BETWEEN :startDate AND :endDate', {
            startDate: new Date(filters.startDate),
            endDate: new Date(filters.endDate),
        });
        if (packageId) {
            query.andWhere('session.packageId = :packageId', { packageId });
        }
        if (routerId) {
            query.andWhere('session.routerId = :routerId', { routerId });
        }
        query.groupBy('period').orderBy('period', 'ASC');
        const periods = await query.getRawMany();
        const perPackageQuery = this.wifiSessionRepo
            .createQueryBuilder('session')
            .leftJoin('session.package', 'pkg')
            .select([
            'pkg.id AS "packageId"',
            'pkg.name AS "packageName"',
            `${this.castNumeric('SUM(session.dataUsedMb)')} AS "totalDataMb"`,
            `${this.castNumeric('AVG(session.dataUsedMb)')} AS "avgSessionMb"`,
            `${this.castInt('COUNT(session.id)')} AS "sessionCount"`,
        ])
            .where('session.businessId = :businessId', { businessId })
            .andWhere('session.createdAt BETWEEN :startDate AND :endDate', {
            startDate: new Date(filters.startDate),
            endDate: new Date(filters.endDate),
        });
        if (packageId) {
            perPackageQuery.andWhere('pkg.id = :packageId', { packageId });
        }
        perPackageQuery.groupBy('pkg.id, pkg.name').orderBy('totalDataMb', 'DESC');
        const perPackage = await perPackageQuery.getRawMany();
        const totals = periods.reduce((acc, row) => ({
            totalDataMb: acc.totalDataMb + Number(row.totalDataMb || 0),
            totalSessions: acc.totalSessions + Number(row.sessionCount || 0),
        }), { totalDataMb: 0, totalSessions: 0 });
        return {
            data: periods,
            perPackage,
            totals: {
                ...totals,
                overallAvgMb: totals.totalSessions > 0 ? totals.totalDataMb / totals.totalSessions : 0,
            },
            groupBy,
        };
    }
    async getPaymentSuccessRateReport(businessId, filters) {
        const { groupBy = report_filter_dto_1.GroupBy.DAILY } = filters;
        const truncExpr = this.getTruncExpr('payment', 'createdAt', groupBy);
        const query = this.paymentRepo
            .createQueryBuilder('payment')
            .select([
            `${truncExpr} AS period`,
            `${this.castInt('COUNT(payment.id)')} AS total`,
            `${this.castInt(`SUM(CASE WHEN payment.status = '${payment_entity_1.PaymentStatus.SUCCESSFUL}' THEN 1 ELSE 0 END)`)} AS successful`,
            `${this.castInt(`SUM(CASE WHEN payment.status = '${payment_entity_1.PaymentStatus.FAILED}' THEN 1 ELSE 0 END)`)} AS failed`,
            `${this.castInt(`SUM(CASE WHEN payment.status = '${payment_entity_1.PaymentStatus.CANCELLED}' THEN 1 ELSE 0 END)`)} AS cancelled`,
            `${this.castInt(`SUM(CASE WHEN payment.status = '${payment_entity_1.PaymentStatus.TIMED_OUT}' THEN 1 ELSE 0 END)`)} AS timedOut`,
        ])
            .where('payment.businessId = :businessId', { businessId })
            .andWhere('payment.createdAt BETWEEN :startDate AND :endDate', {
            startDate: new Date(filters.startDate),
            endDate: new Date(filters.endDate),
        })
            .groupBy('period')
            .orderBy('period', 'ASC');
        const rows = await query.getRawMany();
        const totals = rows.reduce((acc, row) => ({
            total: acc.total + Number(row.total || 0),
            successful: acc.successful + Number(row.successful || 0),
            failed: acc.failed + Number(row.failed || 0),
            cancelled: acc.cancelled + Number(row.cancelled || 0),
            timedOut: acc.timedOut + Number(row.timedOut || 0),
        }), { total: 0, successful: 0, failed: 0, cancelled: 0, timedOut: 0 });
        const successRate = totals.total > 0 ? (totals.successful / totals.total) * 100 : 0;
        return {
            data: rows.map((row) => ({
                ...row,
                successRate: row.total > 0 ? Math.round((row.successful / row.total) * 10000) / 100 : 0,
            })),
            totals: {
                ...totals,
                successRate: Math.round(successRate * 100) / 100,
            },
            groupBy,
        };
    }
    async getTaxReport(businessId, filters) {
        const { groupBy = report_filter_dto_1.GroupBy.DAILY } = filters;
        const truncExpr = this.getTruncExpr('payment', 'createdAt', groupBy);
        const query = this.paymentRepo
            .createQueryBuilder('payment')
            .leftJoin('payment.package', 'pkg')
            .select([
            `${truncExpr} AS period`,
            `${this.castNumeric('SUM(payment.amount)')} AS grossRevenue`,
            `${this.castNumeric('SUM(payment.amount / (1 + COALESCE(pkg.taxRate, 0) / 100.0))')} AS netRevenue`,
            `${this.castNumeric('SUM(payment.amount - (payment.amount / (1 + COALESCE(pkg.taxRate, 0) / 100.0)))')} AS taxCollected`,
            `${this.castInt('COUNT(payment.id)')} AS transactions`,
        ])
            .where('payment.businessId = :businessId', { businessId })
            .andWhere('payment.status = :status', { status: payment_entity_1.PaymentStatus.SUCCESSFUL })
            .andWhere('payment.createdAt BETWEEN :startDate AND :endDate', {
            startDate: new Date(filters.startDate),
            endDate: new Date(filters.endDate),
        })
            .groupBy('period')
            .orderBy('period', 'ASC');
        const rows = await query.getRawMany();
        const totals = rows.reduce((acc, row) => ({
            grossRevenue: acc.grossRevenue + Number(row.grossRevenue || 0),
            netRevenue: acc.netRevenue + Number(row.netRevenue || 0),
            taxCollected: acc.taxCollected + Number(row.taxCollected || 0),
            transactions: acc.transactions + Number(row.transactions || 0),
        }), { grossRevenue: 0, netRevenue: 0, taxCollected: 0, transactions: 0 });
        return {
            data: rows,
            totals,
            groupBy,
        };
    }
    async getCommissionReport(businessId, filters) {
        const { groupBy = report_filter_dto_1.GroupBy.DAILY } = filters;
        const truncExpr = this.getTruncExpr('commission', 'createdAt', groupBy);
        const query = this.commissionRepo
            .createQueryBuilder('commission')
            .select([
            `${truncExpr} AS period`,
            `${this.castNumeric('SUM(commission.amount)')} AS totalCommissions`,
            `${this.castInt('COUNT(commission.id)')} AS commissionCount`,
            `${this.castNumeric('AVG(commission.rate)')} AS averageRate`,
            `${this.castInt(`SUM(CASE WHEN commission.status = '${commission_entity_1.CommissionStatus.PAID}' THEN 1 ELSE 0 END)`)} AS paid`,
            `${this.castInt(`SUM(CASE WHEN commission.status = '${commission_entity_1.CommissionStatus.PENDING}' THEN 1 ELSE 0 END)`)} AS pending`,
        ])
            .where('commission.businessId = :businessId', { businessId })
            .andWhere('commission.createdAt BETWEEN :startDate AND :endDate', {
            startDate: new Date(filters.startDate),
            endDate: new Date(filters.endDate),
        })
            .groupBy('period')
            .orderBy('period', 'ASC');
        const rows = await query.getRawMany();
        const totals = rows.reduce((acc, row) => ({
            totalCommissions: acc.totalCommissions + Number(row.totalCommissions || 0),
            totalCount: acc.totalCount + Number(row.commissionCount || 0),
            totalPaid: acc.totalPaid + Number(row.paid || 0),
            totalPending: acc.totalPending + Number(row.pending || 0),
        }), { totalCommissions: 0, totalCount: 0, totalPaid: 0, totalPending: 0 });
        return {
            data: rows,
            totals,
            groupBy,
        };
    }
    async exportReportCsv(businessId, reportType, filters) {
        let data = [];
        let columns = [];
        switch (reportType) {
            case 'revenue': {
                const report = await this.getRevenueReport(businessId, filters);
                data = report.data;
                columns = ['period', 'totalTransactions', 'totalRevenue', 'averageTransaction'];
                break;
            }
            case 'packages': {
                const report = await this.getPackageSalesReport(businessId, filters);
                data = report.data;
                columns = ['packageId', 'packageName', 'saleCount', 'totalRevenue'];
                break;
            }
            case 'routers': {
                const report = await this.getRouterReport(businessId, filters);
                data = report.data;
                columns = ['routerId', 'routerName', 'totalSessions', 'totalDataUsedMb', 'totalRevenue'];
                break;
            }
            case 'customers': {
                const report = await this.getCustomerReport(businessId, filters);
                data = report.data;
                columns = ['period', 'newCustomers', 'returningCustomers'];
                break;
            }
            case 'data-usage': {
                const report = await this.getDataUsageReport(businessId, filters);
                data = report.data;
                columns = ['period', 'totalDataMb', 'avgSessionMb', 'sessionCount'];
                break;
            }
            case 'payment-success': {
                const report = await this.getPaymentSuccessRateReport(businessId, filters);
                data = report.data;
                columns = ['period', 'total', 'successful', 'failed', 'cancelled', 'timedOut', 'successRate'];
                break;
            }
            case 'tax': {
                const report = await this.getTaxReport(businessId, filters);
                data = report.data;
                columns = ['period', 'grossRevenue', 'netRevenue', 'taxCollected', 'transactions'];
                break;
            }
            case 'commissions': {
                const report = await this.getCommissionReport(businessId, filters);
                data = report.data;
                columns = ['period', 'totalCommissions', 'commissionCount', 'averageRate', 'paid', 'pending'];
                break;
            }
            default:
                columns = ['reportType'];
                data = [{ reportType: 'Invalid report type' }];
        }
        return (0, sync_1.stringify)(data, { header: true, columns });
    }
    async exportReportPdf(businessId, reportType, filters) {
        const csvData = await this.exportReportCsv(businessId, reportType, filters);
        const lines = csvData.split('\n').filter((line) => line.trim());
        const headers = lines[0]?.split(',') || [];
        const rows = lines.slice(1).map((line) => line.split(','));
        return new Promise((resolve, reject) => {
            const chunks = [];
            const doc = new PDFKit();
            doc.on('data', (chunk) => chunks.push(chunk));
            doc.on('end', () => resolve(Buffer.concat(chunks)));
            doc.on('error', reject);
            doc.fontSize(18).text(`Report: ${reportType.toUpperCase()}`, { align: 'center' });
            doc.fontSize(10).text(`Period: ${filters.startDate} to ${filters.endDate}`, { align: 'center' });
            doc.moveDown(1);
            const startX = 30;
            const colWidth = (doc.page.width - startX * 2) / Math.max(headers.length, 1);
            let y = doc.y;
            doc.fontSize(8).font('Helvetica-Bold');
            for (const header of headers) {
                doc.text(header, startX + headers.indexOf(header) * colWidth, y, {
                    width: colWidth,
                    align: 'left',
                });
            }
            y += 20;
            doc.font('Helvetica').fontSize(8);
            for (const row of rows) {
                if (y > doc.page.height - 50) {
                    doc.addPage();
                    y = 50;
                }
                for (let i = 0; i < headers.length; i++) {
                    doc.text(row[i] || '', startX + i * colWidth, y, { width: colWidth, align: 'left' });
                }
                y += 15;
            }
            doc.end();
        });
    }
};
exports.ReportsService = ReportsService;
exports.ReportsService = ReportsService = ReportsService_1 = __decorate([
    (0, common_1.Injectable)(),
    __param(0, (0, typeorm_1.InjectRepository)(payment_entity_1.Payment)),
    __param(1, (0, typeorm_1.InjectRepository)(wifi_session_entity_1.WifiSession)),
    __param(2, (0, typeorm_1.InjectRepository)(customer_entity_1.Customer)),
    __param(3, (0, typeorm_1.InjectRepository)(package_entity_1.Package)),
    __param(4, (0, typeorm_1.InjectRepository)(router_entity_1.Router)),
    __param(5, (0, typeorm_1.InjectRepository)(business_entity_1.Business)),
    __param(6, (0, typeorm_1.InjectRepository)(transaction_entity_1.Transaction)),
    __param(7, (0, typeorm_1.InjectRepository)(commission_entity_1.Commission)),
    __metadata("design:paramtypes", [typeorm_2.Repository,
        typeorm_2.Repository,
        typeorm_2.Repository,
        typeorm_2.Repository,
        typeorm_2.Repository,
        typeorm_2.Repository,
        typeorm_2.Repository,
        typeorm_2.Repository,
        typeorm_2.DataSource])
], ReportsService);
