package cn.sagacloud.server.algorithm.services.endpoint

import cn.sagacloud.server.algorithm.models.dataCheck.*
import cn.sagacloud.server.algorithm.models.excel.IsPassedEnum
import cn.sagacloud.server.algorithm.models.excel.nonBlockingReport.*
import cn.sagacloud.server.algorithm.models.modelFile.FloorModelView
import cn.sagacloud.server.algorithm.models.responses.DataCheckListResponse
import cn.sagacloud.server.algorithm.services.excel.ExcelService
import com.sybotan.service.utils.SSpringContextUtil
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.stereotype.Component
import java.util.HashMap

/**
 *
 *
 * @author jxing
 */
@Suppress("UNCHECKED_CAST")
@Component
class ReportService {

    @Autowired
    lateinit var floorService : FloorService

    fun doNonBlockingStatistics(revitDataCheckResult: RevitDataCheckResult, dataCheckListResponse: DataCheckListResponse) {
        dataCheckListResponse.elementRangeCheck = countError(revitDataCheckResult.elementRangeCheck as ArrayList<DataCheckResultBase?>?)
        dataCheckListResponse.familyNameCheck = countError(revitDataCheckResult.familyNameCheck as ArrayList<DataCheckResultBase?>?)
        dataCheckListResponse.equipPartLocationCheck = countError(revitDataCheckResult.equipPartLocationCheck as ArrayList<DataCheckResultBase?>?)
        dataCheckListResponse.columnCheck = countError(revitDataCheckResult.columnCheck as ArrayList<DataCheckResultBase?>?)
        dataCheckListResponse.connectorCheck = countError(revitDataCheckResult.connectorCheck as ArrayList<DataCheckResultBase?>?)
        dataCheckListResponse.systemNameCheck = countError(revitDataCheckResult.systemNameCheck as ArrayList<DataCheckResultBase?>?)
        dataCheckListResponse.equipInSpaceCheck = countError(revitDataCheckResult.equipInSpaceCheck as ArrayList<DataCheckResultBase?>?)
        dataCheckListResponse.pipeCheck = countError(revitDataCheckResult.pipeCheck as ArrayList<DataCheckResultBase?>?)
        dataCheckListResponse.systemReferEquipCheck = countError(revitDataCheckResult.systemReferEquipCheck as ArrayList<DataCheckResultBase?>?)
        dataCheckListResponse.parameterIntegrityCheck = countError(revitDataCheckResult.parameterIntegrityCheck as ArrayList<DataCheckResultBase?>?)
        dataCheckListResponse.xyzOverlapCheck = countError(revitDataCheckResult.xyzOverlapCheck as ArrayList<DataCheckResultBase?>?)
    }

    fun countError(baseList : ArrayList<DataCheckResultBase?>?) : Int{
        if(baseList.isNullOrEmpty())
            return 0
        var count = 0;
        baseList.forEach {
            if(it == null)
                return@forEach
            if(!"success".equals(it.result, ignoreCase = true)){
                ++count
            }
        }
        return count
    }

    /**
     * 写非阻塞性检查excel报告
     */
    fun writeNonBlockingReportToExcel(list: java.util.ArrayList<FloorModelView>, reportMap: HashMap<String, RevitDataCheckResult>, excelService: ExcelService) {
        writeDataCheck(reportMap, excelService)
        writeMissingFloorCheck(list, excelService)
    }

    private fun writeMissingFloorCheck(list: java.util.ArrayList<FloorModelView>, excelService: ExcelService) {
        if(list.isEmpty()){
            return
        }
        val totalReport = SSpringContextUtil.getBean(NonBlockingTotalReport::class.java) as NonBlockingTotalReport
        val content = floorService.addMissingFloor(list)
        val missingFloorReport = SSpringContextUtil.getBean(MissingFloorReport::class.java) as MissingFloorReport
        var hasError = false
        content.forEach {
            val data = MissingFloorReport.Data()
            data.floorName = it.floorName?:""

            if(it.id == null){
                data.isPassed = IsPassedEnum.Unpass
                data.note = "缺失楼层${data.floorName}, 请检查"
                hasError = true
            }else
                data.isPassed = IsPassedEnum.Pass
            missingFloorReport.rowValue.add(data)
        }
        excelService.insertReport(missingFloorReport)
        if(hasError)
            excelService.randomWrite(totalReport.sheetIndex, 1, 1, errorMsg)
    }

