package com.om.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.PageUtil;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.obs.services.model.TemporarySignatureRequest;
import com.om.entity.dto.*;
import com.om.entity.po.*;
import com.om.entity.vo.DiagnosisVersionSearchVO;
import com.om.entity.vo.DiagnosisVersionVO;
import com.om.entity.vo.DignosisPageVO;
import com.om.exception.BadReqException;
import com.om.exception.BizException;
import com.om.mapper.DiagnosisVersionDescribeMapper;
import com.om.mapper.DiagnosisVersionInfoMapper;
import com.om.service.*;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.om.utils.*;
import io.swagger.v3.oas.annotations.parameters.RequestBody;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.PathVariable;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author bmmx
 * @since 2024-03-06
 */
@Service
@Slf4j
public class DiagnosisVersionInfoServiceImpl extends ServiceImpl<DiagnosisVersionInfoMapper, DiagnosisVersionInfo> implements IDiagnosisVersionInfoService {

    @Resource
    IDiagnosisVersionDescribeService describeService;
    @Resource
    IBrandService brandService;
    @Resource
    IClientService clientService;
    @Resource
    IUserService userService;
    @Resource
    IDiagClientsService diagClientsService;

    @Resource
    private JwtUtils jwtUtils;

    @Resource
    private HuaweiObsUtil obsUtil;

    @Resource
    private PushUtil pushUtil;

    @Override
    @Transactional
    public Result add(DiagnosisVersionVO diagnosisVersionVO) {
        DiagnosisVersionInfo info = new DiagnosisVersionInfo();
        //客户端编号,需要取id，后面在进行设置
        String[] clientNums = diagnosisVersionVO.getClientNums();
        StringBuffer sb = new StringBuffer();
        for (int i = 0; i < clientNums.length; i++) {
            sb.append(clientNums[i]);
            if (clientNums.length != 1 && i != clientNums.length - 1){
                sb.append(",");
            }
        }
        //文件地址
        info.setFile(diagnosisVersionVO.getFileUrl());
        //文件大小
        info.setDiagnosisFileSize(diagnosisVersionVO.getDiagnosisFileSize());
        //品牌代码
        info.setBrandCode(diagnosisVersionVO.getBrandCode());
        info.setClientNumber(sb.toString());
        //诊断程序名称
        info.setDiagnosisName(diagnosisVersionVO.getDiagnosisName());
        //程序状态
        info.setStatus(0);
        //设置用户名
        info.setUsername(diagnosisVersionVO.getUsername());
        //版本号
        info.setVersion(diagnosisVersionVO.getVersion());
        //保存地址
        info.setSavePath(diagnosisVersionVO.getSavePath());
        info.setFileName(diagnosisVersionVO.getFileName());
        info.setLifecycle(0);
        info.setCreateTime(LocalDateTime.now());
        info.setUpdateTime(LocalDateTime.now());
        //保存
        this.save(info);




        LambdaQueryWrapper<DiagnosisVersionInfo> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(DiagnosisVersionInfo::getId, info.getId());
        //保存后获取
        DiagnosisVersionInfo versionInfo = getOne(queryWrapper);
        log.info("==========={}=========", versionInfo);

        for (int i = 0; i < diagnosisVersionVO.getDescriptionList().length; i++) {
            DiagnosisVersionDescribe describe = new DiagnosisVersionDescribe();
            describe.setDiagnosisId(versionInfo.getId());
            describe.setDescription(diagnosisVersionVO.getDescriptionList()[i]);
            describe.setLanguage(diagnosisVersionVO.getLanguage()[i]);
            describeService.save(describe);
        }
        for (int i = 0; i < diagnosisVersionVO.getClientNums().length; i++) {
            DiagClients diagClients = new DiagClients();
            diagClients.setDiagId(versionInfo.getId());
            diagClients.setClientNum(diagnosisVersionVO.getClientNums()[i]);
            diagClientsService.save(diagClients);
        }


        return Result.ok();
    }

    @Override
    public Result downloadFile(Integer id) {
        DiagnosisVersionInfo diagnosisVersionInfo = this.getById(id);
        if (BeanUtil.isEmpty(diagnosisVersionInfo)) {
            throw new BadReqException("该诊断程序不存在");
        }
        String uploadUrl = obsUtil.getUploadUrl(diagnosisVersionInfo.getFileName(), "program");
        return Result.ok(uploadUrl);
    }

