import { TuyaService } from '@app/common/integrations/tuya/services/tuya.service'; import { CommunityRepository } from '@app/common/modules/community/repositories'; import { SpaceRepository } from '@app/common/modules/space/repositories'; import { HttpException, HttpStatus, Injectable } from '@nestjs/common'; import { GetDeviceDetailsInterface } from 'src/device/interfaces/get.device.interface'; import { GetSpaceParam } from '../dtos'; import { BaseResponseDto } from '@app/common/dto/base.response.dto'; import { SuccessResponseDto } from '@app/common/dto/success.response.dto'; import { convertKeysToCamelCase } from '@app/common/helper/camelCaseConverter'; import { ProductRepository } from '@app/common/modules/product/repositories'; @Injectable() export class SpaceDeviceService { constructor( private readonly spaceRepository: SpaceRepository, private readonly tuyaService: TuyaService, private readonly productRepository: ProductRepository, private readonly communityRepository: CommunityRepository, ) {} async listDevicesInSpace(params: GetSpaceParam): Promise { const { spaceUuid, communityUuid } = params; try { const space = await this.validateCommunityAndSpace( communityUuid, spaceUuid, ); const detailedDevices = await Promise.all( space.devices.map(async (device) => { const tuyaDetails = await this.getDeviceDetailsByDeviceIdTuya( device.deviceTuyaUuid, ); return { uuid: device.uuid, deviceTuyaUuid: device.deviceTuyaUuid, productUuid: device.productDevice.uuid, productType: device.productDevice.prodType, isActive: device.isActive, updatedAt: device.updatedAt, ...tuyaDetails, }; }), ); return new SuccessResponseDto({ data: detailedDevices, message: 'Successfully retrieved list of devices', }); } catch (error) { console.error('Error listing devices in space:', error); throw new HttpException( error.message || 'Failed to retrieve devices in space', error.status || HttpStatus.INTERNAL_SERVER_ERROR, ); } } async validateCommunityAndSpace(communityUuid: string, spaceUuid: string) { const community = await this.communityRepository.findOne({ where: { uuid: communityUuid }, }); if (!community) { this.throwNotFound('Community', communityUuid); } const space = await this.spaceRepository.findOne({ where: { uuid: spaceUuid, community: { uuid: communityUuid } }, relations: ['devices', 'devices.productDevice'], }); if (!space) { this.throwNotFound('Space', spaceUuid); } return space; } private throwNotFound(entity: string, uuid: string) { throw new HttpException( `${entity} with ID ${uuid} not found`, HttpStatus.NOT_FOUND, ); } private async getDeviceDetailsByDeviceIdTuya( deviceId: string, ): Promise { try { const tuyaDeviceDetails = await this.tuyaService.getDeviceDetails(deviceId); // Convert keys to camel case const camelCaseResponse = convertKeysToCamelCase(tuyaDeviceDetails); // Exclude specific keys and add `productUuid` // eslint-disable-next-line @typescript-eslint/no-unused-vars const { uuid, ...rest } = camelCaseResponse; return { ...rest, } as GetDeviceDetailsInterface; } catch (error) { throw new HttpException( `Error fetching device details from Tuya for device id ${deviceId}`, HttpStatus.INTERNAL_SERVER_ERROR, ); } } }