    val errorMsg = "包含问题数据"
    /**
     * 构建范围检查
     */
    private fun writeDataCheck(reportMap: HashMap<String, RevitDataCheckResult>, excelService: ExcelService) : Boolean{
        val componentRangeReport = SSpringContextUtil.getBean(ComponentRangeReport::class.java) as ComponentRangeReport
        val familyNameCheckReport = SSpringContextUtil.getBean(EquipNameCodeReport::class.java) as EquipNameCodeReport
        val equipPartLocationCheckReport = SSpringContextUtil.getBean(PartLocationReport::class.java) as PartLocationReport
        val columnCheckReport = SSpringContextUtil.getBean(ColumnBoundaryReport::class.java) as ColumnBoundaryReport
        val connectorCheckReport = SSpringContextUtil.getBean(ConnectorReport::class.java) as ConnectorReport
        val systemNameCheckReport = SSpringContextUtil.getBean(SystemNameReport::class.java) as SystemNameReport
        val equipInSpaceCheckReport = SSpringContextUtil.getBean(EquipNotInSpaceReport::class.java) as EquipNotInSpaceReport
        val pipeCheckReport = SSpringContextUtil.getBean(PipeSegmentReport::class.java) as PipeSegmentReport
        val systemReferEquipCheckReport = SSpringContextUtil.getBean(PipeAndRelatedEquipReport::class.java) as PipeAndRelatedEquipReport
        val parameterIntegrityCheckReport = SSpringContextUtil.getBean(FamilyParamReport::class.java) as FamilyParamReport
        val xyzOverlapCheckReport = SSpringContextUtil.getBean(DuplicateLocationReport::class.java) as DuplicateLocationReport
        val totalReport = SSpringContextUtil.getBean(NonBlockingTotalReport::class.java) as NonBlockingTotalReport
        var hasError = false
        var componentRangeCheckCnt = 0;
        var columnCheckCnt = 0
        var connectorCheckCnt = 0
        var equipInSpaceCheckCnt = 0
        var pipeCheckCnt = 0
        var systemReferEquipCheckCnt = 0
        var parameterIntegrityCheckCnt = 0
        var xyzOverlapCheckCnt = 0
        reportMap.forEach{
            val floorName = it.key
            var pair = generateElementRangeCheck(it, floorName, componentRangeReport, excelService, componentRangeCheckCnt)
            componentRangeCheckCnt = pair.second
            if (pair.first)
                totalReport.addCellValue(2, 1, errorMsg)
            hasError = generateFamilyNameCheck(it, floorName, familyNameCheckReport, excelService)
            if(hasError)
                totalReport.addCellValue(3, 1, errorMsg)
            hasError = generateEquipPartLocationCheck(it, floorName, equipPartLocationCheckReport, excelService)
            if(hasError)
                totalReport.addCellValue(4, 1, errorMsg)
            pair = generateColumnCheck(it, floorName, columnCheckReport, excelService, columnCheckCnt)
            columnCheckCnt = pair.second
            if(pair.first)
                totalReport.addCellValue(5, 1, errorMsg)
            pair = generateConnectorCheck(it, floorName, connectorCheckReport, excelService, connectorCheckCnt)
            connectorCheckCnt = pair.second
            if(pair.first)
                totalReport.addCellValue(6, 1, errorMsg)
            hasError = generateSystemNameCheck(it, floorName, systemNameCheckReport, excelService)
            if(hasError)
                totalReport.addCellValue(7, 1, errorMsg)
            pair = generateEquipInSpaceCheck(it, floorName, equipInSpaceCheckReport, excelService, equipInSpaceCheckCnt)
            equipInSpaceCheckCnt = pair.second
            if(pair.first)
                totalReport.addCellValue(8, 1, errorMsg)
            pair = generatePipeCheck(it, floorName, pipeCheckReport, excelService, pipeCheckCnt)
            pipeCheckCnt = pair.second
            if(pair.first)
                totalReport.addCellValue(9, 1, errorMsg)
            pair = generateSystemReferEquipCheck(it, floorName, systemReferEquipCheckReport, excelService, systemReferEquipCheckCnt)
            systemReferEquipCheckCnt = pair.second
            if(pair.first)
                totalReport.addCellValue(10, 1, errorMsg)
            pair = generateParameterIntegrityCheck(it, floorName, parameterIntegrityCheckReport, excelService, parameterIntegrityCheckCnt)
            parameterIntegrityCheckCnt = pair.second
            if(pair.first)
                totalReport.addCellValue(11, 1, errorMsg)
            pair = generateXYZOverlapCheck(it, floorName, xyzOverlapCheckReport, excelService, xyzOverlapCheckCnt)
            xyzOverlapCheckCnt = pair.second
            if(pair.first)
                totalReport.addCellValue(12, 1, errorMsg)
            for (cellValue in totalReport.cellValues){
                excelService.randomWrite(totalReport.sheetIndex, cellValue)
            }
        }
        return true
    }

