package com.jwipc.supplier.logic.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson2.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.jwipc.api.dto.ESignOutOrgParamDTO;
import com.jwipc.api.dto.ESignOutOrgResult;
import com.jwipc.constant.DelFlag;
import com.jwipc.constant.DictCode;
import com.jwipc.constant.EnableStatus;
import com.jwipc.constant.FlagConst;
import com.jwipc.exception.DaoException;
import com.jwipc.page.PageUtil;
import com.jwipc.page.PageView;
import com.jwipc.prop.SysProp;
import com.jwipc.supplier.clent.dto.SupplierDTO;
import com.jwipc.supplier.constant.AnswerType;
import com.jwipc.supplier.constant.SampleState;
import com.jwipc.supplier.constant.TemplateFiledType;
import com.jwipc.supplier.convert.SupplierBankConvert;
import com.jwipc.supplier.convert.SupplierConvert;
import com.jwipc.supplier.convert.SupplierFieldConvert;
import com.jwipc.supplier.convert.SupplierTemplateQuestionnaireConvert;
import com.jwipc.supplier.dto.*;
import com.jwipc.supplier.entity.*;
import com.jwipc.supplier.logic.SupplierLogic;
import com.jwipc.supplier.model.po.FieldDictPO;
import com.jwipc.supplier.model.po.SupplierBankSendPO;
import com.jwipc.supplier.model.po.SupplierSelectPO;
import com.jwipc.supplier.model.po.TemplateQuestionnairePO;
import com.jwipc.supplier.model.query.SupplierSelectQuery;
import com.jwipc.supplier.service.*;
import com.jwipc.sys.client.ESignClient;
import com.jwipc.sys.client.EmailSendClient;
import com.jwipc.sys.client.UserClient;
import com.jwipc.sys.client.dto.EmailTmpSendDTO;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;


/**
 * <p> </p>
 *
 * @author BOGON
 * @version 1.0
 * @since JDK 1.8
 */
@Service
@RequiredArgsConstructor
@Slf4j
public class SupplierLogicImpl implements SupplierLogic {
    private final ISupplierService supplierService;
    private final SupplierConvert supplierConvert;
    private final ISupplierTemplateFieldRelationService supplierTemplateFieldRelationService;
    private final ISupplierTemplateService supplierTemplateService;
    private final ISupplierTemplateFieldService supplierTemplateFieldService;
    private final ISupplierExtensionService supplierExtensionService;
    private final ISupplierTemplateQuestionnaireRelationService questionnaireRelationService;
    private final ISupplierTemplateQuestionnaireItemService questionnaireItemService;
    private final SupplierTemplateQuestionnaireConvert templateQuestionnaireConvert;
    private final ISupplierFieldService supplierFieldService;
    private final SupplierFieldConvert supplierFieldConvert;
    private final ISupplierBankService supplierBankService;
    private final ISupplierPurchaseCategoryService supplierPurchaseCategoryService;
    private final UserClient userClient;
    private final EmailSendClient emailSendClient;
    private final SysProp sysProp;
    private final ISupplierContactsService supplierContactsService;
    private final ESignClient eSignClient;
    private final ISupplierInvitaionService supplierInvitaionService;
    private final ISupplierNameConvertService supplierNameConvertService;
    private final ISupplierExtensionVersionService supplierExtensionServiceVersionService;
    private final ISupplierBankInfoService supplierBankInfoService;
    private final SupplierBankConvert supplierBankConvert;





    @Override
    public PageView getListForSelect(SupplierSelectQuery query) {
        final Page<SupplierSelectPO> page = PageUtil.toPage(query);
        final List<SupplierSelectPO> list = supplierService.getListForSelect(page, query);
        List<SupplierSelectListDTO> supplierSelectListDTOS = supplierConvert.pos2SelectListDTOs(list);
        return PageUtil.getPV(supplierSelectListDTOS, page.getTotal());
    }

