package com.sckw.fleet.service;

import com.sckw.core.common.enums.enums.DictTypeEnum;
import com.sckw.core.exception.SystemException;
import com.sckw.core.model.constant.Global;
import com.sckw.core.utils.BeanUtils;
import com.sckw.core.utils.CollectionUtils;
import com.sckw.core.utils.RegularUtils;
import com.sckw.core.utils.StringUtils;
import com.sckw.core.web.constant.HttpStatus;
import com.sckw.core.web.context.LoginUserHolder;
import com.sckw.core.web.response.HttpResult;
import com.sckw.fleet.dao.KwfDriverMapper;
import com.sckw.fleet.dao.KwfTruckMapper;
import com.sckw.fleet.dao.KwfTruckReportMapper;
import com.sckw.fleet.model.KwfDriver;
import com.sckw.fleet.model.KwfTruck;
import com.sckw.fleet.model.KwfTruckReport;
import com.sckw.fleet.model.dto.KwfChangeFleetDto;
import com.sckw.fleet.model.dto.KwfDriverDto;
import com.sckw.fleet.model.dto.KwfTruckDto;
import com.sckw.fleet.model.dto.KwfTruckReportDto;
import com.sckw.fleet.model.vo.KwfTableTopCount;
import com.sckw.fleet.model.vo.KwfTruckReportVo;
import com.sckw.system.api.RemoteSystemService;
import com.sckw.system.api.model.dto.res.EntCacheResDto;
import com.sckw.system.api.model.dto.res.SysDictResDto;
import com.sckw.system.api.model.dto.res.UserCacheResDto;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @author zk
 * @desc 车辆上报
 * @date 2023/7/15 0006
 */
@Service
public class KwfTruckReportService {

    @Autowired
    KwfTruckMapper truckDao;
    @Autowired
    KwfDriverMapper driverDao;
    @Autowired
    KwfTruckReportMapper truckReportDao;
    @Autowired
    KwfDriverService driverService;
    @Autowired
    KwfTruckService truckService;
    @DubboReference(version = "2.0.0", group = "design", check = false)
    private RemoteSystemService remoteSystemService;

    /**
     * @param key 主键id
     * @desc 根据主键查询
     * @author zk
     * @date 2023/7/15
     **/
    public KwfTruckReport selectByKey(Long key) {
        return null;
    }

    /**
     * @param params 参数
     * @desc 统计
     * @author zk
     * @date 2023/7/11
     **/
    public Map statistics(Map<String, Object> params) {
        /**统计数据**/
        List<KwfTableTopCount> counts = truckReportDao.statistics(params);
        long tatol = 0;
        for (KwfTableTopCount topCount:counts) {
            tatol += topCount.getTotal();
        }

        /**全部数据-处理**/
        List<KwfTableTopCount> countList = new ArrayList();
        KwfTableTopCount allCount = new KwfTableTopCount();
        allCount.setValue(String.valueOf(Global.NUMERICAL_ZERO));
        allCount.setTotal(tatol);
        allCount.setName("全部");
        countList.add(allCount);

        /**数据处理**/
        Map<String, Integer> statusMap = new HashMap(){{put("正常", 1); put("临时", 2); put("异常", 3);}};
        for(Map.Entry<String, Integer> entry:statusMap.entrySet()){
            System.out.println(entry.getKey()+"--->"+entry.getValue());
            KwfTableTopCount count = new KwfTableTopCount();
            for (KwfTableTopCount topCount:counts) {
                if (Integer.parseInt(topCount.getValue()) == entry.getValue()) {
                    BeanUtils.copyProperties(topCount, count);
                }
            }
            count.setName(entry.getKey());
            count.setValue(String.valueOf(entry.getValue()));
            countList.add(count);
        }

        /**数据组装**/
        Map tableCount = new HashMap();
        tableCount.put("tableTop", countList);
        tableCount.put("tableBottom", tatol);
        return tableCount;
    }

