package com.mortals.xhx.daemon.task;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.IdcardUtil;
import cn.hutool.http.HttpUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;
import com.mortals.framework.common.Rest;
import com.mortals.framework.exception.AppException;
import com.mortals.framework.service.ITask;
import com.mortals.framework.service.ITaskExcuteService;
import com.mortals.xhx.base.system.upload.service.UploadService;
import com.mortals.xhx.busiz.rsp.register.DataItem;
import com.mortals.xhx.busiz.rsp.register.RegisterDataInfo;
import com.mortals.xhx.common.code.SourceEnum;
import com.mortals.xhx.common.code.YesNoEnum;
import com.mortals.xhx.module.person.model.PersonEntity;
import com.mortals.xhx.module.person.model.PersonQuery;
import com.mortals.xhx.module.person.service.PersonService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileItemFactory;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.commons.CommonsMultipartFile;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 同步注册用户。
 * 定时以一定时间间隔进行人员获取 定时时间要早于每日预约人数的同步时间
 */
@Slf4j
@Service("SyncRegisterUserTask")
public class SyncRegisterUserTaskImpl implements ITaskExcuteService {

    @Autowired
    private PersonService personService;
    @Autowired
    private UploadService uploadService;

    @Value("${php.host:''}")
    private String host;


    @Override
    public void excuteTask(ITask task) throws AppException {
        log.info("同步注册用户任务");
        syncRegisterUsers();
        log.info("同步注册用户任务完成");

        log.info("同步注册用户照片任务");
        syncRegisterPhotoUsers();
        log.info("同步注册用户任务照片完成");

    }

    private void syncRegisterPhotoUsers() {
        String registerPath = "/inter/Actuary/peoplePhotoList";
        String url = host + registerPath;
        Map<String, Object> params = new HashMap<>();
        params.put("page", 1);
        params.put("size", 10000);
        String respJson = HttpUtil.get(url, params);
        Rest<RegisterDataInfo> rest = JSON.parseObject(respJson, new TypeReference<Rest<RegisterDataInfo>>() {
        });

        if (rest.getCode() == YesNoEnum.YES.getValue()) {
            List<DataItem> userList = rest.getData().getData();
            log.info("注册用户有照片数量：{}  {}", userList.size(),JSON.toJSONString(userList));
            for (DataItem user : userList) {
                if (ObjectUtils.isEmpty(user.getIdcardIDCardNo())) {
                    continue;
                }
                PersonEntity personServiceExtCache = personService.getExtCache(user.getIdcardIDCardNo());
                if (ObjectUtils.isEmpty(personServiceExtCache)) {
                    log.info("用户不存在，idcard:{}", user.getIdcardIDCardNo());
                    continue;
                }
                //判断是否有图片地址
                if (ObjectUtils.isEmpty(personServiceExtCache.getSourcePhotoUri())) {
                    PersonEntity personEntity = new PersonEntity();
                    personEntity.setId(personServiceExtCache.getCreateUserId());
                    personEntity.setSourcePhotoUri(user.getIdcardDataPhotoFileName());
                    personEntity.setIdCard(user.getIdcardIDCardNo());
                    //直接下载更新到本地
                    String downUrl = host + "/" + personEntity.getSourcePhotoUri();
                    // String downUrl = "http://192.168.0.98:11078/file/fileupload/1679215657433.jpg";
                    log.info("downUrl:{}", downUrl);
                    byte[] bytes = HttpUtil.downloadBytes(downUrl);
                    if (bytes.length > 0) {
                        InputStream inputStream = new ByteArrayInputStream(bytes);
                        MultipartFile file = getMultipartFile(inputStream, "photo.jpg");
                        String filePath = uploadService.saveFileUpload(file, "file/fileupload/photo", null);
                        personEntity.setPhoto(filePath);
                        personEntity.setId(personServiceExtCache.getId());
                        personService.update(personEntity);
                    } else {
                        log.info("图片下载失败:{}", downUrl);
                    }
                }
            }
        }

    }

