package com.storlead.sales.controller.customer;


import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.storlead.framework.common.constant.CommonConstant;
import com.storlead.framework.common.util.MD5Util;
import com.storlead.framework.util.LoginUserUtil;
import com.storlead.framework.common.result.Result;
import com.storlead.framework.redis.RedisService;
import com.storlead.sales.pojo.dto.customer.*;
import com.storlead.sales.pojo.entity.customer.*;
import com.storlead.sales.pojo.vo.customer.CustomerAllVO;
import com.storlead.sales.pojo.vo.customer.CustomerCountVO;
import com.storlead.sales.pojo.vo.customer.CustomerListVO;
import com.storlead.sales.pojo.vo.customer.CustomerVO;
import com.storlead.sales.enums.ResourceTypeEnum;
import com.storlead.sales.pojo.entity.sku.QuotationEntity;
import com.storlead.sales.service.customer.*;
import com.storlead.sales.service.CustomerMailBingMarkService;
import com.storlead.sales.service.CustomerMailRecordService;
import com.storlead.sales.service.sku.QuotationService;
import com.storlead.sales.service.systemrule.OperationLogService;
import com.storlead.sales.service.task.TaskService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.log4j.Log4j2;
import org.springframework.beans.BeanUtils;
import javax.annotation.Resource;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * <p>
 * 客户基本信息表 前端控制器
 * </p>
 *
 * @author YPZ
 * @since 2024-04-12
 */
@RestController
@Log4j2
@RequestMapping("/customer")
@Api(tags = "销售: 客户管理相关接口")
public class CustomerController {
    @Resource
    private CustomerService customerService;
    @Resource
    private BusinessService businessService;
    @Resource
    private OrderFormService orderFormService;
    @Resource
    private CustomerUserFollowService customerUserFollowService;
    @Resource
    private CustomerFollowUpService customerFollowUpService;
    @Resource
    private SendRecordService sendRecordService;
    @Resource
    private WorkOrderService workOrderService;
    @Resource
    private TaskService taskService;
    @Resource
    private LiaisonService liaisonService;
    @Resource
    private MessageAssembleService assembleService;
    @Resource
    private CustomerMailRecordService mailRecordService;
    @Resource
    private SysResourceService resourceService;
    @Resource
    private CustomerMailBingMarkService customerMailBingMarkService;
    @Resource
    private QuotationService quotationService;
    @Resource
    private OperationLogService operationLogService;
    @Resource
    private CustomerOwnerRecordService customerOwnerRecordService;
    @Resource
    private RedisService redisService;

    @PostMapping(value = "/add")
    @ApiOperation(value = "客户管理-新增客户", notes = "客户管理-新增客户")
    @Transactional(rollbackFor = Throwable.class)
    public Result<?> add(@RequestBody CustomerAddDTO customerAddDTO) {
        return customerService.addCustomer(customerAddDTO);
    }

    @PostMapping(value = "/add-check")
    @ApiOperation(value = "客户管理-新增客户校验", notes = "客户管理-新增客户校验")
    @Transactional(rollbackFor = Throwable.class)
    public Result<?> addCheck(@RequestBody CustomerAddDTO customerAddDTO) {
        return customerService.addCheck(customerAddDTO);
    }