    /**
     * 生成报告 - xyz坐标重叠检查
     */
    private fun generateXYZOverlapCheck(it: Map.Entry<String, RevitDataCheckResult>, floorName: String, xyzOverlapCheckReport: DuplicateLocationReport, excelService: ExcelService, xyzOverlapCheckCnt: Int): Pair<Boolean, Int> {
        var hasError1 = false
        var xyzOverlapCheckCnt1 = xyzOverlapCheckCnt
        it.value.xyzOverlapCheck?.forEach {
            val data = DuplicateLocationReport.Data()
            if (!"success".equals(it!!.result, true)) {
                data.isPassed = IsPassedEnum.Unpass
                data.floorName = floorName
                data.id = it.id ?: ""
                data.familyName = it.familyName ?: ""
                data.note = it.resultMsg ?: ""
                xyzOverlapCheckReport.rowValue.add(data)
                hasError1 = true
            }
        }
//        if (it.value.xyzOverlapCheck != null) {
//            xyzOverlapCheckCnt1 += it.value.xyzOverlapCheck!!.size
//            xyzOverlapCheckReport.addCheckTitle(xyzOverlapCheckCnt1)
//        }
        excelService.insertReport(xyzOverlapCheckReport)
        return Pair(hasError1, xyzOverlapCheckCnt1)
    }

    /**
     * 生成报告 - Revit族参数完整性检查
     */
    private fun generateParameterIntegrityCheck(it: Map.Entry<String, RevitDataCheckResult>, floorName: String, parameterIntegrityCheckReport: FamilyParamReport, excelService: ExcelService, parameterIntegrityCheckCnt: Int): Pair<Boolean, Int> {
        var hasError1 = false
        var parameterIntegrityCheckCnt1 = parameterIntegrityCheckCnt
        it.value.parameterIntegrityCheck?.forEach {
            val data = FamilyParamReport.Data()
            if (!"success".equals(it!!.result, true)) {
                data.isPassed = IsPassedEnum.Unpass
                data.floorName = floorName
                data.familyName = it.familyName ?: ""
                data.note = it.resultMsg ?: ""
                parameterIntegrityCheckReport.rowValue.add(data)
                hasError1 = true
            }
        }
        if (it.value.parameterIntegrityCheck != null) {
            parameterIntegrityCheckCnt1 += it.value.parameterIntegrityCheck!!.size
            parameterIntegrityCheckReport.addCheckTitle(parameterIntegrityCheckCnt1)
        }
        excelService.insertReport(parameterIntegrityCheckReport)
        return Pair(hasError1, parameterIntegrityCheckCnt1)
    }

    /**
     * 生成报告 - 管网及相关设备检查
     */
    private fun generateSystemReferEquipCheck(it: Map.Entry<String, RevitDataCheckResult>, floorName: String, systemReferEquipCheckReport: PipeAndRelatedEquipReport, excelService: ExcelService, systemReferEquipCheckCnt: Int): Pair<Boolean, Int> {
        var hasError1 = false
        var systemReferEquipCheckCnt1 = systemReferEquipCheckCnt
        it.value.systemReferEquipCheck?.forEach {
            val data = PipeAndRelatedEquipReport.Data()
            if (!"success".equals(it!!.result, true)) {
                data.isPassed = IsPassedEnum.Unpass
                data.floorName = floorName
                data.id = it.id ?: ""
                data.familyName = it.familyName ?: ""
                data.passedPipe = it.passSystems ?: ""
                data.unpassedPipe = it.unPassSystems ?: ""
                data.note = it.resultMsg ?: ""
                systemReferEquipCheckReport.rowValue.add(data)
                hasError1 = true
            }
        }
        if (it.value.systemReferEquipCheck != null) {
            systemReferEquipCheckCnt1 += it.value.systemReferEquipCheck!!.size
            systemReferEquipCheckReport.addCheckTitle(systemReferEquipCheckCnt1)
        }
        excelService.insertReport(systemReferEquipCheckReport)
        return Pair(hasError1, systemReferEquipCheckCnt1)
    }