    private void syncRegisterUsersTotal() {
        log.info("同步注册用户全量更新");

        String registerPath = "/inter/Actuary/peopleList";
        String url = host + registerPath;
        Map<String, Object> params = new HashMap<>();
        params.put("page", 1);
        params.put("size", 1);
        params.put("startid", 0);
        String respJson = HttpUtil.get(url, params);
        Rest<RegisterDataInfo> rest = JSON.parseObject(respJson, new TypeReference<Rest<RegisterDataInfo>>() {
        });

        if (rest.getCode() == YesNoEnum.YES.getValue()) {
            Integer total = rest.getData().getTotal();
            if (total > 1) {
                //todo 分页请求
                params = new HashMap<>();
                params.put("page", 1);
                params.put("size", total);
                respJson = HttpUtil.get(url, params);
                Rest<RegisterDataInfo> restTotal = JSON.parseObject(respJson, new TypeReference<Rest<RegisterDataInfo>>() {
                });

                if (restTotal.getCode() == YesNoEnum.YES.getValue()) {
                    //同步所有用户
                    List<DataItem> userList = restTotal.getData().getData();
                    log.info("注册用户数量：{}", userList.size());
                    if (!ObjectUtils.isEmpty(userList)) {
                        List<PersonEntity> newUserList = userList.stream().map(user -> {
                            if (ObjectUtils.isEmpty(user.getIdcardIDCardNo())) {
                                return null;
                            }
                            if (!ObjectUtils.isEmpty(user.getIdcardDataPhotoFileName())) {
                                log.info("注册用户名称:{} ,idCard:{},照片路径：{}", user.getIdcardName(), user.getIdcardIDCardNo(), user.getIdcardDataPhotoFileName());
                            }
                            PersonEntity personEntity = new PersonEntity();
                            personEntity.initAttrValue();
                            personEntity.setName(user.getIdcardName());
                            personEntity.setGender("男".equals(user.getIdcardSex()) ? 0 : 1);
                            personEntity.setIdCard(user.getIdcardIDCardNo());
                            personEntity.setPhone(user.getPhone());
                            personEntity.setAddress(user.getIdcardAddress());
                            try {
                                personEntity.setBirthday(DateUtil.parse(IdcardUtil.getBirth(user.getIdcardIDCardNo()), "yyyyMMdd"));
                            } catch (Exception e) {
                            }
                            personEntity.setSourceId(user.getId());
                            personEntity.setSource(SourceEnum.排队叫号系统.getValue());
                            personEntity.setSourcePhotoUri(user.getIdcardDataPhotoFileName());
                            return personEntity;
                        }).filter(f -> f != null).collect(Collectors.toList());

                        List<PersonEntity> oldUserList = personService.find(new PersonQuery());
                        Map<String, PersonEntity> oldUserMap = oldUserList.stream().collect(Collectors.toMap(x -> x.getIdCard(), y -> y, (o, n) -> n));
                        Map<String, PersonEntity> newUserMap = newUserList.stream().collect(Collectors.toMap(x -> x.getIdCard(), y -> y, (o, n) -> n));

                        List<PersonEntity> updateUserLsit = newUserList.stream().map(item -> {
                            if (oldUserMap.containsKey(item.getIdCard())) {
                                PersonEntity personEntity = oldUserMap.get(item.getIdCard());
                                //校验 如果参数都一样 则不添加更新
                                //if(!ObjectUtils.isEmpty(item.getSourcePhotoUri()))
                                Boolean bool = checkFieldSame(item, personEntity);
                                if (bool) return null;
                                personEntity.setName(item.getName());
                                personEntity.setGender(item.getGender());
                                personEntity.setPhone(item.getPhone());
                                personEntity.setAddress(item.getAddress());
                                personEntity.setBirthday(item.getBirthday());
                                personEntity.setSourcePhotoUri(item.getSourcePhotoUri());
                                personEntity.setUpdateUserId(1L);
                                personEntity.setUpdateTime(new Date());
                                return personEntity;
                            }
                            return null;
                        }).filter(f -> f != null).collect(Collectors.toList());

                        List<PersonEntity> saveUserList = newUserList.stream().map(item -> {
                            if (!oldUserMap.containsKey(item.getIdCard())) {
                                item.setCreateUserId(1L);
                                item.setCreateUserName("系统管理员");
                                item.setCreateTime(new Date());
                                return item;
                            }
                            return null;
                        }).filter(f -> f != null).collect(Collectors.toList());

                        //做差集
                        List<Long> delUserList = oldUserList.stream().map(item -> {
                            if (!newUserMap.containsKey(item.getIdCard())) {
                                return item.getId();
                            }
                            return null;
                        }).filter(f -> f != null).collect(Collectors.toList());

                        if (!ObjectUtils.isEmpty(updateUserLsit)) {
                            log.info("注册用户更新，size:{}", updateUserLsit.size());
                            personService.update(updateUserLsit);
                        }

                        if (!ObjectUtils.isEmpty(saveUserList)) {
                            log.info("注册用户新增，size:{}", saveUserList.size());
                            personService.save(saveUserList);
                        }

                    }

                }


            }
        }


    }