    @PostMapping(value = "/add-check-by-field")
    @ApiOperation(value = "客户管理-新增客户校验", notes = "客户管理-新增客户校验")
    @Transactional(rollbackFor = Throwable.class)
    public Result<?> addCheckByField(@RequestBody CustomerCheckDTO customerCheckDTO) {
        CustomerAddDTO customerAddDTO = new CustomerAddDTO();
        customerAddDTO.setHasPublicCustomer(true);
        if (ObjectUtils.isEmpty(customerCheckDTO.getCustomerForm()) || customerCheckDTO.getCustomerForm() == 10) {
            customerAddDTO.setCustomerForm(10);

        }else{
            customerAddDTO.setCustomerForm(11);
        }

        if (customerCheckDTO.getFieldCode().equals("customerName")) {
            customerAddDTO.setCustomerName(customerCheckDTO.getBlurry());
        }
        if (customerCheckDTO.getFieldCode().equals("customerCompany.website")) {
            CustomerCompanyAddDTO customerCompany = new CustomerCompanyAddDTO();

            BeanUtils.copyProperties(customerCheckDTO, customerCompany);
            if (!ObjectUtils.isEmpty(customerCheckDTO.getBlurry())){
                customerCompany.setWebsite(customerCheckDTO.getBlurry());
            }
            customerAddDTO.setCustomerCompany(customerCompany);
        }
        if (customerCheckDTO.getFieldCode().equals("customerCompany.email")) {
            CustomerCompanyAddDTO customerCompany = new CustomerCompanyAddDTO();

            BeanUtils.copyProperties(customerCheckDTO, customerCompany);
            if (!ObjectUtils.isEmpty(customerCheckDTO.getBlurry())){
                customerCompany.setEmail(customerCheckDTO.getBlurry());
            }
            customerAddDTO.setCustomerCompany(customerCompany);
        }
        if (customerCheckDTO.getFieldCode().equals("liaison.email")) {
            LiaisonAddDTO liaison = new LiaisonAddDTO();
            BeanUtils.copyProperties(customerCheckDTO, liaison);
            liaison.setId(customerCheckDTO.getId());
            if (!ObjectUtils.isEmpty(customerCheckDTO.getBlurry())){
                liaison.setEmail(customerCheckDTO.getBlurry());
            }
            if (!ObjectUtils.isEmpty(customerCheckDTO.getId())){
                LiaisonEntity liaisonEntity = liaisonService.getById(customerCheckDTO.getId());
                customerAddDTO.setId(liaisonEntity.getCustomerId());
            }
            customerAddDTO.setLiaison(liaison);
        }

        return customerService.addCheck(customerAddDTO);
    }

    @PostMapping(value = "/edit")
    @ApiOperation(value = "客户管理-编辑客户", notes = "客户管理-编辑客户")
    @Transactional(rollbackFor = Throwable.class)
    public Result<?> edit(@RequestBody CustomerAddDTO customerAddDTO) {
        return customerService.editCustomer(customerAddDTO);
    }

    @PostMapping(value = "/chenge-clus-status")
    @ApiOperation(value = "客户管理-变更线索状态", notes = "客户管理-变更线索状态")
    @Transactional(rollbackFor = Throwable.class)
    public Result<?> chengeClusStatus(@RequestBody CustomerAddDTO customerAddDTO) {
        return customerService.chengeClusStatus(customerAddDTO);
    }

    @PostMapping(value = "/edit-list")
    @ApiOperation(value = "客户管理-批量编辑客户", notes = "客户管理-批量编辑客户")
    @Transactional(rollbackFor = Throwable.class)
    public Result<?> editList(@RequestBody CustomerEditListDTO customerEditListDTO) {
        List<CustomerEntity> customerList = new ArrayList<>();
        for (Long id : customerEditListDTO.getIdList()) {
            CustomerEntity customerEntity = new CustomerEntity();
            BeanUtils.copyProperties(customerEditListDTO.getCustomer(), customerEntity);
            customerEntity.setId(id);
            customerEntity.setEmptyStringsToNull();
            customerList.add(customerEntity);
        }
        boolean success = customerService.updateBatchById(customerList);
//        boolean success = customerService.saveOrUpdateBatch(customerList);
        if (success) {
            return Result.ok();
        }
        return Result.error("批量编辑客户失败");
    }

    @PostMapping(value = "/for-reason")
    @ApiOperation(value = "客户管理-移入公海", notes = "客户管理-移入公海")
    @Transactional(rollbackFor = Throwable.class)
    public Result<?> forReson(@RequestBody CustomerForReasonDTO customerForReason) {
        return customerService.forReson(customerForReason);
    }

