package com.chushang.inspection.work.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.chushang.common.core.constant.SecurityConstants;
import com.chushang.common.core.context.SecurityContextHolder;
import com.chushang.common.core.exception.ResultException;
import com.chushang.common.core.exception.utils.AssertUtil;
import com.chushang.common.core.text.Convert;
import com.chushang.common.core.util.StringUtils;
import com.chushang.common.core.web.AjaxResult;
import com.chushang.common.core.web.Result;
import com.chushang.common.dict.utils.DictUtils;
import com.chushang.common.excel.utils.ExcelUtils;
import com.chushang.common.mq.produce.MqProduceService;
import com.chushang.common.mybatis.page.CommonParam;
import com.chushang.common.mybatis.utils.PageResult;
import com.chushang.common.mybatis.utils.WrapperUtils;
import com.chushang.inspection.project.po.PollingTask;
import com.chushang.inspection.project.service.PollingTaskService;
import com.chushang.inspection.terminal.po.Store;
import com.chushang.inspection.terminal.po.Terminal;
import com.chushang.inspection.terminal.service.StoreService;
import com.chushang.inspection.terminal.service.TerminalService;
import com.chushang.inspection.work.dto.WrkInfoPhoneImportDTO;
import com.chushang.inspection.work.query.WrkInfoQuery;
import com.chushang.inspection.work.service.WrkInfoPhoneService;
import com.chushang.oss.entity.dto.UploadBytesDTO;
import com.chushang.oss.entity.vo.FileSourceVo;
import com.chushang.oss.feign.RemoteOssService;
import com.chushang.security.utils.SecurityUtils;
import com.chushang.system.feign.RemoteUserService;
import com.chushang.task.entity.dto.CreateTaskDTO;
import com.chushang.task.enums.ServiceEnum;
import com.chushang.task.enums.TaskTypeEnum;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.chushang.inspection.work.mapper.WrkInfoPhoneMapper;
import com.chushang.inspection.work.po.WrkInfoPhone;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import java.io.ByteArrayOutputStream;
import java.util.*;
import java.util.stream.Collectors;

/**
  * @auther: zhao
  * @date: 2024/6/26 17:26
  */
@Slf4j
@Service
public class WrkInfoPhoneServiceImpl extends ServiceImpl<WrkInfoPhoneMapper, WrkInfoPhone> implements WrkInfoPhoneService {

    @Resource
    StoreService storeService;
    @Resource
    PollingTaskService pollingTaskService;
    @Resource
    TerminalService terminalService;
    @Resource
    RemoteUserService remoteUserService;
    @Resource
    RemoteOssService remoteOssService;
    @Resource
    MqProduceService mqProduceService;

    @Override
    public PageResult pageList(WrkInfoQuery query) {
        CommonParam commonParam = CommonParam.buildPageRequest();
        LambdaQueryWrapper<WrkInfoPhone> infoPhoneSql = WrapperUtils.builder(query, commonParam);
        IPage<WrkInfoPhone> page = this.page(
                new com.baomidou.mybatisplus.extension.plugins.pagination.Page<>(commonParam.getPage(), commonParam.getLimit()),
                infoPhoneSql
        );
        return new PageResult(page);
    }

    /**
     * 导入读
     * @param file
     * @return
     */
    @Override
    public List<WrkInfoPhoneImportDTO> importRead(MultipartFile file) {
        return ExcelUtils.read(file, WrkInfoPhoneImportDTO.class);
    }

    /**
     * 导入 存
     */
    @Override
    public AjaxResult importSave(List<WrkInfoPhoneImportDTO> importReadList, Long taskId, Long lowerTaskId) {

        Map<String, Object> bodyMap = new HashMap<>();
        bodyMap.put("taskId", taskId);
        bodyMap.put("lowerTaskId", lowerTaskId);
        bodyMap.put("importReadList", importReadList);
        CreateTaskDTO task = CreateTaskDTO.builder()
                .params(JSON.toJSONString(bodyMap))
                .taskName("电话工单导入")
                .applicationName(ServiceEnum.INSPECTION)
                .methodName("savePhoneInfo")
                .className(this.getClass().getName())
                .deptId(SecurityUtils.getDeptId())
                .taskType(TaskTypeEnum.DOWN)
                .remark("电话工单导入")
                .createBy(SecurityUtils.getUsername())
                .userId(SecurityUtils.getUserId())
                .build();
//        remoteTaskService.createTask(task, SecurityConstants.INNER);
        mqProduceService.send(ServiceEnum.TASK.getServiceName(), task);
        return AjaxResult.success("导入成功, 请在后台任务中查看导入结果");
    }