    private boolean checkFieldSame(PersonEntity newPerson, PersonEntity oldPerson) {

        if (!ObjectUtils.isEmpty(newPerson.getSourcePhotoUri()) && !newPerson.getSourcePhotoUri().equals(oldPerson.getSourcePhotoUri())) {
            return false;
        }
        return true;
    }


    private void syncRegisterUsers() {
        //查询本地最大id
        int count = 0;
        List<PersonEntity> max = personService.getDao().getMax();
        if (!ObjectUtils.isEmpty(max)) {
            count = max.get(0).getSourceId().intValue();
        }
        String registerPath = "/inter/Actuary/peopleList";
        String url = host + registerPath;
        Map<String, Object> params = new HashMap<>();
        params.put("page", 1);
        params.put("size", 1);
        params.put("startid", count);
        String respJson = HttpUtil.get(url, params);
        Rest<RegisterDataInfo> rest = JSON.parseObject(respJson, new TypeReference<Rest<RegisterDataInfo>>() {
        });

        if (rest.getCode() == YesNoEnum.YES.getValue()) {
            Integer total = rest.getData().getTotal();
            log.info("total：{}", total);
            if (total > 1) {
                params = new HashMap<>();
                params.put("page", 1);
                params.put("size", total);
                params.put("startid", count);
                respJson = HttpUtil.get(url, params);
                Rest<RegisterDataInfo> restTotal = JSON.parseObject(respJson, new TypeReference<Rest<RegisterDataInfo>>() {
                });

                if (restTotal.getCode() == YesNoEnum.YES.getValue()) {
                    //同步所有用户
                    List<DataItem> userList = restTotal.getData().getData();
                    log.info("注册用户新增数量：{}", userList.size());
                    if (!ObjectUtils.isEmpty(userList)) {
                        List<PersonEntity> newUserList = userList.stream().map(user -> {
                            if (ObjectUtils.isEmpty(user.getIdcardIDCardNo())) {
                                return null;
                            }

                            PersonEntity personEntity = new PersonEntity();
                            personEntity.initAttrValue();
                            personEntity.setName(user.getIdcardName());
                            personEntity.setGender("男".equals(user.getIdcardSex()) ? 0 : 1);
                            personEntity.setIdCard(user.getIdcardIDCardNo());
                            personEntity.setPhone(user.getPhone());
                            personEntity.setAddress(user.getIdcardAddress());
                            try {
                                personEntity.setBirthday(DateUtil.parse(IdcardUtil.getBirth(user.getIdcardIDCardNo()), "yyyyMMdd"));
                            } catch (Exception e) {
                            }
                            personEntity.setSourceId(user.getId());
                            personEntity.setSource(SourceEnum.排队叫号系统.getValue());
                            personEntity.setSourcePhotoUri(user.getIdcardDataPhotoFileName());
                            return personEntity;
                        }).filter(f -> f != null).collect(Collectors.toList());

                        List<PersonEntity> oldUserList = personService.find(new PersonQuery());
                        Map<String, PersonEntity> oldUserMap = oldUserList.stream().collect(Collectors.toMap(x -> x.getIdCard(), y -> y, (o, n) -> n));
                        Map<String, PersonEntity> newUserMap = newUserList.stream().collect(Collectors.toMap(x -> x.getIdCard(), y -> y, (o, n) -> n));

                        List<PersonEntity> updateUserLsit = newUserList.stream().map(item -> {
                            if (oldUserMap.containsKey(item.getIdCard())) {
                                PersonEntity personEntity = oldUserMap.get(item.getIdCard());
                                personEntity.initAttrValue();
                                personEntity.setName(item.getName());
                                personEntity.setGender(item.getGender());
                                personEntity.setPhone(item.getPhone());
                                personEntity.setAddress(item.getAddress());
                                personEntity.setBirthday(item.getBirthday());
                                personEntity.setSourcePhotoUri(item.getSourcePhotoUri());
                                personEntity.setUpdateUserId(1L);
                                personEntity.setUpdateTime(new Date());
                                return personEntity;
                            }
                            return null;
                        }).filter(f -> f != null).collect(Collectors.toList());

                        List<PersonEntity> saveUserList = newUserList.stream().map(item -> {
                            if (!oldUserMap.containsKey(item.getIdCard())) {
                                item.setCreateUserId(1L);
                                item.setCreateUserName("系统管理员");
                                item.setCreateTime(new Date());
                                return item;
                            }
                            return null;
                        }).filter(f -> f != null).collect(Collectors.toList());

                        //做差集
                        List<Long> delUserList = oldUserList.stream().map(item -> {
                            if (!newUserMap.containsKey(item.getIdCard())) {
                                return item.getId();
                            }
                            return null;
                        }).filter(f -> f != null).collect(Collectors.toList());

                        if (!ObjectUtils.isEmpty(updateUserLsit)) {
                            log.info("注册用户更新，size:{}", updateUserLsit.size());
                            personService.update(updateUserLsit);
                        }

                        if (!ObjectUtils.isEmpty(saveUserList)) {
                            log.info("注册用户新增，size:{}", saveUserList.size());
                            personService.save(saveUserList);
                        }

                    }

                }
            }


        }

    }

