package com.ruoyi.cc.service.impl;

import com.ruoyi.cc.domain.CcOutboundCdr;
import com.ruoyi.cc.mapper.CcOutboundCdrMapper;
import com.ruoyi.cc.service.ICcOutboundCdrService;
import com.ruoyi.common.core.text.Convert;
import com.ruoyi.common.utils.DateUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.net.URLDecoder;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * 外呼记录Service业务层处理
 * 
 * @author ruoyi
 * @date 2024-12-22
 */
@Service
public class CcOutboundCdrServiceImpl implements ICcOutboundCdrService 
{
    @Autowired
    private CcOutboundCdrMapper ccOutboundCdrMapper;

    /**
     * 查询外呼记录
     * 
     * @param id 外呼记录主键
     * @return 外呼记录
     */
    @Override
    public CcOutboundCdr selectCcOutboundCdrById(String id)
    {
        return ccOutboundCdrMapper.selectCcOutboundCdrById(id);
    }

    /**
     * 查询外呼记录列表
     * 
     * @param ccOutboundCdr 外呼记录
     * @return 外呼记录
     */
    @Override
    public List<CcOutboundCdr> selectCcOutboundCdrList(CcOutboundCdr ccOutboundCdr)
    {
        Map<String, Object> params = ccOutboundCdr.getParams();
        if (null == params) {
            params = new HashMap<>();
        }
        if (null != params.get("startTimeStart")
                && !"".equals(params.get("startTimeStart"))) {
            params.put("startTimeStart", DateUtils.dateTime("yyyy-MM-dd HH:mm:ss", (String)params.get("startTimeStart")).getTime());
        }
        if (null != params.get("startTimeEnd")
                && !"".equals(params.get("startTimeEnd"))) {
            params.put("startTimeEnd", DateUtils.dateTime("yyyy-MM-dd HH:mm:ss", (String)params.get("startTimeEnd")).getTime());
        }
        if (null != params.get("answeredTimeStart")
                && !"".equals(params.get("answeredTimeStart"))) {
            params.put("answeredTimeStart", DateUtils.dateTime("yyyy-MM-dd HH:mm:ss", (String)params.get("answeredTimeStart")).getTime());
        }
        if (null != params.get("answeredTimeEnd")
                && !"".equals(params.get("answeredTimeEnd"))) {
            params.put("answeredTimeEnd", DateUtils.dateTime("yyyy-MM-dd HH:mm:ss", (String)params.get("answeredTimeEnd")).getTime());
        }
        if (null != params.get("endTimeStart")
                && !"".equals(params.get("endTimeStart"))) {
            params.put("endTimeStart", DateUtils.dateTime("yyyy-MM-dd HH:mm:ss", (String)params.get("endTimeStart")).getTime());
        }
        if (null != params.get("endTimeEnd")
                && !"".equals(params.get("endTimeEnd"))) {
            params.put("endTimeEnd", DateUtils.dateTime("yyyy-MM-dd HH:mm:ss", (String)params.get("endTimeEnd")).getTime());
        }
        // 通话时长（分钟）
        if (null != params.get("timeLenStart")
                && !"".equals(params.get("timeLenStart"))) {
            params.put("timeLenStart", Double.valueOf((String)params.get("timeLenStart")) * 60 * 1000L);
        }
        if (null != params.get("timeLenEnd")
                && !"".equals(params.get("timeLenEnd"))) {
            params.put("timeLenEnd", Double.valueOf((String)params.get("timeLenEnd")) * 60 * 1000L);
        }
        // 通话时长（秒）
        if (null != params.get("timeLenSecondStart")
                && !"".equals(params.get("timeLenSecondStart"))) {
            params.put("timeLenStart", Double.valueOf((String)params.get("timeLenSecondStart")) * 1000L);
        }
        if (null != params.get("timeLenSecondEnd")
                && !"".equals(params.get("timeLenSecondEnd"))) {
            params.put("timeLenEnd", Double.valueOf((String)params.get("timeLenSecondEnd")) * 1000L);
        }
        ccOutboundCdr.setParams(params);
        return ccOutboundCdrMapper.selectCcOutboundCdrList(ccOutboundCdr);
    }

    /**
     * 新增外呼记录
     * 
     * @param ccOutboundCdr 外呼记录
     * @return 结果
     */
    @Override
    public int insertCcOutboundCdr(CcOutboundCdr ccOutboundCdr)
    {
        // 对opnum字段进行URL解码，防止乱码
        if(StringUtils.isNotBlank(ccOutboundCdr.getOpnum())){
            try {
                ccOutboundCdr.setOpnum(URLDecoder.decode(ccOutboundCdr.getOpnum(), "UTF-8"));
            } catch (Exception e) {}
        }
        return ccOutboundCdrMapper.insertCcOutboundCdr(ccOutboundCdr);
    }

    /**
     * 修改外呼记录
     * 
     * @param ccOutboundCdr 外呼记录
     * @return 结果
     */
    @Override
    public int updateCcOutboundCdr(CcOutboundCdr ccOutboundCdr)
    {
        return ccOutboundCdrMapper.updateCcOutboundCdr(ccOutboundCdr);
    }

    /**
     * 批量删除外呼记录
     * 
     * @param ids 需要删除的外呼记录主键
     * @return 结果
     */
    @Override
    public int deleteCcOutboundCdrByIds(String ids)
    {
        return ccOutboundCdrMapper.deleteCcOutboundCdrByIds(Convert.toStrArray(ids));
    }

