package com.zksy.web.controller.gasbasic;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.zksy.base.alarm.domain.AlarmData;
import com.zksy.base.alarm.service.AlarmDataService;
import com.zksy.base.constant.GasEquipmentTypeEnum;
import com.zksy.base.domain.EquipmentBase;
import com.zksy.base.domain.EquipmentType;
import com.zksy.base.mapper.EquipmentBaseMapper;
import com.zksy.base.mapper.EquipmentTypeMapper;
import com.zksy.common.annotation.Anonymous;
import com.zksy.common.core.domain.AjaxResult;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 管线压力异常报警
 */
@RestController
@RequestMapping("/api/pressure-alarm")
@Api(tags = "燃气监测-压力报警")
public class PressureAlarmController {

    @Autowired private AlarmDataService alarmDataService;
    @Autowired private EquipmentTypeMapper equipmentTypeMapper;
    @Autowired private EquipmentBaseMapper equipmentBaseMapper;

    private static final DateTimeFormatter FMT = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");

    private Set<String> getPressureCodes() {
        List<EquipmentType> types = equipmentTypeMapper.selectList(
                new LambdaQueryWrapper<EquipmentType>().eq(EquipmentType::getTypeId, GasEquipmentTypeEnum.PRESSURE));
        Set<String> typeIds = types.stream().map(EquipmentType::getId).collect(Collectors.toSet());
        if (typeIds.isEmpty()) return Collections.emptySet();
        return equipmentBaseMapper.selectList(
                new LambdaQueryWrapper<EquipmentBase>().in(EquipmentBase::getEquipmentTypeId, typeIds))
                .stream().map(EquipmentBase::getEquipmentCode).filter(Objects::nonNull).collect(Collectors.toSet());
    }

    private Map<String, EquipmentBase> loadEquipMap() {
        return equipmentBaseMapper.selectList(null).stream()
                .collect(Collectors.toMap(EquipmentBase::getEquipmentCode, e -> e, (a, b) -> a));
    }

    private Map<String, Object> toVo(AlarmData a, Map<String, EquipmentBase> eqMap) {
        EquipmentBase eq = eqMap.get(a.getDeviceCode());
        Map<String, Object> m = new LinkedHashMap<>();
        m.put("id", a.getId()); m.put("deviceCode", a.getDeviceCode());
        m.put("pointName", eq != null ? eq.getEquipmentName() : a.getDeviceCode());
        m.put("address", eq != null ? eq.getEquipmentLocation() : "");
        m.put("pressure", a.getActualValue()); m.put("threshold", a.getMaxValue());
        m.put("alarmLevelText", a.getAlarmLevel() != null && a.getAlarmLevel() == 1 ? "严重" : "预警");
        m.put("alarmTime", a.getAlarmTime() != null ? a.getAlarmTime().format(FMT) : "");
        m.put("alarmStatus", a.getAlarmStatus());
        m.put("statusText", a.getAlarmStatus() != null && a.getAlarmStatus() == 0 ? "待处理" : "已处理");
        m.put("resolveTime", a.getHandleTime() != null ? a.getHandleTime().format(FMT) : null);
        m.put("handler", a.getHandleUser()); m.put("remark", a.getHandleRemark());
        return m;
    }

    @GetMapping("/equipment")
    @ApiOperation("压力设备列表(含最新报警值)") @Anonymous
    public AjaxResult equipment() {
        Set<String> codes = getPressureCodes();
        List<EquipmentBase> eqs = equipmentBaseMapper.selectList(null).stream()
                .filter(e -> codes.contains(e.getEquipmentCode())).collect(Collectors.toList());
        List<AlarmData> all = codes.isEmpty() ? Collections.emptyList()
                : alarmDataService.list(new LambdaQueryWrapper<AlarmData>().in(AlarmData::getDeviceCode, codes)
                        .orderByDesc(AlarmData::getAlarmTime));
        Map<String, AlarmData> latestMap = all.stream()
                .collect(Collectors.toMap(AlarmData::getDeviceCode, a -> a, (a, b) -> a));
        List<Map<String, Object>> rows = new ArrayList<>();
        for (EquipmentBase eq : eqs) {
            AlarmData latest = latestMap.get(eq.getEquipmentCode());
            Map<String, Object> m = new LinkedHashMap<>();
            m.put("equipmentId", eq.getEquipmentId()); m.put("equipmentCode", eq.getEquipmentCode());
            m.put("equipmentName", eq.getEquipmentName()); m.put("location", eq.getEquipmentLocation());
            m.put("hasAlarm", latest != null && latest.getAlarmStatus() != null && latest.getAlarmStatus() == 0);
            m.put("latestPressure", latest != null ? latest.getActualValue() : null);
            m.put("latestThreshold", latest != null ? latest.getMaxValue() : null);
            m.put("latestAlarmTime", latest != null && latest.getAlarmTime() != null ? latest.getAlarmTime().format(FMT) : null);
            m.put("latestAlarmLevel", latest != null ? latest.getAlarmLevel() : null);
            rows.add(m);
        }
        return AjaxResult.success(rows);
    }

