package com.njcn.gather.steady.datavie.service.impl;

import com.njcn.common.pojo.enums.response.CommonResponseEnum;
import com.njcn.common.pojo.exception.BusinessException;
import com.njcn.gather.steady.datavie.mapper.SteadyDataViewMapper;
import com.njcn.gather.steady.datavie.pojo.param.SteadyDataViewDetailParam;
import com.njcn.gather.steady.datavie.pojo.vo.SteadyDataViewTemplateVO;
import com.njcn.gather.steady.datavie.pojo.vo.SteadyDataViewVO;
import com.njcn.gather.steady.datavie.service.SteadyDataViewService;
import com.njcn.gather.tool.adddata.component.AddDataTableRegistry;
import com.njcn.gather.tool.adddata.component.AddDataTemplateRegistry;
import com.njcn.gather.tool.adddata.pojo.bo.AddDataTableDefinition;
import com.njcn.gather.tool.adddata.pojo.vo.AddDataTemplateVO;
import com.njcn.gather.tool.addledger.pojo.vo.AddLedgerLinePathVO;
import com.njcn.gather.tool.addledger.service.AddLedgerService;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;

import java.sql.Timestamp;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeParseException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

/**
 * 稳态数据查看服务实现。
 */
@Service
@RequiredArgsConstructor
public class SteadyDataViewServiceImpl implements SteadyDataViewService {

    private static final String DEFAULT_TABLE_NAME = "data_v";
    private static final String EMPTY_TEXT = "-";
    private static final DateTimeFormatter OUTPUT_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
    private static final DateTimeFormatter[] INPUT_FORMATTERS = new DateTimeFormatter[]{
            DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"),
            DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSS"),
            DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss"),
            DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSS")
    };

    private final SteadyDataViewMapper steadyDataViewMapper;
    private final AddLedgerService addLedgerService;
    private final AddDataTableRegistry addDataTableRegistry;
    private final AddDataTemplateRegistry addDataTemplateRegistry;

    @Override
    public SteadyDataViewVO getSteadyDataDetail(SteadyDataViewDetailParam param) {
        if (param == null) {
            throw new BusinessException(CommonResponseEnum.FAIL, "详情查询参数不能为空");
        }
        String tableName = normalizeTableName(param.getTableName());
        String lineId = trimToNull(param.getLineId());
        String timeId = normalizeRequiredTime(param.getTimeId(), "时间不能为空");
        String phasicType = normalizePhasicType(param.getPhasicType());
        if (lineId == null) {
            throw new BusinessException(CommonResponseEnum.FAIL, "监测点 ID 不能为空");
        }
        if (phasicType == null) {
            throw new BusinessException(CommonResponseEnum.FAIL, "相别不能为空");
        }
        AddDataTableDefinition definition = resolveTableDefinition(tableName);
        Map<String, Object> row = steadyDataViewMapper.selectSteadyDetail(definition.getTableName(), definition.getColumns(),
                lineId, timeId, phasicType);
        if (row == null || row.isEmpty()) {
            throw new BusinessException(CommonResponseEnum.FAIL, "稳态数据不存在");
        }
        List<Map<String, Object>> rows = new ArrayList<Map<String, Object>>();
        rows.add(row);
        return buildSteadyDataList(definition.getTableName(), definition.getColumns(), rows).get(0);
    }

    @Override
    public List<SteadyDataViewTemplateVO> listTemplates() {
        List<SteadyDataViewTemplateVO> result = new ArrayList<SteadyDataViewTemplateVO>();
        for (AddDataTemplateVO template : addDataTemplateRegistry.getTemplates()) {
            AddDataTableDefinition definition = resolveTableDefinition(template.getTableName());
            SteadyDataViewTemplateVO vo = new SteadyDataViewTemplateVO();
            vo.setParameterName(template.getParameterName());
            vo.setTableName(template.getTableName());
            vo.setPhaseDisplay(template.getPhaseDisplay());
            vo.setPhaseCodes(template.getPhaseCodes());
            vo.setValueColumns(resolveValueColumns(definition.getColumns()));
            result.add(vo);
        }
        return result;
    }

    private List<SteadyDataViewVO> buildSteadyDataList(String tableName, List<String> columns, List<Map<String, Object>> rows) {
        if (rows == null || rows.isEmpty()) {
            return Collections.emptyList();
        }
        List<String> lineIds = new ArrayList<String>();
        for (Map<String, Object> row : rows) {
            String lineId = trimToNull(toStringValue(row.get("LINEID")));
            if (lineId != null && !lineIds.contains(lineId)) {
                lineIds.add(lineId);
            }
        }
        Map<String, AddLedgerLinePathVO> linePathMap = addLedgerService.listLinePathByLineIds(lineIds);
        List<SteadyDataViewVO> result = new ArrayList<SteadyDataViewVO>();
        for (Map<String, Object> row : rows) {
            String lineId = trimToNull(toStringValue(row.get("LINEID")));
            AddLedgerLinePathVO linePath = linePathMap.get(lineId);
            result.add(buildSteadyDataVO(tableName, columns, row, linePath));
        }
        return result;
    }