    @Override
    public SupplierDetailPageDTO renderPage(Long id,Long changeId) {
        SupplierDetailPageDTO supplierDetailPageDTO = new SupplierDetailPageDTO();
        final Supplier supplier = supplierService.getById(id);
        //需要把供应商的数据放到map中
        final Map<String, Object> stringObjectMap = BeanUtil.beanToMap(supplier);
        if(Objects.nonNull(changeId)){
             final List<SupplierExtensionVersion> list = supplierExtensionServiceVersionService.list(new LambdaQueryWrapper<SupplierExtensionVersion>().eq(SupplierExtensionVersion::getChangeVersionId,changeId));
       for (SupplierExtensionVersion supplierExtensionVersion : list){
           stringObjectMap.put(supplierExtensionVersion.getExtensionKey(), supplierExtensionVersion.getExtensionValue());
       }
        }else{
            final List<SupplierExtension> list = supplierExtensionService.list(
                    new LambdaQueryWrapper<SupplierExtension>().eq(SupplierExtension::getSupplierId, id));
            for (SupplierExtension supplierExtension : list) {
                stringObjectMap.put(supplierExtension.getExtensionKey(), supplierExtension.getExtensionValue());
            }
        }


        supplierDetailPageDTO.setSupplier(stringObjectMap);
        String templateId;
        if (Objects.nonNull(supplier.getTemplateId())) {
            templateId = String.valueOf(supplier.getTemplateId());
        } else {
            final SupplierTemplate moduleTemplate = supplierTemplateService.getOne(
                    new LambdaQueryWrapper<SupplierTemplate>().eq(SupplierTemplate::getTemplateName, "default")
                            .last(" LIMIT 1"));
            templateId = String.valueOf(moduleTemplate.getId());
        }
        List<SupplierField> supplierFields = supplierFieldService.list(
                new LambdaQueryWrapper<SupplierField>().eq(SupplierField::getSupplierId, supplier.getId()));
        Set<String> fieldCodes = supplierFields.stream().map(SupplierField::getFieldCode).collect(Collectors.toSet());
        //需要查询到字段表的remark
        final List<SupplierTemplateField> list1 = supplierTemplateFieldService.list(
                new LambdaQueryWrapper<SupplierTemplateField>().in(SupplierTemplateField::getFieldName, fieldCodes));
        final Map<String, String> remarkCache = list1.stream().filter(a -> StrUtil.isNotEmpty(a.getRemark()))
                .collect(Collectors.toMap(SupplierTemplateField::getFieldName, SupplierTemplateField::getRemark));

        List<SupplierFieldBaseDTO> supplierFieldBaseDTOS = supplierFieldConvert.entities2Dtos(supplierFields);

        for (SupplierFieldBaseDTO e : supplierFieldBaseDTOS) {
            final String s = remarkCache.get(e.getFieldCode());
            if (StrUtil.isNotEmpty(s)) {
                e.setRemark(s);
            }
            e.setFieldCode(StrUtil.toCamelCase(e.getFieldCode()));
            if (e.getFormControl() == TemplateFiledType.DICT.getType()) {
                final String sqlSentence = e.getSqlSentence();
                if (StringUtils.isNotEmpty(sqlSentence)) {
                    List<FieldDictPO> map = supplierTemplateFieldRelationService.selectDataBySql(sqlSentence);
                    e.setData(JSON.toJSONString(map));
                    e.setFieldLength(map.size());
                }
            }
        }


        List<SupplierFieldBaseDTO> templateBaseFieldList = Lists.newArrayList();
        List<SupplierFieldBaseDTO> templateTextFieldList = Lists.newArrayList();

        //关联表字段
        Map<String, String> templateFollowTable = new HashMap<>();
        // 待加载关联表【必填-表名称】
        Map<String, String> requiredTemplateFollowTable = new HashMap<>();

        //根据form_control判断字段属于哪种类型，1.基础字段 2.表格 3.问卷调查
        supplierFieldBaseDTOS.forEach(e -> {
            Integer formControl = e.getFormControl();
            final TemplateFiledType filedType = TemplateFiledType.forType(formControl);
            switch (filedType) {
                case BASIC:
                    //基础字段
                    //需要把fieldName从下划线变成驼峰
                    templateBaseFieldList.add(e);
                    break;
                case ASSOCIATED:
                    String fieldType = e.getFieldType();
                    if (fieldType.equals("table")) {
                        //关联表
                        templateFollowTable.put(StrUtil.toUnderlineCase(e.getFieldCode()), e.getFieldAlias());
                        // 关联表必填
                        if (e.getRequired() == 1) {
                            requiredTemplateFollowTable.put(StrUtil.toUnderlineCase(e.getFieldCode()),
                                    e.getFieldAlias());
                        }
                        break;
                    } else if (fieldType.equals("varchar")) {
                        // 长文本
                        //需要把fieldName从下划线变成驼峰
                        templateTextFieldList.add(e);
                        break;
                    }
                case NUMBER:
                    //数字
                    templateBaseFieldList.add(e);
                    break;
                case AREA:
                case DICT:
                    //字典字段
                case DATE:
                    // 日期字段
                    //需要把fieldName从下划线变成驼峰
                    templateBaseFieldList.add(e);
                    break;
                default:
            }
        });
        supplierDetailPageDTO.setFieldList(templateBaseFieldList);
        supplierDetailPageDTO.setTextList(templateTextFieldList);
        supplierDetailPageDTO.setTemplateFollowTable(templateFollowTable);
        final SupplierTemplate moduleTemplate = supplierTemplateService.getById(templateId);
        String supplierId = String.valueOf(id);
        /**
         * 如果模板启用了问卷调查，则查找改模板的问卷调查题目
         */
        if (moduleTemplate.getEnableQuestionnaire() == EnableStatus.ENABLE.getStatus()) {
            final List<TemplateQuestionnairePO> templateQuestionnairePOS = questionnaireAndItemByRelation(templateId,
                    supplierId);
            List<TemplateQuestionnaireDTO> questionnaireList = templateQuestionnaireConvert.pos2DTOs(
                    templateQuestionnairePOS);
            supplierDetailPageDTO.setQuestionnaireList(questionnaireList);

        }
        return supplierDetailPageDTO;
    }