    /**
     * 单条录入
     */
    @Override
    @Transactional
    public Long saveInfo(WrkInfoPhoneImportDTO info, Long taskId, Long lowerTaskId) {
        Result<Map<String, Long>> result = remoteUserService.getIdByUsernames(Set.of(info.getUserName()), SecurityConstants.INNER);
        AssertUtil.invalidate(!result.isSuccess() || CollectionUtil.isEmpty(result.getData()), "没有获取到业务员信息");

        Map<String, Long> idByUsernames = result.getData();
        PollingTask pollingTask = pollingTaskService.getById(taskId);
        PollingTask lowerTask = pollingTaskService.getById(lowerTaskId);
        AssertUtil.invalidate(ObjectUtil.isEmpty(pollingTask) || ObjectUtil.isEmpty(lowerTask), "没有获取到巡检任务信息");
        WrkInfoPhone wrkInfoPhone = convert(info, idByUsernames);
        wrkInfoPhone.setTaskId(taskId);
        wrkInfoPhone.setTaskName(pollingTask.getName());
        wrkInfoPhone.setLowerTaskId(lowerTaskId);
        wrkInfoPhone.setLowerTaskName(lowerTask.getName());
        String terminalNo = info.getTerminalNo();
        String storeNo = info.getStoreNo();
        String storeName = info.getStoreName();
        if (StringUtils.isNotEmpty(storeNo) && StringUtils.isNotEmpty(storeName)) {
            // 去获取唯一的 store 集合
            List<Store> list = storeService.list(
                    new LambdaQueryWrapper<Store>()
                            .eq(Store::getStoreNo, storeNo)
                            .eq(Store::getStoreName, storeName));
            // 不为空时走下一步
            if (CollectionUtil.isNotEmpty(list)) {
                if (list.size() > 1) {
                    AssertUtil.invalidate(true, "商户编号:" + storeNo + ",商户名称:" + storeName + "重复");
                } else {
                    Store storeEntity = list.get(0);
                    assert null != storeEntity;
                    // 获取 到了 商户编号, 商户id, 商户名称
                    wrkInfoPhone.setStoreId(storeEntity.getStoreId());
                    wrkInfoPhone.setStoreNo(storeEntity.getStoreNo());
                    wrkInfoPhone.setStoreName(storeEntity.getStoreName());
                }
            }
        }
        // 终端不为空
        if (StringUtils.isNotEmpty(terminalNo)) {
            List<Terminal> list = terminalService.list(
                    new LambdaQueryWrapper<Terminal>()
                            .eq(Terminal::getTerminalNo, terminalNo)
                            .eq(Terminal::getStoreNo, storeNo));
            if (CollectionUtil.isNotEmpty(list)) {
                if (list.size() > 1) {
                    AssertUtil.invalidate(true, "商户编号:" + storeNo + ",商户名称:" + storeName + "终端编号:" + terminalNo + " 重复");
                } else {
                    Terminal terminal = list.get(0);
                    assert null != terminal;
                    wrkInfoPhone.setTerminalType(terminal.getTerminalType());
                    wrkInfoPhone.setTerminalNo(terminal.getTerminalNo());
                    wrkInfoPhone.setTerminalId(terminal.getTerminalId());
                }
            }
            // 去获取唯一的 store 集合
        }
        save(wrkInfoPhone);
        return wrkInfoPhone.getWrkId();
    }