    private void syncRegisterUsersPhotos() {
        String url = host.endsWith("/") ? host : host + "/";
        List<PersonEntity> collect = personService.find(new PersonQuery()).stream()
                .filter(item -> ObjectUtils.isEmpty(item.getPhoto()))
                .filter(item -> !ObjectUtils.isEmpty(item.getSourcePhotoUri())).collect(Collectors.toList());
        for (PersonEntity personEntity : collect) {
            //下载图片到本地保存并更新
            String downUrl = url + personEntity.getSourcePhotoUri();
            // String downUrl = "http://192.168.0.98:11078/file/fileupload/1679215657433.jpg";
            log.info("downUrl:{}", downUrl);
            byte[] bytes = HttpUtil.downloadBytes(downUrl);
            if (bytes.length > 0) {
                InputStream inputStream = new ByteArrayInputStream(bytes);
                MultipartFile file = getMultipartFile(inputStream, "photo.jpg");
                String filePath = uploadService.saveFileUpload(file, "file/fileupload", null);
                personEntity.setPhoto(filePath);
                personService.update(personEntity);
            }
        }
    }


    @Override
    public void stopTask(ITask task) throws AppException {

    }


    /**
     * 获取封装得MultipartFile
     *
     * @param inputStream inputStream
     * @param fileName    fileName
     * @return MultipartFile
     */
    public MultipartFile getMultipartFile(InputStream inputStream, String fileName) {
        FileItem fileItem = createFileItem(inputStream, fileName);
        //CommonsMultipartFile是feign对multipartFile的封装，但是要FileItem类对象
        return new CommonsMultipartFile(fileItem);
    }


    /**
     * FileItem类对象创建
     *
     * @param inputStream inputStream
     * @param fileName    fileName
     * @return FileItem
     */
    public FileItem createFileItem(InputStream inputStream, String fileName) {
        FileItemFactory factory = new DiskFileItemFactory(16, null);
        String textFieldName = "file";
        FileItem item = factory.createItem(textFieldName, MediaType.MULTIPART_FORM_DATA_VALUE, true, fileName);
        int bytesRead = 0;
        byte[] buffer = new byte[10 * 1024 * 1024];
        OutputStream os = null;
        //使用输出流输出输入流的字节
        try {
            os = item.getOutputStream();
            while ((bytesRead = inputStream.read(buffer, 0, 8192)) != -1) {
                os.write(buffer, 0, bytesRead);
            }
            inputStream.close();
        } catch (IOException e) {
            log.error("Stream copy exception", e);
            throw new IllegalArgumentException("文件上传失败");
        } finally {
            if (os != null) {
                try {
                    os.close();
                } catch (IOException e) {
                    log.error("Stream close exception", e);

                }
            }
            if (inputStream != null) {
                try {
                    inputStream.close();
                } catch (IOException e) {
                    log.error("Stream close exception", e);
                }
            }
        }

        return item;
    }

    public static void main(String[] args) {


        System.out.println(DateUtil.parse("19951071", "yyyyMMdd"));
    }


}