    @Override
    public List<TemplateQuestionnairePO> questionnaireAndItemByRelation(String templateId, String supplierId) {
        List<TemplateQuestionnairePO> questionnaireList = questionnaireRelationService.selectQuestionnaireByRelation(
                templateId, supplierId);
        if (CollUtil.isNotEmpty(questionnaireList)) {
            final Map<Long, TemplateQuestionnairePO> map = new HashMap<>();
            final List<Long> questionnaireIds = Lists.newArrayList();
            /**
             *把问卷调查和答案项组装
             */
            for (int i = 0, length = questionnaireList.size(); i < length; i++) {
                final TemplateQuestionnairePO e = questionnaireList.get(i);

                /**
                 * 查询单选和多选问题的答案项
                 * 如果是多选项，且供应商有答复的，那么需要把多选内容分割成数组
                 */
                final AnswerType answerType = AnswerType.forType(e.getAnswerType());
                switch (answerType) {
                    case Multiple:
//                        if (query.getSupplierId() != null && StringUtils.isNotEmpty(e.getQuestionAnswer())) {
//                            e.setQuestionAnswer(e.getQuestionAnswer().split(",").toString());
//                        }
                    case Single:
                        questionnaireIds.add(e.getId());
                        map.put(e.getId(), e);
                        break;
                }
            }
            if (CollUtil.isNotEmpty(questionnaireIds)) {
                List<SupplierTemplateQuestionnaireItem> itemList = questionnaireItemService.list(
                        new LambdaQueryWrapper<SupplierTemplateQuestionnaireItem>().eq(
                                        SupplierTemplateQuestionnaireItem::getDeleteFlag, DelFlag.NORMAL.getStatus())
                                .in(SupplierTemplateQuestionnaireItem::getQuestionId, questionnaireIds));
                if (CollUtil.isNotEmpty(itemList)) {
                    for (int i = 0; i < itemList.size(); i++) {
                        final SupplierTemplateQuestionnaireItem e = itemList.get(i);
                        List<SupplierTemplateQuestionnaireItem> itemDtoList;
                        if (map.get(e.getQuestionId()) == null) {
                            break;
                        }
                        if (map.get(e.getQuestionId()).getItemList() == null) {
                            itemDtoList = Lists.newArrayList();
                        } else {
                            itemDtoList = map.get(e.getQuestionId()).getItemList();
                        }
                        itemDtoList.add(e);
                        map.get(e.getQuestionId()).setItemList(itemDtoList);
                    }
                }
            }
        }
        return questionnaireList;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateSamplePass(Long id) {
        final Supplier supplier = supplierService.getById(id);
        if (Objects.nonNull(supplier)) {
            supplier.setSampleState(SampleState.OK.getStatus());
            supplierService.updateById(supplier);
        }
    }

    @Override
    public List<SupplierBankDTO> findSupplierBankData(String supplierId) {
        List<SupplierBank> supplierBanks = supplierBankService.findSupplierBankData(supplierId);
        return supplierConvert.entityToDtoListBank(supplierBanks);
    }

    @Override
    public SupplierBaseDTO getById(Long supplierId) {
        Supplier supplier = supplierService.getById(supplierId);
        return supplierConvert.supplierToSupplierBaseDTO(supplier);
    }

    @Override
    public Set<String> getPurchaseCategoryCodes(Long supplierId) {
        final List<SupplierPurchaseCategory> list = supplierPurchaseCategoryService.list(
                new LambdaQueryWrapper<SupplierPurchaseCategory>().eq(SupplierPurchaseCategory::getSupplierId,
                        supplierId));
        return list.stream().map(SupplierPurchaseCategory::getPurchaseCategoryCode).collect(Collectors.toSet());
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateFormalCode(Long supplierId, String supplierCode) {
        final Supplier supplier = supplierService.getById(supplierId);
        if (StrUtil.isEmpty(supplier.getSupplierErpCode())) {
            //需要更新供应商银行的正式编码
            supplier.setSupplierErpCode(supplierCode);
            supplier.setSupplierCode(supplierCode);
            supplierService.update(new LambdaUpdateWrapper<Supplier>().set(Supplier::getSupplierCode, supplierCode)
                    .set(Supplier::getSupplierErpCode, supplierCode)
                    .eq(Supplier::getId, supplier.getId()));
            userClient.updateUserCode(supplier.getId(), supplierCode);
            //更新银行供应商编码
            supplierBankService.update(
                    new LambdaUpdateWrapper<SupplierBank>().set(SupplierBank::getSupplierCode, supplierCode)
                            .eq(SupplierBank::getSupplierId, supplierId));

            //更新供应商联系人表中供应商编码
            supplierContactsService.update(
                    new LambdaUpdateWrapper<SupplierContacts>().set(SupplierContacts::getSupplierCode, supplierCode)
                            .eq(SupplierContacts::getSupplierId, supplierId));
            //需要发送邮件
            final EmailTmpSendDTO emailTxtSingleSendDTO = new EmailTmpSendDTO();
            //需要查询供应商联系人
            final List<SupplierContacts> supplierContacts = supplierContactsService.list(
                    new LambdaQueryWrapper<SupplierContacts>().eq(SupplierContacts::getSupplierId, supplier.getId())
                            .eq(SupplierContacts::getContactsType, DictCode.ContactType.BUSINESS.getType()));
            if (CollUtil.isNotEmpty(supplierContacts)) {
                final Set<String> emails = supplierContacts.stream()
                        .filter(a -> StrUtil.isNotEmpty(a.getEmail())).map(SupplierContacts::getEmail)
                        .collect(Collectors.toSet());
                emailTxtSingleSendDTO.setTemplateCode("JW_POST_070");
                Map<String, Object> params = Maps.newHashMap();
                params.put("url", sysProp.getWebsiteUrl());
                params.put("accountCode", supplierCode);
                params.put("supplierName", supplier.getSupplierName());
                emailTxtSingleSendDTO.setParams(params);
                emailTxtSingleSendDTO.setReceiver(emails);
                emailTxtSingleSendDTO.setSender(1L);
                emailSendClient.async(emailTxtSingleSendDTO);
            }
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateSignatureFlag(Long id) {
        final Supplier supplier = supplierService.getById(id);
        if (Objects.isNull(supplier)) {
            throw new DaoException("供应商信息不存在!");
        }
        String supplierName = supplier.getSupplierName();
        SupplierNameConvert nameConvert = supplierNameConvertService.getOne(new LambdaQueryWrapper<>(SupplierNameConvert.class).eq(SupplierNameConvert::getCode, supplier.getSupplierCode()));
        if(!Objects.isNull(nameConvert)){//不为空则需要替换供应商繁体名称
            supplierName = nameConvert.getTraditional();
        }

        final Integer signatureFlag = supplier.getSignatureFlag();
        if (Objects.nonNull(signatureFlag) && signatureFlag.equals(FlagConst.Y.getCode())) {
            supplierService.update(
                    new LambdaUpdateWrapper<>(Supplier.class).set(Supplier::getSignatureFlag, FlagConst.N.getCode())
                            .eq(Supplier::getId, id));
        } else {
            supplierService.update(
                    new LambdaUpdateWrapper<>(Supplier.class).set(Supplier::getSignatureFlag, FlagConst.Y.getCode())
                            .eq(Supplier::getId, id));

            //需要查询电子签章联系人
            final SupplierContacts contacts = supplierContactsService.getOne(
                    new LambdaQueryWrapper<>(SupplierContacts.class)
                            .eq(SupplierContacts::getSupplierId, id)
                            .eq(SupplierContacts::getContactsType, DictCode.ContactType.SIGNATURE.getType()),
                    false);
            if (Objects.isNull(contacts)) {
                throw new DaoException("签章联系人不存在!");
            }
            // TODO: 2024/5/8  jiez 需要推送给电子签章
            final ESignOutOrgParamDTO eSignOutOrgParamDTO = new ESignOutOrgParamDTO();
            eSignOutOrgParamDTO.setCustomOrgNo(supplier.getSupplierCode());
//                eSignOutOrgParamDTO.setLicenseNo(supplier.getBusinessRegisterNo());
//                eSignOutOrgParamDTO.setLegalRepUserCode(supplier.getBusinessRegisterNo());
            eSignOutOrgParamDTO.setName(supplierName);
            final ESignOutOrgParamDTO.User user = new ESignOutOrgParamDTO.User();
            user.setEmail(contacts.getEmail());
            user.setMobile(contacts.getContactsTel());
            user.setUserCode(contacts.getContactsTel());
            user.setName(contacts.getContactsName());
            user.setCustomAccountNo(contacts.getContactsTel());
            if (StrUtil.isNotEmpty(contacts.getIdCard())) {
                user.setLicenseType("ID_CARD");
                user.setLicenseNo(contacts.getIdCard());
            }
            eSignOutOrgParamDTO.setUser(user);
            final ESignOutOrgResult eSignOutOrgResult = eSignClient.saveOutOrgWithUser(eSignOutOrgParamDTO);
            if (Objects.nonNull(eSignOutOrgResult)) {
                //需要推送用户
                log.info("返回的数据:{}", eSignOutOrgResult);
                supplierService.update(
                        new LambdaUpdateWrapper<>(Supplier.class)
                                .set(Supplier::getSignatureFlag, FlagConst.Y.getCode())
                                .eq(Supplier::getId, id));
            } else {
                throw new DaoException("推送E签宝系统发生错误!");
            }

        }
    }

    @Override
    public void updateMonthFlagFlag(Long id) {
        final Supplier supplier = supplierService.getById(id);
        if (Objects.isNull(supplier)) {
            throw new DaoException("供应商信息不存在!");
        }
        final Integer monthFlag = supplier.getMonthFlag();
        if (monthFlag.equals(FlagConst.Y.getCode())) {
            supplierService.update(
                    new LambdaUpdateWrapper<>(Supplier.class).set(Supplier::getMonthFlag, FlagConst.N.getCode())
                            .eq(Supplier::getId, id));
        } else {
            supplierService.update(
                    new LambdaUpdateWrapper<>(Supplier.class).set(Supplier::getMonthFlag, FlagConst.Y.getCode())
                            .eq(Supplier::getId, id));
        }
    }

    @Override
    public void updateApprovalOpinion(Long id, String approvalOpinion) {
        supplierService.update(
                new LambdaUpdateWrapper<>(Supplier.class).set(Supplier::getApprovalOpinion, StringUtils.isNotEmpty(approvalOpinion) ? approvalOpinion : "")
                        .eq(Supplier::getId, id));
    }

    @Override
    public void updatePurchaseGroup(Long id, String purchaseGroup) {
        final LambdaUpdateWrapper<Supplier> eq = new LambdaUpdateWrapper<Supplier>().set(Supplier::getPurchaseGroupCode,
                        purchaseGroup)
                .eq(Supplier::getId, id);
        supplierService.update(eq);
        final LambdaUpdateWrapper<SupplierInvitaion> invitaionLambdaUpdateWrapper =
                new LambdaUpdateWrapper<SupplierInvitaion>()
                .set(SupplierInvitaion::getPurchaseGroupCode, purchaseGroup)
                .eq(SupplierInvitaion::getSupplierId, id);
        supplierInvitaionService.update(invitaionLambdaUpdateWrapper);
    }

    @Override
    public void updateRecommender(Long id, String recommenderCode) {
        final LambdaUpdateWrapper<SupplierInvitaion> invitaionLambdaUpdateWrapper =
                new LambdaUpdateWrapper<SupplierInvitaion>()
                        .set(SupplierInvitaion::getRecommender, recommenderCode)
                        .eq(SupplierInvitaion::getSupplierId, id);
        supplierInvitaionService.update(invitaionLambdaUpdateWrapper);
    }

    @Override
    public SupplierDTO getSupplierByCode(String supplierCode) {
        final Supplier supplier = supplierService.getOne(
                new LambdaQueryWrapper<>(Supplier.class)
                        .eq(Supplier::getSupplierCode, supplierCode));
        if (Objects.isNull(supplier)) {
            throw new DaoException("供应商不存在!");
        }
        SupplierDTO supplierDTO = supplierConvert.supplierToSupplierDTO(supplier);
        return supplierDTO;
    }


    @Override
    public void findSupplierBankDatas(List<Long> ids) {
        List<SupplierBankSendPO> supplierBanks = supplierBankService.findSupplierBankDatas(ids);
        List<SupplierBankInfo> supplierBankInfos = supplierBankConvert.bank2SupplierBanks(supplierBanks);
        supplierBankInfoService.deleteBySupplieId(ids);
        supplierBankInfoService.saveSupplierBankInfos(supplierBankInfos);
    }
}