    @PostMapping(value = "/data-count")
    @ApiOperation(value = "客户管理-关联数据统计", notes = "客户管理-关联数据统计")
    @Transactional(rollbackFor = Throwable.class)
    public Result<CustomerCountVO> dataCount(@RequestBody CustomerCountDTO customerCountDTO) {
        CustomerCountVO customerCountVO = new CustomerCountVO();
        //操作日志
        QueryWrapper olWrapper =  new QueryWrapper<>();
        olWrapper.eq("resource_type_id", customerCountDTO.getId());
        olWrapper.eq("resource_type", 10);
        olWrapper.eq("is_delete", CommonConstant.DEL_FLAG_0);
        QueryWrapper wrapper =  new QueryWrapper<>();
        wrapper.eq("customer_id", customerCountDTO.getId());
        wrapper.eq("is_delete", CommonConstant.DEL_FLAG_0);
        customerCountVO.setOrderFormCount(orderFormService.count(wrapper));
        customerCountVO.setBusinessCount(businessService.count(wrapper));
        customerCountVO.setWorkOrderCount(workOrderService.count(wrapper));
        customerCountVO.setTaskCount(taskService.count(wrapper));
        customerCountVO.setSendRecordCount(sendRecordService.count(wrapper));
        customerCountVO.setLisionCount(liaisonService.count(wrapper));
        customerCountVO.setFollowUpCount(customerFollowUpService.count(wrapper));
        customerCountVO.setEmailCount(customerMailBingMarkService.count(wrapper));
        LambdaQueryWrapper<QuotationEntity> quotatiomWrapper = new LambdaQueryWrapper<>();
        quotatiomWrapper.eq(QuotationEntity::getCustomerId, customerCountDTO.getId());
        quotatiomWrapper.eq(QuotationEntity::getIsDelete, CommonConstant.DEL_FLAG_0);
        List<QuotationEntity> quotationEntities = quotationService.list(quotatiomWrapper);
        BigDecimal totalOrderAmt = BigDecimal.ZERO;
        if (!quotationEntities.isEmpty()) {
            totalOrderAmt = quotationEntities.stream()
                                             .map(QuotationEntity::getTotalOrderAmt)
                                             .reduce(BigDecimal.ZERO, BigDecimal::add);
        }
        customerCountVO.setQuotationCount(totalOrderAmt);
        customerCountVO.setAttachmentCount(resourceService.count(wrapper));
        customerCountVO.setOwnerCount(customerOwnerRecordService.count(wrapper));

        customerCountVO.setOperationCount(operationLogService.count(olWrapper));
//        LambdaQueryWrapper<TaskEntity> taskWrapper = new LambdaQueryWrapper<>();
//        taskWrapper.eq(TaskEntity::getIsDelete, CommonConstant.DEL_FLAG_0);
//        taskWrapper.eq(TaskEntity::getResourceType, ResourceTypeEnum.CUSTOMER.code);
//        taskWrapper.eq(TaskEntity::getResourceTypeId, customerCountDTO.getId());
//        customerCountVO.setTaskCount(taskService.count(taskWrapper));
        return Result.result(customerCountVO);
    }

    @PostMapping(value = "/collaborator")
    @ApiOperation(value = "通用添加协作", notes = "通用添加协作")
    public Result<?> collaborator(@RequestBody CustomerCollaboratorDTO customerCollaboratorDTO) {
        //添加/修改客户协作人员
        if (customerCollaboratorDTO.getResourceType().equals(ResourceTypeEnum.CUSTOMER.code)){
            return customerService.collaborator(customerCollaboratorDTO);
        }
        if (customerCollaboratorDTO.getResourceType().equals(ResourceTypeEnum.BUSINESS.code)){
            return businessService.collaborator(customerCollaboratorDTO);
        }
        if (customerCollaboratorDTO.getResourceType().equals(ResourceTypeEnum.ORDER_FORM.code)){
            return orderFormService.collaborator(customerCollaboratorDTO);
        }

        return Result.error("未配置");

    }

    @PostMapping(value = "/convert-to-customer")
    @ApiOperation(value = "客户管理-线索转为客户", notes = "客户管理-线索转为客户")
    @Transactional(rollbackFor = Throwable.class)
    public Result<?> convertToCustomer(@RequestBody CustomerConvertDTO customerConvert) {
        return customerService.convertToCustomer(customerConvert);
    }

    @PostMapping(value = "/collect-clues")
    @ApiOperation(value = "客户管理-领取客户/线索", notes = "客户管理-领取客户/线索")
//    @Transactional(rollbackFor = Throwable.class)
    public Result<?> collectClues(@RequestBody CustomerCollectCluesDTO collectCluesDTO) {
        return customerService.collectClues(collectCluesDTO);
    }

