"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.getLastDataSampleByDataSetName = exports.getPowerPlansForHeader = exports.getPowerPlantHeaderInfo = exports.getPowerPlantDetail = exports.getPowerPlansCount = exports.getPowerPlans = exports.getDomainListByTypeBuilder = exports.IS_DEV = void 0;
const shell_1 = require("@things-factory/shell");
const dataset_1 = require("@things-factory/dataset");
const inverter_1 = require("@esome-dev/inverter");
const power_plant_query_1 = require("./power-plant-query");
exports.IS_DEV = false;
const getDomainListByTypeBuilder = async (domainId) => {
    const domain = await (0, shell_1.getRepository)(shell_1.Domain).findOneBy({ id: domainId });
    if (domain.extType === 'onm') {
        return (0, shell_1.getRepository)(shell_1.Domain)
            .createQueryBuilder('onm_d')
            .innerJoin('onm_domain_bindings', 'odb', 'odb.onm_domain_id = onm_d.id')
            .innerJoin('domains', 'pp_d', 'odb.power_plant_domain_id = pp_d.id')
            .andWhere('onm_d.id = :id', { id: domain.id });
        // } else if (domain.extType === 'power-plant') {
    }
    else {
        return (0, shell_1.getRepository)(shell_1.Domain).createQueryBuilder('pp_d').andWhere('pp_d.id = :id', { id: domain.id });
    }
};
exports.getDomainListByTypeBuilder = getDomainListByTypeBuilder;
const getPowerPlans = async (params, domain) => {
    const { page, limit } = params.pagination;
    const statusFilter = params.filters.find(v => v.name === 'status');
    const nameFilter = params.filters.find(v => v.name === 'name');
    const nameSorting = params.sortings.find(v => v.name === 'name');
    let powerPlans = (await (0, exports.getDomainListByTypeBuilder)(domain.id))
        .select('pp_d.id', 'id')
        .addSelect('pp_d.description', 'name')
        .addSelect("pp_d.attributes::json ->> 'address'", 'address')
        .addSelect("pp_d.attributes::json ->> 'capacity'", 'capacity')
        .addSelect("pp_d.attributes::json ->> 'weatherId'", 'weatherId')
        .addSelect('SUM(is.acc)', 'generationAmount')
        .addSelect('SUM(is.dc)', 'directCurrent')
        .addSelect('SUM(is.ac)', 'alternatingCurrent')
        .addSelect("SUM(is.acc) / COALESCE(NULLIF(pp_d.attributes::json ->> 'capacity', '')::NUMERIC, 1)", 'generationTime')
        .addSelect('MAX(is.run)', 'maxInverterOperationStatus')
        .addSelect('MAX(is.com)', 'maxInverterCommunicationStatus')
        .addSelect("CASE WHEN (DATE_PART('hour', NOW() + INTERVAL '9 hour') NOT BETWEEN 9 AND 20) THEN 'F' WHEN MAX(is.collected_at) < NOW() - INTERVAL '1 hour' THEN 'T' ELSE 'F' END", 'isNoSignal') // 1시간 (한국 타임존 9시간 포함해서 10시간) 이상된 인버터 시간은 통신장애 (9~21시는 해가 없으므로 정상)
        .leftJoin('inverter_statuses', 'is', 'is.domain_id = pp_d.id')
        .groupBy('pp_d.id')
        .limit(limit)
        .offset((page - 1) * limit);
    // 발전소 이름 검색
    if (nameFilter?.value) {
        powerPlans.andWhere('pp_d.description ILIKE :name', { name: `%${nameFilter.value}%` });
    }
    // 인버터 상태 검색
    if (statusFilter?.value) {
        if (statusFilter.value === power_plant_query_1.POWER_PLANT_STATUS.COMMUNICATION_FAULT) {
            powerPlans.andWhere("is.collected_at < NOW() - INTERVAL '1 hour'"); // 1시간 (한국 타임존 9시간 포함해서 10시간) 이상된 인버터 시간은 통신장애 (9~21시는 해가 없으므로 정상)
            powerPlans.andWhere("DATE_PART('hour', NOW() + INTERVAL '9 hour') BETWEEN 9 AND 20");
        }
        else if (statusFilter.value === power_plant_query_1.POWER_PLANT_STATUS.FAULT) {
            powerPlans.andHaving("MAX(is.run) != '0'");
        }
        else if (statusFilter.value === power_plant_query_1.POWER_PLANT_STATUS.STOP) {
            powerPlans.andHaving("MAX(is.com) = '1'");
        }
        else if (statusFilter.value === power_plant_query_1.POWER_PLANT_STATUS.NORMAL) {
            powerPlans.andHaving("MAX(is.run) = '0'");
            powerPlans.andHaving("MAX(is.com) = '0'");
            powerPlans.andWhere("(is.collected_at >= NOW() - INTERVAL '1 hour' OR DATE_PART('hour', NOW() + INTERVAL '9 hour') NOT BETWEEN 9 AND 20)"); // 1시간 (한국 타임존 9시간 포함해서 10시간) 이상된 인버터 시간은 통신장애 (9~21시는 해가 없으므로 정상)
        }
    }
    if (nameSorting?.name) {
        powerPlans.orderBy(`pp_d.description COLLATE "ko_KR" `, nameSorting.desc ? 'DESC' : 'ASC');
    }
    powerPlans = getPowerPlansCondition(powerPlans, params);
    const items = await powerPlans.getRawMany();
    // 카운트 쿼리
    const countQueryBuilder = powerPlans.clone();
    countQueryBuilder.select('pp_d.id', 'id');
    // order by, limit 제거
    countQueryBuilder.expressionMap.orderBys = {};
    countQueryBuilder.limit(undefined);
    countQueryBuilder.offset(undefined);
    const listCount = await (0, shell_1.getDataSource)()
        .createQueryBuilder()
        .select('COUNT(*)', 'cnt')
        .from('(' + countQueryBuilder.getQuery() + ')', 'sub_query')
        .setParameters(countQueryBuilder.getParameters())
        .getRawOne();
    return { items, listCount: listCount.cnt };
};
exports.getPowerPlans = getPowerPlans;
const getPowerPlansCount = async (params, domain) => {
    // 기존 쿼리 빌더 주석 처리
    let powerPlans = (await (0, exports.getDomainListByTypeBuilder)(domain.id))
        .select('pp_d.id', 'id')
        .addSelect("COALESCE(NULLIF((pp_d.attributes::json ->> 'capacity'), '')::NUMERIC, 0)", 'capacity')
        .addSelect('SUM(is.acc)', 'acc')
        .addSelect('MAX((is.run)::NUMERIC)', 'maxInverterOperationStatus')
        .addSelect('MAX((is.com)::NUMERIC)', 'maxInverterCommunicationStatus')
        .addSelect("CASE WHEN (DATE_PART('hour', NOW() + INTERVAL '9 hour') NOT BETWEEN 9 AND 20) THEN 'F' WHEN MAX(is.collected_at) < NOW() - INTERVAL '1 hour' THEN 'T' ELSE 'F' END", 'isNoSignal') // 1시간 (한국 타임존 9시간 포함해서 10시간) 이상된 인버터 시간은 통신장애 (9~21시는 해가 없으므로 정상)
        .leftJoin('inverter_statuses', 'is', 'is.domain_id = pp_d.id')
        .groupBy('pp_d.id');
    powerPlans = getPowerPlansCondition(powerPlans, params);
    return powerPlans.getRawMany();
};
exports.getPowerPlansCount = getPowerPlansCount;
const getPowerPlansCondition = (queryBuilder, params) => {
    const groupIdFilter = params.filters.find(v => v.name === 'groupId');
    // 그룹 필터 있으면 Inner Join으로 그룹이 아닌 발전소 제외
    if (groupIdFilter?.value) {
        queryBuilder.innerJoin('power_plant_group_bindings', 'ppgb', 'pp_d.id = ppgb.domain_id AND ppgb.power_plant_group_id = :groupId', { groupId: groupIdFilter.value });
    }
    // if (!IS_DEV) {
    //   queryBuilder.andWhere('is.collectedAt = :collectedAt', {
    //     collectedAt: moment().subtract(1, 'day').format('YYYY-MM-DD')
    //   })
    // }
    return queryBuilder;
};
const getPowerPlantDetail = async (powerPlantId) => {
    const powerPlant = await (0, shell_1.getRepository)(shell_1.Domain).findOneBy({ id: powerPlantId });
    const inverter = await (0, shell_1.getRepository)(inverter_1.InverterStatus)
        .createQueryBuilder('is')
        .select('SUM(is.acc)', 'todayGenerated')
        .addSelect('SUM(is.ac)', 'alternatingCurrent')
        .addSelect('MAX(is.collectedAt)', 'collectedAt')
        .where('is.domain_id = :powerPlantId', { powerPlantId })
        .groupBy('is.domain_id')
        .getRawOne();
    return {
        id: powerPlant.id,
        alternatingCurrent: inverter?.alternatingCurrent,
        todayGenerated: inverter?.todayGenerated,
        name: powerPlant.description,
        address: powerPlant.attributes?.address,
        capacity: Number(powerPlant.attributes?.capacity) || 0,
        ceo: powerPlant.attributes?.ceo,
        ceoPhone: powerPlant.attributes?.phone,
        weatherId: powerPlant.attributes?.weatherId,
        rec: powerPlant.attributes?.rec,
        safetyManager: powerPlant.attributes?.safetyManager,
        safetyManagerPhone: powerPlant.attributes?.phone2,
        refreshTime: powerPlant.attributes?.refreshTime,
        inverterManufacturer: powerPlant.attributes?.inverterManufacturer,
        inverterModel: powerPlant.attributes?.inverterModel,
        collectedAt: inverter?.collectedAt
    };
};
exports.getPowerPlantDetail = getPowerPlantDetail;
const getPowerPlantHeaderInfo = async (powerPlantId) => {
    const powerPlant = await (0, shell_1.getRepository)(shell_1.Domain).findOneBy({ id: powerPlantId });
    const inverter = await (0, shell_1.getRepository)(inverter_1.InverterStatus)
        .createQueryBuilder('is')
        .select('domain_id', 'domain_id')
        .addSelect('MAX(run)', 'maxInverterOperationStatus')
        .addSelect('MAX(com)', 'maxInverterCommunicationStatus')
        .addSelect("CASE WHEN (DATE_PART('hour', NOW() + INTERVAL '9 hour') NOT BETWEEN 6 AND 20) THEN 'F' WHEN MAX(collected_at) < NOW() - INTERVAL '1 hour' THEN 'T' ELSE 'F' END", 'isNoSignal') // 1시간 (한국 타임존 9시간 포함해서 10시간) 이상된 인버터 시간은 통신장애 (6~21시는 해가 없으므로 정상)
        .where('domain_id = :powerPlantId', { powerPlantId })
        .groupBy('domain_id')
        .getRawOne();
    return {
        id: powerPlant.id,
        capacity: Number(powerPlant.attributes?.capacity) || 0,
        name: powerPlant.description,
        weatherId: powerPlant.attributes?.weatherId,
        maxInverterOperationStatus: inverter?.maxInverterOperationStatus,
        maxInverterCommunicationStatus: inverter?.maxInverterCommunicationStatus,
        isNoSignal: inverter?.isNoSignal
    };
};
exports.getPowerPlantHeaderInfo = getPowerPlantHeaderInfo;
const getPowerPlansForHeader = async (powerPlantId) => {
    const powerPlans = (await (0, exports.getDomainListByTypeBuilder)(powerPlantId))
        .select('pp_d.id', 'id')
        .addSelect('pp_d.description', 'name')
        .orderBy('pp_d.description', 'ASC')
        .getRawMany();
    return powerPlans;
};
exports.getPowerPlansForHeader = getPowerPlansForHeader;
const getLastDataSampleByDataSetName = async (dataSetName) => {
    const powerPlant = await (0, shell_1.getRepository)(shell_1.Domain).findOneBy({ name: 'SYSTEM' });
    const todaySmp = await (0, shell_1.getRepository)(dataset_1.DataSample)
        .createQueryBuilder('d_sample')
        .select('d_sample.domain_id', 'powerPlantId')
        .addSelect('d_sample.data', 'data')
        .leftJoin('data_sets', 'd_set', 'd_set.id = d_sample.data_set_id')
        .where('d_set.name = :dataSetName', { dataSetName })
        .andWhere('d_sample.domain_id = :domainId', { domainId: powerPlant.id })
        .orderBy('d_sample.collected_at', 'DESC')
        .limit(1)
        .getRawOne();
    return todaySmp;
};
exports.getLastDataSampleByDataSetName = getLastDataSampleByDataSetName;
//# sourceMappingURL=power-plant-model.js.map