    private SteadyDataViewVO buildSteadyDataVO(String tableName, List<String> columns, Map<String, Object> row, AddLedgerLinePathVO linePath) {
        SteadyDataViewVO vo = new SteadyDataViewVO();
        vo.setTableName(tableName);
        vo.setLineId(toStringValue(row.get("LINEID")));
        vo.setTimeId(toLocalDateTime(row.get("TIMEID")));
        vo.setPhasicType(toStringValue(row.get("PHASIC_TYPE")));
        vo.setQualityFlag(toInteger(row.get("QUALITYFLAG")));
        vo.setEquipmentName(linePath == null ? EMPTY_TEXT : defaultText(linePath.getEquipmentName()));
        vo.setEngineeringName(linePath == null ? EMPTY_TEXT : defaultText(linePath.getEngineeringName()));
        vo.setProjectName(linePath == null ? EMPTY_TEXT : defaultText(linePath.getProjectName()));
        vo.setLineName(linePath == null ? EMPTY_TEXT : defaultText(linePath.getLineName()));
        Map<String, Object> values = new LinkedHashMap<String, Object>();
        for (String column : columns) {
            if (!isInfrastructureColumn(column)) {
                values.put(column, row.get(column));
            }
        }
        vo.setValues(values);
        return vo;
    }

    private AddDataTableDefinition resolveTableDefinition(String tableName) {
        try {
            return addDataTableRegistry.getDefinition(tableName);
        } catch (IllegalArgumentException ex) {
            throw new BusinessException(CommonResponseEnum.FAIL, "稳态数据表不支持：" + tableName);
        }
    }

    private String normalizeTableName(String tableName) {
        String normalizedTableName = trimToNull(tableName);
        return normalizedTableName == null ? DEFAULT_TABLE_NAME : normalizedTableName;
    }

    private String normalizeRequiredTime(String value, String emptyMessage) {
        LocalDateTime dateTime = parseDateTime(value);
        if (dateTime == null) {
            throw new BusinessException(CommonResponseEnum.FAIL, emptyMessage);
        }
        return OUTPUT_FORMATTER.format(dateTime);
    }

    private LocalDateTime parseDateTime(String value) {
        String text = trimToNull(value);
        if (text == null) {
            return null;
        }
        for (DateTimeFormatter formatter : INPUT_FORMATTERS) {
            try {
                return LocalDateTime.parse(text, formatter);
            } catch (DateTimeParseException ignored) {
                // 尝试下一个前端可能传入的时间格式。
            }
        }
        throw new BusinessException(CommonResponseEnum.FAIL, "时间格式不正确，仅支持 yyyy-MM-dd HH:mm:ss");
    }

    private String normalizePhasicType(String phasicType) {
        String text = trimToNull(phasicType);
        if (text == null) {
            return null;
        }
        String normalized = text.toUpperCase();
        if (!"A".equals(normalized) && !"B".equals(normalized) && !"C".equals(normalized) && !"T".equals(normalized)) {
            throw new BusinessException(CommonResponseEnum.FAIL, "相别只能是 A、B、C、T");
        }
        return normalized;
    }

    private List<String> resolveValueColumns(List<String> columns) {
        List<String> result = new ArrayList<String>();
        for (String column : columns) {
            if (!isInfrastructureColumn(column)) {
                result.add(column);
            }
        }
        return result;
    }

    private boolean isInfrastructureColumn(String column) {
        return "TIMEID".equals(column) || "LINEID".equals(column) || "PHASIC_TYPE".equals(column) || "QUALITYFLAG".equals(column);
    }

    private LocalDateTime toLocalDateTime(Object value) {
        if (value instanceof LocalDateTime) {
            return (LocalDateTime) value;
        }
        if (value instanceof Timestamp) {
            return ((Timestamp) value).toLocalDateTime();
        }
        String text = trimToNull(toStringValue(value));
        return text == null ? null : parseDateTime(text);
    }

    private Integer toInteger(Object value) {
        if (value instanceof Number) {
            return ((Number) value).intValue();
        }
        String text = trimToNull(toStringValue(value));
        return text == null ? null : Integer.valueOf(text);
    }

    private String toStringValue(Object value) {
        return value == null ? null : String.valueOf(value);
    }

    private String defaultText(String value) {
        String text = trimToNull(value);
        return text == null ? EMPTY_TEXT : text;
    }

    private String trimToNull(String value) {
        if (value == null) {
            return null;
        }
        String trimmed = value.trim();
        return trimmed.isEmpty() ? null : trimmed;
    }
}