    @PostMapping(value = "/assign-clues")
    @ApiOperation(value = "客户管理-分配线索", notes = "客户管理-分配线索")
    @Transactional(rollbackFor = Throwable.class)
    public Result<?> assignClues(@RequestBody CustomerAssignCluesDTO customerAssignCluesDTO) {
        return customerService.assignClues(customerAssignCluesDTO);
    }

    @PostMapping(value = "/merge")
    @ApiOperation(value = "客户管理-合并客户", notes = "客户管理-合并客户")
    public Result<?> merge(@RequestBody CustomerMergeDTO customerMergeDTO) {
        //校验合并客户和被合并客户是否已删除
        CustomerEntity customer = customerService.getById(customerMergeDTO.getId());
        if (customer == null || customer.getIsDelete().equals(CommonConstant.DEL_FLAG_1)) {
            return Result.error("客户不存在！");
        }
        CustomerEntity fromCustomer = customerService.getById(customerMergeDTO.getFromId());
        if (fromCustomer == null || fromCustomer.getIsDelete().equals(CommonConstant.DEL_FLAG_1)) {
            return Result.error("被合并客户不存在！");
        }
        return customerService.mergeCustomer(customerMergeDTO);
    }

    @PostMapping(value = "/list")
    @ApiOperation(value = "客户管理查询-列表", notes = "客户管理查询-列表")
    public Result<IPage<CustomerListVO>> list(@RequestBody CustomerSearchDTO customerSearchDTO) {

        return customerService.selectListVO(customerSearchDTO);
    }

    /**
     * 通过id查询
     *
     * @return
     */
    @PostMapping(value = "/get-by-id")
    @ApiOperation(value = "客户管理查询-通过id查看详情", notes = "客户管理查询-通过id查看详情")
    public Result<CustomerVO> getById(@RequestParam(name="id",required=false) Long id) {
        CustomerVO customerVO = customerService.getCustomerVOById(id);
        return Result.result(customerVO);
    }

    @PostMapping(value = "/get-all-by-id")
    @ApiOperation(value = "客户管理查询-通过id查看客户资料详情", notes = "客户管理查询-通过id查看客户资料详情")
    public Result<CustomerAllVO> getAllById(@RequestBody CustomerSearchDTO customerSearchDTO) {
        CustomerAllVO customerAllVO = customerService.getCustomerAllVOById(customerSearchDTO);
        return Result.result(customerAllVO);
    }

    @PostMapping(value = "/get-pre-nex-by-id")
    @ApiOperation(value = "客户管理查询-通过id查看客户资料详情", notes = "客户管理查询-通过id查看客户资料详情")
    public Result<CustomerAllVO> getAllByIdlist(@RequestBody CustomerSearchDTO customerSearchDTO) {
        String jsonKey = JSON.toJSONString(customerSearchDTO.getPreNextScopeMenuId()+"_"+customerSearchDTO.getCustomerBelongType()+"_"+ LoginUserUtil.getCurrentUserId());
        log.error("jsonKey 2= "+jsonKey);
        String preNexKey = MD5Util.MD5Encode(jsonKey,"UTF-8");
        CustomerAllVO customerAllVO = customerService.getCustomerAllVOById(customerSearchDTO);
        Object ids = redisService.getCacheObject(preNexKey);
        findNeighbors(ids,customerAllVO);
        return Result.result(customerAllVO);
    }

    public static void findNeighbors(Object ids, CustomerAllVO customerAllVO) {
        try {
            List<Long> list =  (List)ids;
            Long target = customerAllVO.getId();
            if (CollectionUtils.isEmpty(list) || Objects.isNull(target)) {
                return;
            }
            int index = list.indexOf(target);
            if (index == -1) {
                return;
            }
            // 查找上一个元素
            if (index > 0) {
                customerAllVO.setPreviousId(list.get(index - 1));
            }
            // 查找下一个元素
            if (index < list.size() - 1) {
                customerAllVO.setNextId(list.get(index + 1));
            }
        }catch (Exception e) {
            log.error("findNeighbors -- error",e);
        }
    }

//    @PostMapping(value = "/testUpdateFolowTime")
//    @ApiOperation(value = "")
//    public Result updateFolowTime() {
//        Set<String> mails = Set.of("fan@storlead.com","152522@qq.com","255522002@qq.com","96444526@163.com","qiyeyouxiang1@163.com","63871999@163.com","baidukeji000003@keji.com");
//        customerService.updateFollowUpTimeByEmail(mails, LocalDateTime.now());
//        return Result.ok();
//    }