    /**
     * 删除外呼记录信息
     * 
     * @param id 外呼记录主键
     * @return 结果
     */
    @Override
    public int deleteCcOutboundCdrById(String id)
    {
        return ccOutboundCdrMapper.deleteCcOutboundCdrById(id);
    }
    /**
     * 查询外呼记录列表
     *
     * @param ccOutboundCdr 外呼记录
     * @return 外呼记录
     */
    @Override
    public List<CcOutboundCdr> selectCcOutboundCdrYlrzList(CcOutboundCdr ccOutboundCdr)
    {
        Map<String, Object> params = ccOutboundCdr.getParams();
        if (null == params) {
            params = new HashMap<>();
        }
        if (null != params.get("timeLenStart")
                && !"".equals(params.get("timeLenStart"))) {
            params.put("timeLenStart", Double.valueOf((String)params.get("timeLenStart")) * 60 * 1000L);
        }
        if (null != params.get("timeLenEnd")
                && !"".equals(params.get("timeLenEnd"))) {
            params.put("timeLenEnd", Double.valueOf((String)params.get("timeLenEnd")) * 60 * 1000L);
        }
        if (null != params.get("calloutTimeStart")
                && !"".equals(params.get("calloutTimeStart"))) {
            params.put("calloutTimeStart", DateUtils.dateTime("yyyy-MM-dd HH:mm:ss", (String)params.get("calloutTimeStart")).getTime());
        }
        if (null != params.get("calloutTimeEnd")
                && !"".equals(params.get("calloutTimeEnd"))) {
            params.put("calloutTimeEnd", DateUtils.dateTime("yyyy-MM-dd HH:mm:ss", (String)params.get("calloutTimeEnd")).getTime());
        }
        if (null != params.get("answeredTimeStart")
                && !"".equals(params.get("answeredTimeStart"))) {
            params.put("answeredTimeStart", DateUtils.dateTime("yyyy-MM-dd HH:mm:ss", (String)params.get("answeredTimeStart")).getTime());
        }
        if (null != params.get("answeredTimeEnd")
                && !"".equals(params.get("answeredTimeEnd"))) {
            params.put("answeredTimeEnd", DateUtils.dateTime("yyyy-MM-dd HH:mm:ss", (String)params.get("answeredTimeEnd")).getTime());
        }
        if (null != params.get("endTimeStart")
                && !"".equals(params.get("endTimeStart"))) {
            params.put("endTimeStart", DateUtils.dateTime("yyyy-MM-dd HH:mm:ss", (String)params.get("endTimeStart")).getTime());
        }
        if (null != params.get("endTimeEnd")
                && !"".equals(params.get("endTimeEnd"))) {
            params.put("endTimeEnd", DateUtils.dateTime("yyyy-MM-dd HH:mm:ss", (String)params.get("endTimeEnd")).getTime());
        }
        ccOutboundCdr.setParams(params);
        return ccOutboundCdrMapper.selectCcOutboundCdrList(ccOutboundCdr);
    }

    @Override
    public List<CcOutboundCdr> selectCcOutboundCdrByIds(List<String> ids) {
        return ccOutboundCdrMapper.selectCcOutboundCdrByIds(ids);
    }

    @Override
    public List<CcOutboundCdr> selectMergedCcOutboundCdrByUuids(List<String> uuids) {
        if (CollectionUtils.isEmpty(uuids)) {
            return Collections.emptyList();
        }
        List<String> distinctUuids = uuids.stream()
                .filter(StringUtils::isNotBlank)
                .distinct()
                .collect(Collectors.toList());
        if (distinctUuids.isEmpty()) {
            return Collections.emptyList();
        }
        List<CcOutboundCdr> list = ccOutboundCdrMapper.selectCcOutboundCdrByUuids(distinctUuids);
        if (CollectionUtils.isEmpty(list)) {
            return Collections.emptyList();
        }
        Map<String, List<CcOutboundCdr>> grouped = list.stream()
                .filter(Objects::nonNull)
                .filter(item -> StringUtils.isNotBlank(item.getUuid()))
                .collect(Collectors.groupingBy(CcOutboundCdr::getUuid, LinkedHashMap::new, Collectors.toList()));

        List<CcOutboundCdr> merged = new ArrayList<>(grouped.size());
        for (List<CcOutboundCdr> segments : grouped.values()) {
            merged.add(mergeReconnectSegments(segments));
        }
        return merged;
    }

    /**
     * 断线重连多段合并：end_time 倒序后，取最晚一条为底；
     * start_time、answered_time 取最早一条；time_len、time_len_valid 全部分段累加。
     */
    private CcOutboundCdr mergeReconnectSegments(List<CcOutboundCdr> segments) {
        if (segments.size() == 1) {
            return segments.get(0);
        }
        List<CcOutboundCdr> ordered = segments.stream()
                .sorted(Comparator.comparing(CcOutboundCdr::getEndTime, Comparator.nullsLast(Long::compareTo)).reversed())
                .collect(Collectors.toList());
        CcOutboundCdr latest = ordered.get(0);
        CcOutboundCdr earliest = ordered.get(ordered.size() - 1);
        latest.setStartTime(earliest.getStartTime());
        latest.setAnsweredTime(earliest.getAnsweredTime());
        long timeLenSum = 0L;
        long timeLenValidSum = 0L;
        for (CcOutboundCdr item : ordered) {
            timeLenSum += item.getTimeLen() == null ? 0L : item.getTimeLen();
            timeLenValidSum += item.getTimeLenValid() == null ? 0L : item.getTimeLenValid();
        }
        latest.setTimeLen(timeLenSum);
        latest.setTimeLenValid(timeLenValidSum);
        return latest;
    }
}
