"use strict";
/**
 * EtapaService - Gestión de etapas de fraccionamientos
 *
 * CRUD de etapas con soporte multi-tenant.
 *
 * @module Construction
 */
Object.defineProperty(exports, "__esModule", { value: true });
exports.EtapaService = void 0;
const typeorm_1 = require("typeorm");
class EtapaService {
    repository;
    constructor(repository) {
        this.repository = repository;
    }
    /**
     * Listar etapas
     */
    async findAll(options) {
        const { tenantId, fraccionamientoId, page = 1, limit = 20, search, status } = options;
        const query = this.repository
            .createQueryBuilder('e')
            .where('e.tenant_id = :tenantId', { tenantId })
            .andWhere('e.deleted_at IS NULL');
        if (fraccionamientoId) {
            query.andWhere('e.fraccionamiento_id = :fraccionamientoId', { fraccionamientoId });
        }
        if (search) {
            query.andWhere('(e.code ILIKE :search OR e.name ILIKE :search)', { search: `%${search}%` });
        }
        if (status) {
            query.andWhere('e.status = :status', { status });
        }
        const total = await query.getCount();
        const items = await query
            .skip((page - 1) * limit)
            .take(limit)
            .orderBy('e.sequence', 'ASC')
            .addOrderBy('e.name', 'ASC')
            .getMany();
        return { items, total };
    }
    /**
     * Obtener etapa por ID
     */
    async findById(id, tenantId) {
        return this.repository.findOne({
            where: { id, tenantId, deletedAt: (0, typeorm_1.IsNull)() },
            relations: ['manzanas'],
        });
    }
    /**
     * Obtener etapa por código dentro de un fraccionamiento
     */
    async findByCode(code, fraccionamientoId, tenantId) {
        return this.repository.findOne({
            where: { code, fraccionamientoId, tenantId, deletedAt: (0, typeorm_1.IsNull)() },
        });
    }
    /**
     * Crear etapa
     */
    async create(tenantId, dto, createdBy) {
        const existing = await this.findByCode(dto.code, dto.fraccionamientoId, tenantId);
        if (existing) {
            throw new Error('Stage code already exists in this fraccionamiento');
        }
        return this.repository.save(this.repository.create({
            tenantId,
            ...dto,
            createdBy,
            status: dto.status || 'draft',
        }));
    }
    /**
     * Actualizar etapa
     */
    async update(id, tenantId, dto, updatedBy) {
        const etapa = await this.findById(id, tenantId);
        if (!etapa) {
            throw new Error('Stage not found');
        }
        // Verificar código único si se está cambiando
        if (dto.code && dto.code !== etapa.code) {
            const existing = await this.findByCode(dto.code, etapa.fraccionamientoId, tenantId);
            if (existing) {
                throw new Error('Stage code already exists in this fraccionamiento');
            }
        }
        await this.repository.update(id, {
            ...dto,
            updatedBy,
            updatedAt: new Date(),
        });
        return this.findById(id, tenantId);
    }
    /**
     * Eliminar etapa (soft delete)
     */
    async delete(id, tenantId, _deletedBy) {
        const etapa = await this.findById(id, tenantId);
        if (!etapa) {
            throw new Error('Stage not found');
        }
        // TODO: Verificar si tiene manzanas antes de eliminar
        await this.repository.update(id, {
            deletedAt: new Date(),
        });
    }
    /**
     * Obtener etapas por fraccionamiento
     */
    async findByFraccionamiento(fraccionamientoId, tenantId) {
        return this.repository.find({
            where: { fraccionamientoId, tenantId, deletedAt: (0, typeorm_1.IsNull)() },
            order: { sequence: 'ASC' },
        });
    }
}
exports.EtapaService = EtapaService;
//# sourceMappingURL=etapa.service.js.map