    @PostMapping(value = "/add-follow")
    @ApiOperation(value = "客户管理-新增重点关注", notes = "客户管理-新增重点关注")
    @Transactional(rollbackFor = Throwable.class)
    public Result<?> addFollow(@RequestBody BusinessAddOrDeleteDTO businessAddOrDeleteDTO) {
        CustomerEntity customer = new CustomerEntity();
        customer.setId(businessAddOrDeleteDTO.getCustomerId());
        customer.setHasFollowCustomer(true);
        boolean success = customerService.updateById(customer);
        if (!success){
            return Result.error("关注失败！");
        }
        return Result.ok();
    }

    @PostMapping(value = "/cancel")
    @ApiOperation(value = "客户管理-取消重点关注", notes = "客户管理-取消重点关注")
    @Transactional(rollbackFor = Throwable.class)
    public Result<?> cancel(@RequestBody BusinessAddOrDeleteDTO businessAddOrDeleteDTO) {
        CustomerEntity customer = new CustomerEntity();
        customer.setId(businessAddOrDeleteDTO.getCustomerId());
        customer.setHasFollowCustomer(false);
        boolean success = customerService.updateById(customer);
        if (!success){
            return Result.error("取消关注失败！");
        }
        return Result.ok();
    }

    @ApiOperation(value = "客户管理-删除客户", notes = "客户管理-删除客户")
    @PostMapping("delete")
    public Result delete(Long id) {
        if(Objects.isNull(id)) {
            return Result.error("参数错误");
        }
//      boolean success = customerService.lgDelete(id);
        CustomerEntity customer = customerService.getById(id);
        if (Objects.isNull(customer)) {
            return Result.error("参数错误，没有找到对应客户");
        }
        Integer busCount = businessService.count(new LambdaQueryWrapper<BusinessEntity>().eq(BusinessEntity::getCustomerId,customer.getId()).eq(BusinessEntity::getIsDelete,CommonConstant.DEL_FLAG_0));
        if (busCount > 0) {
            return Result.error("该客户有商机，无法删除");
        }
        Integer orderCount = orderFormService.count(new LambdaQueryWrapper<OrderFormEntity>().eq(OrderFormEntity::getCustomerId,customer.getId()).eq(OrderFormEntity::getIsDelete,CommonConstant.DEL_FLAG_0));
        if (orderCount > 0) {
            return Result.error("该客户有订单，无法删除");
        }
        Integer sendCount = sendRecordService.count(new LambdaQueryWrapper<SendRecordEntity>().eq(SendRecordEntity::getCustomerId,customer.getId()).eq(SendRecordEntity::getIsDelete,CommonConstant.DEL_FLAG_0));
        if (sendCount > 0) {
            return Result.error("该客户已有寄样，无法删除");
        }
        //删除所有关联数据
        boolean success = customerService.glAllDelete(id);
        if (!success){
            return Result.error("删除失败");
        }
        //发送消息
        if (ResourceTypeEnum.CUSTOMER.code.equals(customer.getCustomerForm().toString())){
            //线索
            assembleService.sendCustomerEventMessages(id,"DELETE_CUSTOMER");
        }
        List<CustomerFollowUpEntity> followUpls = customerFollowUpService.listByResourceId(ResourceTypeEnum.CUSTOMER.code,id);
        if (!CollectionUtils.isEmpty(followUpls)) {
            List<Long> followUpIds = followUpls.stream().map(CustomerFollowUpEntity::getId).collect(Collectors.toList());
            if (!CollectionUtils.isEmpty(followUpIds)) {
                resourceService.deleteByResourceIds(ResourceTypeEnum.FOLLOW_UP.code,followUpIds);
            }
        }
        //删除任务
        taskService.deleteByResourceId(ResourceTypeEnum.CUSTOMER.code, id);
        customerFollowUpService.deleteByResourceId(ResourceTypeEnum.CUSTOMER.code, id);
        resourceService.deleteByResourceId(ResourceTypeEnum.CUSTOMER.code,id);
        return Result.ok();
    }
}