    @Override
    public Long updateInfo(WrkInfoPhoneImportDTO info, Long wrkId) {
        Result<Map<String, Long>> result = remoteUserService.getIdByUsernames(Set.of(info.getUserName()), SecurityConstants.INNER);
        AssertUtil.invalidate(!result.isSuccess() || CollectionUtil.isEmpty(result.getData()), "没有获取到业务员信息");

        Map<String, Long> idByUsernames = result.getData();
        WrkInfoPhone wrkInfoPhone = convert(info, idByUsernames);
        wrkInfoPhone.setWrkId(wrkId);
        String terminalNo = info.getTerminalNo();
        String storeNo = info.getStoreNo();
        String storeName = info.getStoreName();
        if (StringUtils.isNotEmpty(storeNo) && StringUtils.isNotEmpty(storeName)) {
            // 去获取唯一的 store 集合
            List<Store> list = storeService.list(
                    new LambdaQueryWrapper<Store>()
                            .eq(Store::getStoreNo, storeNo)
                            .eq(Store::getStoreName, storeName));
            // 不为空时走下一步
            if (CollectionUtil.isNotEmpty(list)) {
                if (list.size() > 1) {
                    AssertUtil.invalidate(true, "商户编号:" + storeNo + ",商户名称:" + storeName + "重复");
                } else {
                    Store storeEntity = list.get(0);
                    assert null != storeEntity;
                    // 获取 到了 商户编号, 商户id, 商户名称
                    wrkInfoPhone.setStoreId(storeEntity.getStoreId());
                    wrkInfoPhone.setStoreNo(storeEntity.getStoreNo());
                    wrkInfoPhone.setStoreName(storeEntity.getStoreName());
                }
            }
        }
        // 终端不为空
        if (StringUtils.isNotEmpty(terminalNo)) {
            List<Terminal> list = terminalService.list(
                    new LambdaQueryWrapper<Terminal>()
                            .eq(Terminal::getTerminalNo, terminalNo)
                            .eq(Terminal::getStoreNo, storeNo));
            if (CollectionUtil.isNotEmpty(list)) {
                if (list.size() > 1) {
                    AssertUtil.invalidate(true, "商户编号:" + storeNo + ",商户名称:" + storeName + "终端编号:" + terminalNo + " 重复");
                } else {
                    Terminal terminal = list.get(0);
                    assert null != terminal;
                    wrkInfoPhone.setTerminalType(terminal.getTerminalType());
                    wrkInfoPhone.setTerminalNo(terminal.getTerminalNo());
                    wrkInfoPhone.setTerminalId(terminal.getTerminalId());
                }
            }
            // 去获取唯一的 store 集合
        }
        updateById(wrkInfoPhone);

        return wrkId;
    }