    @Override
    public Result edit(DiagnosisVersionVO diagnosisVersionVO) {
        Integer diaId = diagnosisVersionVO.getId();
        DiagnosisVersionVO versionVO = getVO(diaId);
        BeanUtil.copyProperties(diagnosisVersionVO, versionVO);

        DiagnosisVersionInfo info = new DiagnosisVersionInfo();
        DiagnosisVersionInfo info2 = this.getById(diaId);//查询到copy过去
        BeanUtil.copyProperties(info2, info);
        BeanUtil.copyProperties(diagnosisVersionVO, info);
        log.info("----修改用户信息{}-----", info);
        LambdaQueryWrapper<DiagnosisVersionInfo> queryWrappeInfo = new LambdaQueryWrapper<>();
        queryWrappeInfo.eq(DiagnosisVersionInfo::getId, diaId);

        this.update(info, queryWrappeInfo);

        //客户端编号也要更改
        String[] clientNums = diagnosisVersionVO.getClientNums();
        LambdaQueryWrapper<DiagClients> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(DiagClients::getDiagId, diaId);
        //先删除
        diagClientsService.remove(queryWrapper);
        //在增加
        for (int i = 0; i < clientNums.length; i++) {
            DiagClients diagClients = new DiagClients();
            diagClients.setClientNum(clientNums[i]);
            diagClients.setDiagId(diaId);
            log.info("----修改客户端名称{}-----", diagClients);
            diagClientsService.save(diagClients);
        }
        log.info("----修改完成-----");


        return Result.ok();
    }

    @Override
    public DiagnosisVersionVO getVO(Integer id) {
        log.info("-------查询信息------");
        DiagnosisVersionInfo versionInfo = this.getById(id);

        DiagnosisVersionVO versionVO = new DiagnosisVersionVO();
        BeanUtil.copyProperties(versionInfo, versionVO);
        LambdaQueryWrapper<DiagClients> clientQueryWrapper = new LambdaQueryWrapper<>();
        clientQueryWrapper.eq(DiagClients::getDiagId, id);
        List<DiagClients> diagClients = diagClientsService.list(clientQueryWrapper);
        String[] s = new String[diagClients.size()];
        for (int i = 0; i < diagClients.size(); i++) {
            s[i] = diagClients.get(i).getClientNum();
        }
        versionVO.setClientNums(s);
        //语言和描述
        LambdaQueryWrapper<DiagnosisVersionDescribe> describeLambdaQueryWrapper = new LambdaQueryWrapper<>();
        describeLambdaQueryWrapper.eq(DiagnosisVersionDescribe::getDiagnosisId, id);
        List<DiagnosisVersionDescribe> describes = describeService.list(describeLambdaQueryWrapper);
        String[] l = new String[describes.size()];
        String[] d = new String[describes.size()];
        for (int i = 0; i < describes.size(); i++) {
            l[i] = describes.get(i).getLanguage();
            d[i] = describes.get(i).getDescription();
        }
        versionVO.setDescriptionList(d);
        versionVO.setLanguage(l);
        log.info("=====getByUserId={}======", versionVO);
        return versionVO;
    }


    @Override
    public Result getByUserId( Integer id) {
        DiagnosisVersionVO versionVO = this.getVO(id);


        return Result.ok(versionVO);
    }


    @Override
    public Result getPageList(Integer pageIndex,
                              Integer pageSize,
                              String username) {

        Page<DiagnosisVersionInfo> page = this.lambdaQuery()
                .like(StringUtils.isNotBlank(username), DiagnosisVersionInfo::getUsername, username)
                .orderByDesc(DiagnosisVersionInfo::getUpdateTime)
                .page(new Page<>(pageIndex, pageSize));
        //获取总的数据
        List<DiagnosisVersionInfo> diagLists = page.getRecords();
        List<DiagnosisVersionSearchVO> diagVOLists = new ArrayList<>();


        for (int i = 0; i < diagLists.size(); i++) {
            //然后取得客户端编号
            DiagnosisVersionInfo info = diagLists.get(i);
            //创建前端传输数据
            DiagnosisVersionSearchVO versionVO = new DiagnosisVersionSearchVO();
            BeanUtil.copyProperties(info, versionVO);
            Integer diagId = info.getId();
            LambdaQueryWrapper<DiagClients> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(DiagClients::getDiagId, diagId);
            List<DiagClients> diagClients = diagClientsService.list(queryWrapper);
            log.info("====diagClients={}", diagClients);

            String[] s = new String[diagClients.size()];

            for (int j = 0; j < diagClients.size(); j++) {
                Client client = clientService.lambdaQuery()
                        .eq(Client::getNumber, diagClients.get(j).getClientNum())
                        .one();
                if (BeanUtil.isEmpty(client)){
                    throw new BadReqException("该客户端编号"+diagClients.get(j).getClientNum()+"不存在");
                }
                s[j] = client.getName();
            }
            //传入客户端num
            versionVO.setClientNames(s);

            //传输描述和语言集合
            LambdaQueryWrapper<DiagnosisVersionDescribe> describeQueryWrapper = new LambdaQueryWrapper<>();
            describeQueryWrapper.eq(DiagnosisVersionDescribe::getDiagnosisId, diagId);
            List<DiagnosisVersionDescribe> describeList = describeService.list(describeQueryWrapper);
            log.info("List<DiagnosisVersionDescribe> describeList ={}", describeList);
            String[] language = new String[describeList.size()];
            String[] description = new String[describeList.size()];
            for (int i1 = 0; i1 < describeList.size(); i1++) {
                DiagnosisVersionDescribe describe = describeList.get(i1);
                language[i1] = describe.getLanguage();
                description[i1] = describe.getDescription();
            }

            //根据品牌编号查询名称
            Brand brand = brandService.lambdaQuery()
                    .eq(Brand::getBrandCode, info.getBrandCode())
                    .one();
            if (BeanUtil.isEmpty(brand)){
                throw new BadReqException(info.getDiagnosisName()+"此诊断程序中品牌编号有误");
            }
            //传入客户端
            versionVO.setLanguage(language);
            versionVO.setDescriptionList(description);
            versionVO.setBrandName(brand.getBrandCn());
            diagVOLists.add(versionVO);


        }
        Page<DiagnosisVersionSearchVO> pageVO = new Page<>();
        BeanUtil.copyProperties(page, pageVO);
        pageVO.setRecords(diagVOLists);

        log.info("====={}=======", pageVO.getRecords());


        return Result.ok(pageVO);
    }