    /**
     * @param params 分页参数
     * @desc 分页查询
     * @author zk
     * @date 2023/7/15
     **/
    public List<KwfTruckReportVo> findPage(Map<String, Object> params) {
        /**查询分页数据**/
        List<KwfTruckReportVo> trucks = truckReportDao.findPage(params);
        if (CollectionUtils.isEmpty(trucks)) {
            return trucks;
        }

        /**获取查询数据**/
        String pound = Global.POUND;
        List<Long> createBys = new ArrayList<>();
        List<Long> entIds = new ArrayList<>();
        List<String> dictKey = new ArrayList<>();
        for (KwfTruckReportVo truck:trucks) {
            createBys.add(Long.parseLong(truck.getCreateBy()));
            entIds.add(Long.parseLong(truck.getDriverEntId()));
            entIds.add(Long.parseLong(truck.getTruckEntId()));
            dictKey.add(DictTypeEnum.COLOR_TYPE.getType() + pound + truck.getColor());
            dictKey.add(DictTypeEnum.TRUCK_TYPE.getType() + pound + truck.getTruckType());
        }
        //用户数据集
        createBys = createBys.stream().distinct().collect(Collectors.toList());
        Map<Long, UserCacheResDto> users = remoteSystemService.queryUserCacheMapByIds(createBys);
        //企业数据集
        entIds = entIds.stream().distinct().collect(Collectors.toList());
        Map<Long, EntCacheResDto> ents = remoteSystemService.queryEntCacheMapByIds(entIds);
        //数据字典
        dictKey = dictKey.stream().distinct().collect(Collectors.toList());
        Map<String, SysDictResDto> dicts = remoteSystemService.queryDictMapByTypeValues(String.join(",", dictKey));

        /**数据组装**/
        for (KwfTruckReportVo truck:trucks) {
            UserCacheResDto user = users == null ? null : users.get(Long.parseLong(truck.getCreateBy()));
            EntCacheResDto ent = ents == null ? null : ents.get(Long.parseLong(truck.getDriverEntId()));
            SysDictResDto color = dicts == null ? null : dicts.get(DictTypeEnum.COLOR_TYPE.getType() + pound + truck.getColor());
            SysDictResDto type = dicts == null ? null : dicts.get(DictTypeEnum.COLOR_TYPE.getType() + pound + truck.getTruckType());
            truck.setCreateByName(user != null ? user.getName() : null);
            truck.setDriverFirmName(ent != null ? ent.getFirmName() : null);
            ent = ents == null ? null : ents.get(Long.parseLong(truck.getTruckEntId()));
            truck.setTruckFirmName(ent != null ? ent.getFirmName() : null);
            truck.setColorName(color != null ? color.getLabel() : null);
            truck.setTruckTypeName(type != null ? type.getLabel() : null);
        }
        return trucks;
    }

    /**
     * @param {}
     * @description 导出
     * @author zk
     * @date 2023/07/11
     **/
    public HttpResult importExcel(MultipartFile file) {
        return null;
    }

    /**
     * @param params 参数
     * @desc 新增车辆上报
     * @author zk
     * @date 2023/7/15
     **/
    public HttpResult add(List<KwfTruckReportDto> params) {
        /**数据校验**/
        if (CollectionUtils.isEmpty(params)) {
            return HttpResult.error("请选择需要上报的数据！");
        }

        for (KwfTruckReportDto reportDto:params){
            boolean bool = checkReport(reportDto);
            if (!bool) {
                return HttpResult.error("上报数据已存在，请重新识别！");
            }
        }

        /**数据更新**/
        int count = 0;
        for (KwfTruckReportDto reportDto:params){
            KwfTruckReport truckReport = new KwfTruckReport();
            truckReport.setEntId(LoginUserHolder.getEntId());

            /**车辆信息**/
            //校验车辆档案是否存在
            List<Map<String, Object>> trucks = truckDao.findList(new HashMap() {{
                put("truckNo", reportDto.getTruckNo());
            }});
            if (CollectionUtils.isEmpty(trucks)) {
                //新增车辆档案
                KwfTruckDto truckDto = new KwfTruckDto();
                truckDto.setTruckNo(reportDto.getTruckNo());
                HttpResult result = truckService.add(truckDto);
                if (result.getCode() != HttpStatus.SUCCESS_CODE) {
                    return result;
                }
                KwfTruck truck = (KwfTruck) result.getData();
                truckReport.setTruckId(truck.getId());
            } else {
                //校验车辆是否已上报
                Map<String, Object> truck = trucks.get(0);
                Object truckId = truck.get("id");
                List<Map<String, Object>> reports = truckReportDao.findList(new HashMap() {{
                    put("truckId", truckId);
                    put("entId", LoginUserHolder.getEntId());
                }});
                if (CollectionUtils.isEmpty(reports)) {
                    truckReport.setTruckId(Long.parseLong(String.valueOf(truckId)));
                } else {
                    continue;
                }
            }

            /**档案信息**/
            //校验司机档案是否存在
            List<Map<String, Object>> drivers = driverDao.findList(new HashMap() {{
                put("phone", reportDto.getPhone());
            }});
            if (CollectionUtils.isEmpty(drivers)) {
                //新增司机档案
                KwfDriverDto driverDto = new KwfDriverDto();
                driverDto.setName(reportDto.getName());
                driverDto.setPhone(reportDto.getPhone());
                driverDto.setIdcard(reportDto.getIdcard());
                HttpResult result = driverService.add(driverDto);
                if (result.getCode() != HttpStatus.SUCCESS_CODE) {
                    return result;
                }
                KwfDriver driver = (KwfDriver) result.getData();
                truckReport.setDriverId(driver.getId());
            } else {
                //校验司机是否已上报
                Map<String, Object> driver = trucks.get(0);
                Object driverId = driver.get("id");
                List<Map<String, Object>> reports = truckReportDao.findList(new HashMap() {{
                    put("driverId", driverId);
                    put("entId", LoginUserHolder.getEntId());
                }});
                if (CollectionUtils.isEmpty(reports)) {
                    truckReport.setDriverId(Long.parseLong(String.valueOf(driverId)));
                } else {
                    continue;
                }
            }

            count += truckReportDao.insert(truckReport);
        }

        return HttpResult.ok("车辆上报成功"+count+"条！");
    }

