"use strict";
/**
 * BitacoraObraService - Bitácora de Obra
 *
 * Gestiona el registro diario de bitácora de obra.
 * Genera automáticamente el número de entrada secuencial.
 *
 * @module Progress
 */
Object.defineProperty(exports, "__esModule", { value: true });
exports.BitacoraObraService = void 0;
const base_service_1 = require("../../../shared/services/base.service");
class BitacoraObraService extends base_service_1.BaseService {
    constructor(repository) {
        super(repository);
    }
    /**
     * Crear nueva entrada de bitácora
     */
    async createEntry(ctx, data) {
        const entryNumber = await this.getNextEntryNumber(ctx, data.fraccionamientoId);
        return this.create(ctx, {
            ...data,
            entryNumber,
            registeredById: ctx.userId,
        });
    }
    /**
     * Obtener siguiente número de entrada
     */
    async getNextEntryNumber(ctx, fraccionamientoId) {
        const result = await this.repository
            .createQueryBuilder('b')
            .select('MAX(b.entry_number)', 'maxNumber')
            .where('b.tenant_id = :tenantId', { tenantId: ctx.tenantId })
            .andWhere('b.fraccionamiento_id = :fraccionamientoId', { fraccionamientoId })
            .getRawOne();
        return (result?.maxNumber || 0) + 1;
    }
    /**
     * Obtener bitácora por fraccionamiento
     */
    async findByFraccionamiento(ctx, fraccionamientoId, page = 1, limit = 20) {
        return this.findAll(ctx, {
            page,
            limit,
            where: { fraccionamientoId },
        });
    }
    /**
     * Obtener bitácora con filtros
     */
    async findWithFilters(ctx, fraccionamientoId, filters, page = 1, limit = 20) {
        const qb = this.repository
            .createQueryBuilder('b')
            .where('b.tenant_id = :tenantId', { tenantId: ctx.tenantId })
            .andWhere('b.fraccionamiento_id = :fraccionamientoId', { fraccionamientoId })
            .andWhere('b.deleted_at IS NULL');
        if (filters.dateFrom) {
            qb.andWhere('b.entry_date >= :dateFrom', { dateFrom: filters.dateFrom });
        }
        if (filters.dateTo) {
            qb.andWhere('b.entry_date <= :dateTo', { dateTo: filters.dateTo });
        }
        if (filters.hasIncidents !== undefined) {
            if (filters.hasIncidents) {
                qb.andWhere('b.incidents IS NOT NULL');
            }
            else {
                qb.andWhere('b.incidents IS NULL');
            }
        }
        const skip = (page - 1) * limit;
        qb.orderBy('b.entry_date', 'DESC').skip(skip).take(limit);
        const [data, total] = await qb.getManyAndCount();
        return {
            data,
            meta: {
                total,
                page,
                limit,
                totalPages: Math.ceil(total / limit),
            },
        };
    }
    /**
     * Obtener entrada por fecha
     */
    async findByDate(ctx, fraccionamientoId, date) {
        return this.findOne(ctx, {
            fraccionamientoId,
            entryDate: date,
        });
    }
    /**
     * Obtener última entrada
     */
    async findLatest(ctx, fraccionamientoId) {
        const entries = await this.find(ctx, {
            where: { fraccionamientoId },
            order: { entryNumber: 'DESC' },
            take: 1,
        });
        return entries[0] || null;
    }
    /**
     * Obtener estadísticas de bitácora
     */
    async getStats(ctx, fraccionamientoId) {
        const totalEntries = await this.count(ctx, { fraccionamientoId });
        const incidentsCount = await this.repository
            .createQueryBuilder('b')
            .where('b.tenant_id = :tenantId', { tenantId: ctx.tenantId })
            .andWhere('b.fraccionamiento_id = :fraccionamientoId', { fraccionamientoId })
            .andWhere('b.deleted_at IS NULL')
            .andWhere('b.incidents IS NOT NULL')
            .getCount();
        const avgWorkers = await this.repository
            .createQueryBuilder('b')
            .select('AVG(b.workers_count)', 'avg')
            .where('b.tenant_id = :tenantId', { tenantId: ctx.tenantId })
            .andWhere('b.fraccionamiento_id = :fraccionamientoId', { fraccionamientoId })
            .andWhere('b.deleted_at IS NULL')
            .getRawOne();
        return {
            totalEntries,
            entriesWithIncidents: incidentsCount,
            avgWorkersCount: parseFloat(avgWorkers?.avg || '0'),
        };
    }
}
exports.BitacoraObraService = BitacoraObraService;
//# sourceMappingURL=bitacora-obra.service.js.map