    /**
     * 生成报告 - 管段检查
     */
    private fun generatePipeCheck(it: Map.Entry<String, RevitDataCheckResult>, floorName: String, pipeCheckReport: PipeSegmentReport, excelService: ExcelService, pipeCheckCnt: Int): Pair<Boolean, Int> {
        var hasError1 = false
        var pipeCheckCnt1 = pipeCheckCnt
        it.value.pipeCheck?.forEach {
            val data = PipeSegmentReport.Data()
            if (!"success".equals(it!!.result, true)) {
                data.isPassed = IsPassedEnum.Unpass
                data.floorName = floorName
                data.id = it.id ?: ""
                data.type = it.systemName ?: ""
                data.note = it.resultMsg ?: ""
                pipeCheckReport.rowValue.add(data)
                hasError1 = true
            }
        }
//        if (it.value.pipeCheck != null) {
//            pipeCheckCnt1 += it.value.pipeCheck!!.size
//            pipeCheckReport.addCheckTitle(pipeCheckCnt1)
//        }
        excelService.insertReport(pipeCheckReport)
        return Pair(hasError1, pipeCheckCnt1)
    }

    /**
     * 生成报告 - 未在空间中的设备
     */
    private fun generateEquipInSpaceCheck(it: Map.Entry<String, RevitDataCheckResult>, floorName: String, equipInSpaceCheckReport: EquipNotInSpaceReport, excelService: ExcelService, equipInSpaceCheckCnt: Int): Pair<Boolean, Int> {
        var hasError1 = false
        var equipInSpaceCheckCnt1 = equipInSpaceCheckCnt
        it.value.equipInSpaceCheck?.forEach {
            val data = EquipNotInSpaceReport.Data()
            if (!"success".equals(it!!.result, true)) {
                data.isPassed = IsPassedEnum.Unpass
                data.floorName = floorName
                data.id = it.id ?: ""
                data.familyName = it.familyName ?: ""
                data.note = it.resultMsg ?: ""
                equipInSpaceCheckReport.rowValue.add(data)
                hasError1 = true
            }
        }
        if (it.value.equipInSpaceCheck != null) {
            equipInSpaceCheckCnt1 += it.value.equipInSpaceCheck!!.size
            equipInSpaceCheckReport.addCheckTitle(equipInSpaceCheckCnt1)
        }
        excelService.insertReport(equipInSpaceCheckReport)
        return Pair(hasError1, equipInSpaceCheckCnt1)
    }

    /**
     * 生成报告 - 系统类型名称检查
     */
    private fun generateSystemNameCheck(it: Map.Entry<String, RevitDataCheckResult>, floorName: String, systemNameCheckReport: SystemNameReport, excelService: ExcelService): Boolean {
        var hasError1 = false
        it.value.systemNameCheck?.forEach {
            val data = SystemNameReport.Data()
            if ("success".equals(it!!.result, true)) {
                data.isPassed = IsPassedEnum.Pass
            } else {
                data.isPassed = IsPassedEnum.Unpass
                hasError1 = true
            }
            data.floorName = floorName
            data.type = it.systemType ?: ""
            data.systemName = it.systemName ?: ""
            data.note = it.resultMsg ?: ""
            systemNameCheckReport.rowValue.add(data)
        }
        excelService.insertReport(systemNameCheckReport)
        return hasError1
    }

    /**
     * 生成报告 - 连接件检查
     */
    private fun generateConnectorCheck(it: Map.Entry<String, RevitDataCheckResult>, floorName: String, connectorCheckReport: ConnectorReport, excelService: ExcelService, connectorCheckCnt: Int): Pair<Boolean, Int> {
        var hasError1 = false
        var connectorCheckCnt1 = connectorCheckCnt
        it.value.connectorCheck?.forEach {
            val data = ConnectorReport.Data()
            if (!"success".equals(it!!.result, true)) {
                data.isPassed = IsPassedEnum.Unpass
                data.floorName = floorName
                data.type = it.type ?: ""
                data.id = it.id ?: ""
                data.familyName = it.familyName ?: ""
                data.note = it.resultMsg ?: ""
                connectorCheckReport.rowValue.add(data)
                hasError1 = true
            }
        }
        if (it.value.connectorCheck != null) {
            connectorCheckCnt1 += it.value.connectorCheck!!.size
            connectorCheckReport.addCheckTitle(connectorCheckCnt1)
        }
        excelService.insertReport(connectorCheckReport)
        return Pair(hasError1, connectorCheckCnt1)
    }