    @Override
    public Result release(Integer id) {
        DiagnosisVersionInfo info = this.getById(id);
        info.setStatus(1);
        LambdaQueryWrapper<DiagnosisVersionInfo> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(DiagnosisVersionInfo::getId, id);
        this.update(info, queryWrapper);
        return Result.ok();
    }

    @Override
    public Result repeal(Integer id) {
        DiagnosisVersionInfo info = this.getById(id);
        info.setStatus(2);
        LambdaQueryWrapper<DiagnosisVersionInfo> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(DiagnosisVersionInfo::getId, id);
        this.update(info, queryWrapper);
        return Result.ok();
    }

    /*
    修改状态
     */
    @Override
    public Result upStatus(Integer id) {
        DiagnosisVersionInfo info = this.getById(id);
        info.setStatus(2);
        LambdaQueryWrapper<DiagnosisVersionInfo> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(DiagnosisVersionInfo::getId, id);
        this.update(info, queryWrapper);
        return Result.ok();


    }

    @Override
    public Result diagnosisVersionInfoUpdate(AppDiagVersionUpdateDTO dto) {

        if (BeanUtil.isEmpty(dto)) {
            return Result.fail("未获取到数据").result(ResultCode.NO_DATA);
        }
        String language = dto.getLanguage();
        List<AppBrandInfo> brandInfo = dto.getBrandInfo();
        String guid = dto.getGuid();
        GuidDTO guidDTO = AesUtil.getGuidDTOFromGuid(guid);
        String clientNum = guidDTO.getClientNum();
        if (brandInfo.isEmpty()) {
            throw new BadReqException("该诊断程序不存在");
        }
        List<VehicleDates> voList = new ArrayList<>();

        for (AppBrandInfo vehicleDates : brandInfo) {
            String version = vehicleDates.getVersion();

            List<DiagnosisVersionInfo> diagnosisVersionInfos = this.lambdaQuery()
                    .eq(DiagnosisVersionInfo::getBrandCode, vehicleDates.getBrandCode())
                    .apply("CONCAT(',', client_number, ',') LIKE {0}", "%,"+clientNum+",%")
                    .gt(DiagnosisVersionInfo::getVersion, version)
                    .orderByDesc(DiagnosisVersionInfo::getVersion)
                    .list();
            if (diagnosisVersionInfos.isEmpty()){
                return Result.fail("未获取到数据").result(ResultCode.NO_DATA);
            }
            DiagnosisVersionInfo diagnosisVersionInfo = diagnosisVersionInfos.get(0);
            if (BeanUtil.isEmpty(diagnosisVersionInfo)) {
                return Result.fail("未获取到数据").result(ResultCode.NO_DATA);
            }
            //根据品牌id查询品牌
            Brand brand = brandService.lambdaQuery()
                    .eq(Brand::getBrandCode,diagnosisVersionInfo.getBrandCode())
                    .one();
            if (BeanUtil.isEmpty(brand)) {
                throw new BadReqException("品牌不存在");
            }
            VehicleDates vehicleDates1 = BeanUtil.copyProperties(diagnosisVersionInfo, VehicleDates.class);
            //根据语言获取对应描述
            DiagnosisVersionDescribe diagnosisVersionDescribe = describeService.lambdaQuery()
                    .eq(DiagnosisVersionDescribe::getLanguage, language)
                    .eq(DiagnosisVersionDescribe::getDiagnosisId, diagnosisVersionInfo.getId())
                    .one();
            if (!BeanUtil.isEmpty(diagnosisVersionDescribe)) {
                vehicleDates1.setDescription(diagnosisVersionDescribe.getDescription());
            }else {
                vehicleDates1.setDescription("");
            }
            //获取下载链接
            String uploadUrl = obsUtil.getUploadUrl(diagnosisVersionInfo.getFileName(), "program");

            vehicleDates1.setUrl(uploadUrl);
            vehicleDates1.setVersion(diagnosisVersionInfo.getVersion());
            double v = Double.valueOf(diagnosisVersionInfo.getDiagnosisFileSize()) * 1024 * 1024;

            vehicleDates1.setFileSize((long) v);
            vehicleDates1.setBrandCn(brand.getBrandCn());
            vehicleDates1.setBrandEn(brand.getBrandEn());
            vehicleDates1.setFileName(diagnosisVersionInfo.getFileName());
            vehicleDates1.setPath(diagnosisVersionInfo.getSavePath());
            vehicleDates1.setCreateTime(diagnosisVersionInfo.getCreateTime().toInstant(ZoneOffset.of("+8")).toEpochMilli());
            voList.add(vehicleDates1);
        }


        return Result.ok(voList);
    }