    /**
     * 导入成功
     */
    @Transactional
    public Result<String> savePhoneInfo(String params)
    {
        if (StringUtils.isEmpty(params)){
            return Result.failed("获取信息为空");
        }
        JSONObject jsonObject = JSON.parseObject(params);
        Long taskId = jsonObject.getLong("taskId");
        Long lowerTaskId = jsonObject.getLong("lowerTaskId");
        List<WrkInfoPhoneImportDTO> importReadList = jsonObject.getList("importReadList", WrkInfoPhoneImportDTO.class);

        List<WrkInfoPhoneImportDTO> errList = new ArrayList<>();
        List<WrkInfoPhone> successList = new ArrayList<>();
        if (CollectionUtil.isNotEmpty(importReadList)) {
            Set<String> userNames = importReadList.stream().map(WrkInfoPhoneImportDTO::getUserName)
                    .filter(StringUtils::isNotEmpty)
                    .collect(Collectors.toSet());
            // 获取 用户名 + id
            Result<Map<String, Long>> result = remoteUserService.getIdByUsernames(userNames, SecurityConstants.INNER);
            if (!result.isSuccess() || CollectionUtil.isEmpty(result.getData())){
                return Result.failed("没有获取到业务员信息");
            }
            Map<String, Long> idByUsernames = result.getData();
            PollingTask pollingTask = pollingTaskService.getById(taskId);
            PollingTask lowerTask = pollingTaskService.getById(lowerTaskId);
            if (ObjectUtil.isEmpty(pollingTask) || ObjectUtil.isEmpty(lowerTask)){
                return Result.failed("没有获取到巡检任务信息");
            }
            for (WrkInfoPhoneImportDTO wrkInfoPhoneImportDTO : importReadList) {
                WrkInfoPhone wrkInfoPhone = convert(wrkInfoPhoneImportDTO, idByUsernames);
                wrkInfoPhone.setTaskId(taskId);
                wrkInfoPhone.setTaskName(pollingTask.getName());
                wrkInfoPhone.setLowerTaskId(lowerTaskId);
                wrkInfoPhone.setLowerTaskName(lowerTask.getName());
                String terminalNo = wrkInfoPhoneImportDTO.getTerminalNo();
                String storeNo = wrkInfoPhoneImportDTO.getStoreNo();
                String storeName = wrkInfoPhoneImportDTO.getStoreName();
                if (StringUtils.isNotEmpty(storeNo) && StringUtils.isNotEmpty(storeName)) {
                    // 去获取唯一的 store 集合
                    List<Store> list = storeService.list(
                            new LambdaQueryWrapper<Store>()
                                    .eq(Store::getStoreNo, storeNo)
                                            .eq(Store::getStoreName, storeName));
                    // 不为空时走下一步
                    if (CollectionUtil.isNotEmpty(list)) {
                        if (list.size() > 1) {
                            wrkInfoPhoneImportDTO.setImportResult("商户编号:" + storeNo + ",商户名称:" + storeName + "重复");
                            errList.add(wrkInfoPhoneImportDTO);
                        } else {
                            Store storeEntity = list.get(0);
                            assert null != storeEntity;
                            // 获取 到了 商户编号, 商户id, 商户名称
                            wrkInfoPhone.setStoreId(storeEntity.getStoreId());
                            wrkInfoPhone.setStoreNo(storeEntity.getStoreNo());
                            wrkInfoPhone.setStoreName(storeEntity.getStoreName());
                        }
                    }
                }
                // 终端不为空
                if (StringUtils.isNotEmpty(terminalNo)) {
                    List<Terminal> list = terminalService.list(
                            new LambdaQueryWrapper<Terminal>()
                                    .eq(Terminal::getTerminalNo, terminalNo)
                                            .eq(Terminal::getStoreNo, storeNo));
                    if (CollectionUtil.isNotEmpty(list)) {
                        if (list.size() > 1) {
                            wrkInfoPhoneImportDTO.setImportResult("商户编号:" + storeNo + ",商户名称:" + storeName + "终端编号:" + terminalNo + " 重复");
                            errList.add(wrkInfoPhoneImportDTO);
                        } else {
                            Terminal terminal = list.get(0);
                            assert null != terminal;
                            wrkInfoPhone.setTerminalType(terminal.getTerminalType());
                            wrkInfoPhone.setTerminalNo(terminal.getTerminalNo());
                            wrkInfoPhone.setTerminalId(terminal.getTerminalId());
                        }
                    }
                    // 去获取唯一的 store 集合
                }
                successList.add(wrkInfoPhone);
            }
        }
        if (CollectionUtil.isNotEmpty(successList)) {
            this.saveBatch(successList);
        }
        if (CollectionUtil.isNotEmpty(errList)) {
            try (ByteArrayOutputStream outputStream = new ByteArrayOutputStream()){
                ExcelUtils.exportList(outputStream, WrkInfoPhoneImportDTO.class, errList,"电话工单导入异常");
                Result<List<FileSourceVo>> ossResult = remoteOssService.uploadBytes(
                        UploadBytesDTO.builder().bytes(outputStream.toByteArray()).build()
                        , "", null, null, "phoneWrk", SecurityConstants.INNER);
                if (ossResult.isSuccess() && CollectionUtil.isNotEmpty(ossResult.getData())){
                    List<FileSourceVo> data = ossResult.getData();
                    FileSourceVo fileSourceVo = data.get(0);
                    return Result.ok(fileSourceVo.getFilePath(), "电话工单导入成功, 异常数据以导入文件系统, 请下载");
                }else {
                    return Result.failed(ossResult.getMsg());
                }
            }catch (Exception e){
                throw new ResultException("电话工单导入失败, 请联系系统管理员");
            }
        }
        return Result.ok("success");
    }

    private WrkInfoPhone convert(WrkInfoPhoneImportDTO wrkInfoPhoneImportDTO, Map<String, Long> idByUsernames)
    {
        WrkInfoPhone wrkInfoPhone = new WrkInfoPhone();
        wrkInfoPhone.setDelState(false);
        String userName = wrkInfoPhoneImportDTO.getUserName();
        //        理论上这个应该是框架 进行赋值的
        wrkInfoPhone.setDeptId(SecurityContextHolder.getDeptId());
        wrkInfoPhone.setUserId(idByUsernames.get(userName));
        wrkInfoPhone.setUserName(userName);
        wrkInfoPhone.setWrkStatus(1);
        wrkInfoPhone.setWorkSource(1);
        wrkInfoPhone.setWrkResult(wrkInfoPhone.getWrkResult());
        wrkInfoPhone.setWrkDetailResult(wrkInfoPhone.getWrkDetailResult());
        wrkInfoPhone.setWrkSpecificResult(wrkInfoPhone.getWrkSpecificResult());
        wrkInfoPhone.setWrkNo(IdUtil.getSnowflake().nextId() + "");
        String terminalType = DictUtils.getDictValue("terminal_type", wrkInfoPhoneImportDTO.getTerminalType());
        wrkInfoPhone.setTerminalType(Convert.toInt(terminalType));
        wrkInfoPhone.setDisposeTime(wrkInfoPhoneImportDTO.getDisposeTime());
        return wrkInfoPhone;
    }

}