    @GetMapping("/history")
    @ApiOperation("历史报警分页") @Anonymous
    public AjaxResult history(@RequestParam(defaultValue = "1") int pageNum,
                              @RequestParam(defaultValue = "8") int pageSize,
                              @RequestParam(required = false) String startDate,
                              @RequestParam(required = false) String endDate,
                              @RequestParam(required = false) String deviceCode) {
        LambdaQueryWrapper<AlarmData> qw = new LambdaQueryWrapper<AlarmData>();
        if (deviceCode != null && !deviceCode.isEmpty()) {
            qw.eq(AlarmData::getDeviceCode, deviceCode);
        } else {
            Set<String> codes = getPressureCodes();
            if (codes.isEmpty()) return AjaxResult.success(new Page<>(pageNum, pageSize, 0));
            qw.in(AlarmData::getDeviceCode, codes);
        }
        if (startDate != null && !startDate.isEmpty()) qw.ge(AlarmData::getAlarmTime, startDate + " 00:00:00");
        if (endDate != null && !endDate.isEmpty()) qw.le(AlarmData::getAlarmTime, endDate + " 23:59:59");
        qw.orderByDesc(AlarmData::getAlarmTime);
        Page<AlarmData> page = alarmDataService.page(new Page<>(pageNum, pageSize), qw);
        Map<String, EquipmentBase> eqMap = loadEquipMap();
        List<Map<String, Object>> rows = page.getRecords().stream().map(a -> toVo(a, eqMap)).collect(Collectors.toList());
        Map<String, Object> result = new LinkedHashMap<>();
        result.put("records", rows); result.put("total", page.getTotal());
        return AjaxResult.success(result);
    }

    @GetMapping("/stats")
    @ApiOperation("统计") @Anonymous
    public AjaxResult stats() {
        Set<String> codes = getPressureCodes();
        List<AlarmData> all = codes.isEmpty() ? Collections.emptyList()
                : alarmDataService.list(new LambdaQueryWrapper<AlarmData>().in(AlarmData::getDeviceCode, codes));
        long realtime = all.stream().filter(a -> a.getAlarmStatus() != null && a.getAlarmStatus() == 0)
                .map(AlarmData::getDeviceCode).filter(Objects::nonNull).distinct().count();
        double maxP = all.stream().filter(a -> a.getActualValue() != null)
                .mapToDouble(a -> a.getActualValue().doubleValue()).max().orElse(0);
        Map<String, Object> r = new LinkedHashMap<>();
        r.put("realtimeCount", (int) realtime); r.put("pendingCount", (int) realtime);
        r.put("maxPressure", (int) maxP); r.put("totalPoints", codes.size());
        return AjaxResult.success(r);
    }

    @PutMapping("/resolve/{id}") @ApiOperation("标记已处理") @Anonymous
    public AjaxResult resolve(@PathVariable String id) {
        AlarmData e = alarmDataService.getById(id);
        if (e == null) return AjaxResult.error("记录不存在");
        e.setAlarmStatus(1); e.setHandleTime(java.time.LocalDateTime.now()); e.setHandleUser("当前用户");
        alarmDataService.updateById(e);
        return AjaxResult.success("已处理");
    }

    @PostMapping("/dispatch/{id}") @ApiOperation("派发工单(伪)") @Anonymous
    public AjaxResult dispatch(@PathVariable String id) {
        return AjaxResult.success("工单已派发(伪)");
    }
}