    @Override
    public Result pushDiagnosis(Integer id) {
        DiagnosisVersionInfo diagnosisVersionInfo = this.getById(id);
        if (BeanUtil.isEmpty(diagnosisVersionInfo)) {
            throw new BadReqException("该诊断程序不存在");
        }

        PushInfo pushInfo = new PushInfo();
        pushInfo.setPushInfoType(2);
        VehicleInfo vehicleInfo = new VehicleInfo();

       BeanUtil.copyProperties(diagnosisVersionInfo, vehicleInfo);
        Brand brand = brandService.lambdaQuery()
                .eq(Brand::getBrandCode,diagnosisVersionInfo.getBrandCode())
                .one();
        if (BeanUtil.isEmpty(brand)) {
            throw new BadReqException("该品牌"+diagnosisVersionInfo.getBrandCode()+"不存在");
        }
        vehicleInfo.setBrandName(brand.getBrandCn());
        vehicleInfo.setBrandNameEn(brand.getBrandEn());
        vehicleInfo.setSortLetter(diagnosisVersionInfo.getDiagnosisName().substring(0,1));
        vehicleInfo.setUrl(diagnosisVersionInfo.getSavePath());
        List<Describe> describeList = new ArrayList<>();
        List<DiagnosisVersionDescribe> diagnosisVersionDescribes = describeService.lambdaQuery()
                .eq(DiagnosisVersionDescribe::getDiagnosisId, diagnosisVersionInfo.getId())
                .list();
        if (!diagnosisVersionDescribes.isEmpty()) {
            for (DiagnosisVersionDescribe diagnosisVersionDescribe : diagnosisVersionDescribes) {
                Describe describe = new Describe();
                describe.setDescription(diagnosisVersionDescribe.getDescription());
                describe.setLanguage(diagnosisVersionDescribe.getLanguage());
                describeList.add(describe);
            }
        }
        vehicleInfo.setDescribeList(describeList);


        List<DiagClients> diagClients = diagClientsService.lambdaQuery()
                .eq(DiagClients::getDiagId, diagnosisVersionInfo.getId())
                .list();

        if (!diagClients.isEmpty()) {
            List<String> clientNums = diagClients.stream().map(c -> c.getClientNum()).collect(Collectors.toList());
            String[] tokens = new String[clientNums.size()];
            for (String clientNum : clientNums) {
                int i = 0;
                Client client = clientService.lambdaQuery()
                        .eq(Client::getNumber, clientNum)
                        .one();
                if (BeanUtil.isNotEmpty(client)) {
                    tokens[i] = client.getDeviceToken();
                    i++;
                }
            }
            //调用工具类

            pushInfo.setJson(GsonUtils.toJsonString(vehicleInfo));
            try {
                pushUtil.sendAndroidListcastJSON(tokens,pushInfo);
            } catch (Exception e) {
                throw new BizException("推送失败！！！");
            }
        }
        return Result.ok();
    }

    @Override
    public Result getDesc(DiagnosisVersionVO diagnosisVersionVO) {
        return null;
    }
}
