"use strict";
/**
 * SubcontractorService - Servicio de gestión de subcontratistas
 *
 * Catálogo de subcontratistas con evaluaciones.
 *
 * @module Contracts
 */
Object.defineProperty(exports, "__esModule", { value: true });
exports.SubcontractorService = void 0;
class SubcontractorService {
    subcontractorRepository;
    constructor(subcontractorRepository) {
        this.subcontractorRepository = subcontractorRepository;
    }
    generateCode() {
        const now = new Date();
        const year = now.getFullYear().toString().slice(-2);
        const random = Math.random().toString(36).substring(2, 6).toUpperCase();
        return `SC-${year}-${random}`;
    }
    async findWithFilters(ctx, filters = {}, page = 1, limit = 20) {
        const skip = (page - 1) * limit;
        const queryBuilder = this.subcontractorRepository
            .createQueryBuilder('sc')
            .leftJoinAndSelect('sc.createdBy', 'createdBy')
            .where('sc.tenant_id = :tenantId', { tenantId: ctx.tenantId })
            .andWhere('sc.deleted_at IS NULL');
        if (filters.specialty) {
            queryBuilder.andWhere('sc.primary_specialty = :specialty', { specialty: filters.specialty });
        }
        if (filters.status) {
            queryBuilder.andWhere('sc.status = :status', { status: filters.status });
        }
        if (filters.search) {
            queryBuilder.andWhere('(sc.business_name ILIKE :search OR sc.trade_name ILIKE :search OR sc.rfc ILIKE :search)', { search: `%${filters.search}%` });
        }
        if (filters.minRating !== undefined) {
            queryBuilder.andWhere('sc.average_rating >= :minRating', { minRating: filters.minRating });
        }
        queryBuilder
            .orderBy('sc.business_name', 'ASC')
            .skip(skip)
            .take(limit);
        const [data, total] = await queryBuilder.getManyAndCount();
        return {
            data,
            meta: {
                total,
                page,
                limit,
                totalPages: Math.ceil(total / limit),
            },
        };
    }
    async findById(ctx, id) {
        return this.subcontractorRepository.findOne({
            where: {
                id,
                tenantId: ctx.tenantId,
                deletedAt: null,
            },
        });
    }
    async findByRfc(ctx, rfc) {
        return this.subcontractorRepository.findOne({
            where: {
                rfc: rfc.toUpperCase(),
                tenantId: ctx.tenantId,
                deletedAt: null,
            },
        });
    }
    async create(ctx, dto) {
        // Check for existing RFC
        const existing = await this.findByRfc(ctx, dto.rfc);
        if (existing) {
            throw new Error('A subcontractor with this RFC already exists');
        }
        const subcontractor = this.subcontractorRepository.create({
            tenantId: ctx.tenantId,
            createdById: ctx.userId,
            code: this.generateCode(),
            businessName: dto.businessName,
            tradeName: dto.tradeName,
            rfc: dto.rfc.toUpperCase(),
            address: dto.address,
            phone: dto.phone,
            email: dto.email,
            contactName: dto.contactName,
            contactPhone: dto.contactPhone,
            primarySpecialty: dto.primarySpecialty,
            secondarySpecialties: dto.secondarySpecialties,
            bankName: dto.bankName,
            bankAccount: dto.bankAccount,
            clabe: dto.clabe,
            notes: dto.notes,
            status: 'active',
        });
        return this.subcontractorRepository.save(subcontractor);
    }
    async update(ctx, id, dto) {
        const subcontractor = await this.findById(ctx, id);
        if (!subcontractor) {
            return null;
        }
        Object.assign(subcontractor, {
            ...dto,
            updatedById: ctx.userId || '',
        });
        return this.subcontractorRepository.save(subcontractor);
    }
    async updateRating(ctx, id, rating) {
        const subcontractor = await this.findById(ctx, id);
        if (!subcontractor) {
            return null;
        }
        // Calculate new average rating
        const totalRatings = subcontractor.completedContracts;
        const currentTotal = subcontractor.averageRating * totalRatings;
        const newTotal = currentTotal + rating;
        subcontractor.averageRating = newTotal / (totalRatings + 1);
        subcontractor.updatedById = ctx.userId || '';
        return this.subcontractorRepository.save(subcontractor);
    }
    async incrementContracts(ctx, id, completed = false) {
        const subcontractor = await this.findById(ctx, id);
        if (!subcontractor) {
            return null;
        }
        subcontractor.totalContracts += 1;
        if (completed) {
            subcontractor.completedContracts += 1;
        }
        subcontractor.updatedById = ctx.userId || '';
        return this.subcontractorRepository.save(subcontractor);
    }
    async incrementIncidents(ctx, id) {
        const subcontractor = await this.findById(ctx, id);
        if (!subcontractor) {
            return null;
        }
        subcontractor.totalIncidents += 1;
        subcontractor.updatedById = ctx.userId || '';
        return this.subcontractorRepository.save(subcontractor);
    }
    async deactivate(ctx, id) {
        const subcontractor = await this.findById(ctx, id);
        if (!subcontractor) {
            return null;
        }
        subcontractor.status = 'inactive';
        subcontractor.updatedById = ctx.userId || '';
        return this.subcontractorRepository.save(subcontractor);
    }
    async blacklist(ctx, id, reason) {
        const subcontractor = await this.findById(ctx, id);
        if (!subcontractor) {
            return null;
        }
        subcontractor.status = 'blacklisted';
        subcontractor.notes = `${subcontractor.notes || ''}\n[BLACKLISTED] ${reason}`;
        subcontractor.updatedById = ctx.userId || '';
        return this.subcontractorRepository.save(subcontractor);
    }
    async softDelete(ctx, id) {
        const subcontractor = await this.findById(ctx, id);
        if (!subcontractor) {
            return false;
        }
        await this.subcontractorRepository.update({ id, tenantId: ctx.tenantId }, { deletedAt: new Date(), deletedById: ctx.userId || '' });
        return true;
    }
    async getBySpecialty(ctx, specialty) {
        return this.subcontractorRepository.find({
            where: {
                tenantId: ctx.tenantId,
                primarySpecialty: specialty,
                status: 'active',
                deletedAt: null,
            },
            order: { averageRating: 'DESC' },
        });
    }
}
exports.SubcontractorService = SubcontractorService;
//# sourceMappingURL=subcontractor.service.js.map