    /**
     * 生成报告 - 柱边界检查
     */
    private fun generateColumnCheck(it: Map.Entry<String, RevitDataCheckResult>, floorName: String, columnCheckReport: ColumnBoundaryReport, excelService: ExcelService, columnCheckCnt: Int): Pair<Boolean, Int> {
        var hasError1 = false
        var columnCheckCnt1 = columnCheckCnt
        it.value.columnCheck?.forEach {
            val data = ColumnBoundaryReport.Data()
            if (!"success".equals(it!!.result, true)) {
                data.isPassed = IsPassedEnum.Unpass
                data.floorName = floorName
                data.id = it.id ?: ""
                data.familyName = it.familyName ?: ""
                data.note = it.resultMsg ?: ""
                columnCheckReport.rowValue.add(data)
                hasError1 = true
            }
        }
        if (it.value.columnCheck != null) {
            columnCheckCnt1 += it.value.columnCheck!!.size
            columnCheckReport.addCheckTitle(columnCheckCnt1)
        }
        excelService.insertReport(columnCheckReport)
        return Pair(hasError1, columnCheckCnt1)
    }

    /**
     * 生成报告 - 部件所在位置检查
     */
    private fun generateEquipPartLocationCheck(it: Map.Entry<String, RevitDataCheckResult>, floorName: String, equipPartLocationCheckReport: PartLocationReport, excelService: ExcelService): Boolean {
        var hasError1 = false
        it.value.equipPartLocationCheck?.forEach {
            val data = PartLocationReport.Data()
            if ("success".equals(it!!.result, true)) {
                data.isPassed = IsPassedEnum.Pass
            } else {
                data.isPassed = IsPassedEnum.Unpass
                hasError1 = true
            }
            data.floorName = floorName
            data.id = it.partId ?: ""
            data.familyName = it.partFamilyName ?: ""
            data.note = it.resultMsg ?: ""
            equipPartLocationCheckReport.rowValue.add(data)
        }
        excelService.insertReport(equipPartLocationCheckReport)
        return hasError1
    }

    /**
     * 生成报告 - 设备族编码检查
     */
    private fun generateFamilyNameCheck(it: Map.Entry<String, RevitDataCheckResult>, floorName: String, familyNameCheckReport: EquipNameCodeReport, excelService: ExcelService): Boolean {
        var hasError1 = false
        it.value.familyNameCheck?.forEach {
            val data = EquipNameCodeReport.Data()
            if ("success".equals(it!!.result, true)) {
                data.isPassed = IsPassedEnum.Pass
            } else {
                data.isPassed = IsPassedEnum.Unpass
                hasError1 = true
            }
            data.floorName = floorName
            data.familyName = it.familyName ?: ""
            data.note = it.resultMsg ?: ""
            familyNameCheckReport.rowValue.add(data)
        }
        excelService.insertReport(familyNameCheckReport)
        return hasError1
    }

    /**
     * 生成报告 - 构件范围检查
     */
    private fun generateElementRangeCheck(it: Map.Entry<String, RevitDataCheckResult>, floorName: String, componentRangeReport: ComponentRangeReport, excelService: ExcelService, componentRangeCheckCnt: Int): Pair<Boolean, Int> {
        var hasError1 = false
        var componentRangeCheckCnt1 = componentRangeCheckCnt
        it.value.elementRangeCheck?.forEach {
            if (!"success".equals(it!!.result, true)) {
                val data = ComponentRangeReport.Data()
                data.floorName = floorName
                data.familyName = it.familyName ?: ""
                data.type = it.type ?: ""
                data.id = it.id ?: ""
                data.isPassed = IsPassedEnum.Unpass
                data.note = it.resultMsg ?: ""
                componentRangeReport.rowValue.add(data)
                hasError1 = true
            }
        }
        if (it.value.elementRangeCheck != null) {
            componentRangeCheckCnt1 = componentRangeCheckCnt + it.value.elementRangeCheck!!.size
            componentRangeReport.addCheckTitle(componentRangeCheckCnt1)
        }
        excelService.insertReport(componentRangeReport)
        return Pair(hasError1, componentRangeCheckCnt1)
    }
}