    /**
     * @param params 参数
     * @desc 车辆上报修改
     * @author zk
     * @date 2023/7/15
     **/
    public HttpResult update(KwfTruckReport params) {
        /**数据校验**/
        if (StringUtils.isBlank(params.getId())) {
            return HttpResult.error("参数不正确！");
        }
        KwfTruckReport truckReport = truckReportDao.selectById(params.getId());
        if (truckReport == null) {
            return HttpResult.error("信息已不存在！");
        }

        /**更新**/
        List<Map<String, Object>> reports = truckReportDao.findList(new HashMap() {{
            put("driverId", params.getDriverId());
            put("entId", LoginUserHolder.getEntId());
        }});
        if (!CollectionUtils.isEmpty(reports)) {
            Map<String, Object> report = reports.get(0);
            Long id = StringUtils.isBlank(report.get("id")) ? 0 : Long.parseLong(String.valueOf(report.get("id")));
            if (!id.equals(params.getId())) {
                return HttpResult.error("司机已关联车辆！");
            }
        }

        /**更新数据**/
        int count = truckReportDao.updateById(params);
        return count > 0 ? HttpResult.ok("修改成功！") : HttpResult.error("修改失败！");
    }

    /**
     * @param {ids：主键ID（多个以逗号隔开）}
     * @desc 删除
     * @author zk
     * @date 2023/7/15
     **/
    public HttpResult del(String ids) {
        /**数据校验**/
        if (StringUtils.isBlank(ids)) {
            return HttpResult.error("请选择要删除的数据！");
        }

        /**数据组装**/
        String[] idArray = ids.split(",");
        for (String id : idArray) {
            KwfTruckReport truckReport = truckReportDao.selectById(id);
            if (truckReport != null) {
                truckReport.setDelFlag(Global.YES);
                if (truckReportDao.updateById(truckReport) <= 0) {
                    throw new SystemException(HttpStatus.CRUD_FAIL_CODE, HttpStatus.DELETE_FAIL);
                }
            } else {
                return HttpResult.error("选择删除的数据已不存在！");
            }
        }
        return HttpResult.ok("删除成功！");
    }

    /**
     * @param params
     * @desc 变更车队
     * @author zk
     * @date 2023/7/18
     **/
    public HttpResult changeFleet(KwfChangeFleetDto params) {
        KwfTruckReport truckReport = truckReportDao.selectById(params.getId());
        if (truckReport == null) {
            return HttpResult.error("信息已不存在！");
        }

        //更新司机所属车队班组
        HttpResult result = driverService.driverFleetEdit(truckReport.getDriverId(), params.getFleetId());
        if (result.getCode() == HttpStatus.SUCCESS_CODE) {
            //更新车辆所属车队班组
            result = truckService.truckFleetEdit(truckReport.getTruckId(), params.getFleetId());
        }

        return result;
    }

    /**
     * @param params 上报信息
     * @desc 校验上报
     * @author zk
     * @date 2023/7/18
     **/
    public HttpResult checkReports(List<String> params) {
        /**数据校验**/
        if (CollectionUtils.isEmpty(params)) {
            return HttpResult.error("请选择需要上报的数据！");
        }

        //有效上报信息
        List<KwfTruckReportDto> effective = new ArrayList();
        //已有运力/识别失败
        int haveCount = 0, errorCount = 0;
        for (String str:params){
            /**识别上报数据**/
            KwfTruckReportDto reportDto = analysis(str);
            if (reportDto == null) {
                errorCount ++;
                continue;
            }

            /**车辆信息**/
            //校验车辆档案是否存在
            List<Map<String, Object>> trucks = truckDao.findList(new HashMap() {{
                put("truckNo", reportDto.getTruckNo());
            }});
            if (!CollectionUtils.isEmpty(trucks)) {
                //校验车辆是否已上报
                Map<String, Object> truck = trucks.get(0);
                Object truckId = truck.get("id");
                List<Map<String, Object>> reports = truckReportDao.findList(new HashMap() {{
                    put("truckId", truckId);
                    put("entId", LoginUserHolder.getEntId());
                }});
                if (!CollectionUtils.isEmpty(reports)) {
                    haveCount ++;
                    continue;
                }
            }

            /**档案信息**/
            //校验司机档案是否存在
            List<Map<String, Object>> drivers = driverDao.findList(new HashMap() {{
                put("phone", reportDto.getPhone());
            }});
            if (!CollectionUtils.isEmpty(drivers)) {
                //校验司机是否已上报
                Map<String, Object> driver = trucks.get(0);
                Object driverId = driver.get("id");
                List<Map<String, Object>> reports = truckReportDao.findList(new HashMap() {{
                    put("driverId", driverId);
                    put("entId", LoginUserHolder.getEntId());
                }});
                if (!CollectionUtils.isEmpty(reports)) {
                    haveCount ++;
                    continue;
                }
            }

            effective.add(reportDto);
        }

        /**返回数据**/
        Map<String, Object> resultMap = new HashMap<>();
        resultMap.put("haveCount", haveCount);
        resultMap.put("errorCount", errorCount);
        resultMap.put("fail", haveCount + errorCount);
        resultMap.put("success", effective.size());
        resultMap.put("list", effective);

        return HttpResult.ok(resultMap);
    }

    /**
     * @param reportDto 上报信息
     * @desc 校验司机和车辆是否已上报
     * @author zk
     * @date 2023/7/18
     **/
    public boolean checkReport(KwfTruckReportDto reportDto) {
        /**车辆信息**/
        //校验车辆档案是否存在
        List<Map<String, Object>> trucks = truckDao.findList(new HashMap() {{
            put("truckNo", reportDto.getTruckNo());
        }});
        if (!CollectionUtils.isEmpty(trucks)) {
            //校验车辆是否已上报
            Map<String, Object> truck = trucks.get(0);
            Object truckId = truck.get("id");
            List<Map<String, Object>> reports = truckReportDao.findList(new HashMap() {{
                put("truckId", truckId);
                put("entId", LoginUserHolder.getEntId());
            }});
            if (!CollectionUtils.isEmpty(reports)) {
                return false;
            }
        }

        /**档案信息**/
        //校验司机档案是否存在
        List<Map<String, Object>> drivers = driverDao.findList(new HashMap() {{
            put("phone", reportDto.getPhone());
        }});
        if (!CollectionUtils.isEmpty(drivers)) {
            //校验司机是否已上报
            Map<String, Object> driver = trucks.get(0);
            Object driverId = driver.get("id");
            List<Map<String, Object>> reports = truckReportDao.findList(new HashMap() {{
                put("driverId", driverId);
                put("entId", LoginUserHolder.getEntId());
            }});
            if (!CollectionUtils.isEmpty(reports)) {
                return false;
            }
        }
        return true;
    }

    /**
     * @param str 上报字符串
     * @desc 上报数据识别
     * @author zk
     * @date 2023/7/18
     **/
    public KwfTruckReportDto analysis(String str) {
        /**识别上报数据**/
        KwfTruckReportDto reportDto = new KwfTruckReportDto();
        //非控校验
        if (StringUtils.isBlank(str) || StringUtils.isBlank(str.trim())) {
            return null;
        }
        //字符截取-英文逗号/中文逗号
        String[] strArray = str.split(Global.COMMA1);
        strArray = (strArray == null || strArray.length == 0) ? str.split(Global.COMMA) : strArray;
        if (strArray == null || strArray.length == 0 || strArray.length != 5 ) {
            return null;
        }

        /**数据校验**/
        //车牌号-非空/长度为7
        String truckNo = strArray[0];
        if (StringUtils.isBlank(truckNo) || truckNo.trim().length() != 7) {
            return null;
        }

        //司机姓名-非空
        String name = strArray[1];
        if (StringUtils.isBlank(name) || name.trim().length() == 0) {
            return null;
        }

        //司机电话-非空/手机号正则校验
        String phone = strArray[2];
        if (StringUtils.isBlank(phone) || !RegularUtils.matchs(RegularUtils.PHONE_REG, phone)) {
            return null;
        }

        //身份证号-非空/身份证正则校验
        String idcard = strArray[3];
        if (StringUtils.isBlank(idcard) || !RegularUtils.matchs(RegularUtils.IDCARD, idcard)) {
            return null;
        }

        //核定载量/吨-非空/数值正则校验
        String actualWeight = strArray[4];
        if (StringUtils.isBlank(actualWeight) || !RegularUtils.matchs(RegularUtils.DECIMAL_REG, actualWeight)) {
            return null;
        }

        reportDto.setTruckNo(truckNo);
        reportDto.setName(name);
        reportDto.setPhone(phone);
        reportDto.setIdcard(idcard);
        reportDto.setActualWeight(new BigDecimal(actualWeight));
        return reportDto;
    }
}
