package com.yd.csf.api.service.impl;

import com.alibaba.fastjson2.JSON;
import com.yd.base.feign.client.relobjectcertificate.ApiRelObjectCertificateFeignClient;
import com.yd.base.feign.dto.ApiCertificateDto;
import com.yd.base.feign.request.relobjectcertificate.ApiRelObjectCertificateListAddRequest;
import com.yd.base.feign.request.relobjectcertificate.ApiRelObjectCertificateListRequest;
import com.yd.base.feign.response.relobjectcertificate.ApiRelObjectCertificateListResponse;
import com.yd.common.enums.CommonEnum;
import com.yd.common.enums.ResultCode;
import com.yd.common.exception.BusinessException;
import com.yd.common.result.Result;
import com.yd.common.utils.RandomStringGenerator;
import com.yd.csf.api.service.ApiAppointmentCheckService;
import com.yd.csf.api.service.ApiInsurantService;
import com.yd.csf.api.service.ApiTaxationService;
import com.yd.csf.feign.dto.appointment.ApiInsurantInfoDto;
import com.yd.csf.feign.dto.taxation.ApiObjectTaxationDto;
import com.yd.csf.feign.dto.taxation.ApiTaxationDto;
import com.yd.csf.feign.utils.CommonUtil;
import com.yd.csf.feign.enums.RelTypeEnum;
import com.yd.csf.service.model.Insurant;
import com.yd.csf.service.model.Policyholder;
import com.yd.csf.service.model.Taxation;
import com.yd.csf.service.service.IInsurantService;
import com.yd.csf.service.service.IPolicyholderService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * 受保人信息业务实现类
 */
@Slf4j
@Service
public class ApiInsurantServiceImpl implements ApiInsurantService {

    @Autowired
    private IInsurantService iInsurantService;

    @Autowired
    private IPolicyholderService iPolicyholderService;

    @Autowired
    private ApiAppointmentCheckService apiAppointmentCheckService;

    @Autowired
    private ApiTaxationService apiTaxationService;

    @Autowired
    private ApiRelObjectCertificateFeignClient apiRelObjectCertificateFeignClient;

    /**
     * 受保人信息详情
     * @param appointmentBizId 预约信息主表唯一业务ID
     * @param insurantBizId 受保人信息表唯一业务ID
     * @return
     */
    @Override
    public Result<ApiInsurantInfoDto> detail(String appointmentBizId, String insurantBizId) {
        Insurant insurant = iInsurantService.queryOne(appointmentBizId,insurantBizId);
        ApiInsurantInfoDto dto = null;
        if (!Objects.isNull(insurant)) {
            dto = new ApiInsurantInfoDto();
            BeanUtils.copyProperties(insurant,dto);
            //地址列表
            dto.setAddressList(CommonUtil.getAddressList(insurant.getAddressList()));
            //查询证件列表信息
            dto.setApiCertificateDtoList(apiCertificateDtoList(insurant.getInsurantBizId()));

            dto.setApiTaxationDtoList(apiTaxationService.apiTaxationDtoList(insurant.getInsurantBizId()));
        }
        return Result.success(dto);
    }

    /**
     * 查询证件列表信息
     * @param insurantBizId
     * @return
     */
    public List<ApiCertificateDto> apiCertificateDtoList(String insurantBizId) {
        List<ApiCertificateDto> apiCertificateDtoList = new ArrayList<>();
        //查询受保人证件列表信息
        Result<List<ApiRelObjectCertificateListResponse>> result = apiRelObjectCertificateFeignClient.list(ApiRelObjectCertificateListRequest.builder()
                .objectBizId(insurantBizId)
                .build());
        if (!CollectionUtils.isEmpty(result.getData())) {
            apiCertificateDtoList = result.getData().stream().map(dto -> {
                ApiCertificateDto apiCertificateDto = new ApiCertificateDto();
                BeanUtils.copyProperties(dto,apiCertificateDto);
                return apiCertificateDto;
            }).collect(Collectors.toList());
        }
        return apiCertificateDtoList;
    }

    /**
     * 编辑受保人信息
     * @param apiInsurantInfoDto
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Result edit(ApiInsurantInfoDto apiInsurantInfoDto) {
        //编辑预约入参字段校验 - 受保人信息字段校验
        apiAppointmentCheckService.checkEditApiInsurantInfoDto(apiInsurantInfoDto);

        //编辑受保人信息表数据
//        editInsurantData(apiInsurantInfoDto,apiInsurantInfoDto.getAppointmentBizId());
        return Result.success();
    }

    /**
     * 添加受保人信息表数据
     * @param dto
     * @param appointmentBizId
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Result<Insurant> addInsurantData(ApiInsurantInfoDto dto, String appointmentBizId) {
        if (Objects.isNull(dto)){
            //为空设置，方便新建暂存公用方法
            dto = new ApiInsurantInfoDto();
        }
        Insurant insurant = new Insurant();
        //与投保人关系
        if (RelTypeEnum.MYSELF.getItemValue().equals(dto.getPolicyholderRel())) {
            //与投保人关系如果是本人，直接查询投保人信息表新增数据到受保人信息表中
            Policyholder policyholder = iPolicyholderService.queryOne(appointmentBizId,"");
            if (!Objects.isNull(policyholder)) {
                BeanUtils.copyProperties(policyholder,insurant);
                insurant.setId(null);
                insurant.setAppointmentBizId(appointmentBizId);
                insurant.setInsurantBizId(RandomStringGenerator.generateBizId16(CommonEnum.UID_TYPE_INSURANT.getCode()));
                insurant.setPolicyholderRel(dto.getPolicyholderRel());
                iInsurantService.saveOrUpdate(insurant);

                //查询投保人税务列表信息
                Result<List<Taxation>> listResult = apiTaxationService.list(ApiObjectTaxationDto.builder().objectBizId(policyholder.getPolicyholderBizId()).build());
                if (!CollectionUtils.isEmpty(listResult.getData())) {
                    List<ApiTaxationDto> apiTaxationDtoList = listResult.getData().stream().map(d -> {
                        ApiTaxationDto apiTaxationDto = new ApiTaxationDto();
                        apiTaxationDto.setTaxCountry(d.getTaxCountry());
                        apiTaxationDto.setTaxId(d.getTaxId());
                        return apiTaxationDto;
                    }).collect(Collectors.toList());
                    apiTaxationService.saveTaxationList(ApiObjectTaxationDto.builder()
                            .objectBizId(insurant.getInsurantBizId())
                            .objectName(CommonEnum.UID_TYPE_INSURANT.getName())
                            .objectTableName(CommonEnum.UID_TYPE_INSURANT.getCode())
                            .objectType(CommonEnum.UID_TYPE_INSURANT.getCode())
                            .apiTaxationDtoList(apiTaxationDtoList)
                            .build());
                }

                //查询投保人证件列表信息
                Result<List<ApiRelObjectCertificateListResponse>> certificateListResult = apiRelObjectCertificateFeignClient.list(ApiRelObjectCertificateListRequest.builder().objectBizId(policyholder.getPolicyholderBizId()).build());
                if (!CollectionUtils.isEmpty(certificateListResult.getData())) {
                    List<ApiCertificateDto> apiCertificateDtoList = certificateListResult.getData()
                            .stream().map(d -> {
                                ApiCertificateDto apiCertificateDto = new ApiCertificateDto();
                                BeanUtils.copyProperties(d,apiCertificateDto);
                                return apiCertificateDto;
                            }).collect(Collectors.toList());
                    //添加受保人证件列表信息
                    apiRelObjectCertificateFeignClient.addRelObjectCertificateList(ApiRelObjectCertificateListAddRequest.builder()
                            .objectBizId(insurant.getInsurantBizId())
                            .objectName(CommonEnum.UID_TYPE_INSURANT.getName())
                            .objectTableName(CommonEnum.UID_TYPE_INSURANT.getCode())
                            .objectType(CommonEnum.UID_TYPE_INSURANT.getCode())
                            .apiCertificateDtoList(apiCertificateDtoList)
                            .build());
                }
                return Result.success(insurant);
            }
        }

        //受保人信息信息
        BeanUtils.copyProperties(dto,insurant);
        //生成受保人信息表唯一业务ID
        insurant.setInsurantBizId(RandomStringGenerator.generateBizId16(CommonEnum.UID_TYPE_INSURANT.getCode()));
        //预约信息主表唯一业务ID
        insurant.setAppointmentBizId(appointmentBizId);
        //地址列表（json串）
        insurant.setAddressList(CommonUtil.getAddressListJsonStr(dto.getAddressList()));
        iInsurantService.saveOrUpdate(insurant);

        //添加受保人税务列表信息
        if (!CollectionUtils.isEmpty(dto.getApiTaxationDtoList())) {
            apiTaxationService.saveTaxationList(ApiObjectTaxationDto.builder()
                    .objectBizId(insurant.getInsurantBizId())
                    .objectName(CommonEnum.UID_TYPE_INSURANT.getName())
                    .objectTableName(CommonEnum.UID_TYPE_INSURANT.getCode())
                    .objectType(CommonEnum.UID_TYPE_INSURANT.getCode())
                    .apiTaxationDtoList(dto.getApiTaxationDtoList())
                    .build());
        }

        //添加受保人证件列表信息
        if (!CollectionUtils.isEmpty(dto.getApiCertificateDtoList())) {
            apiRelObjectCertificateFeignClient.addRelObjectCertificateList(ApiRelObjectCertificateListAddRequest.builder()
                    .objectBizId(insurant.getInsurantBizId())
                    .objectName(CommonEnum.UID_TYPE_INSURANT.getName())
                    .objectTableName(CommonEnum.UID_TYPE_INSURANT.getCode())
                    .objectType(CommonEnum.UID_TYPE_INSURANT.getCode())
                    .apiCertificateDtoList(dto.getApiCertificateDtoList())
                    .build());
        }
        return Result.success(insurant);
    }

    /**
     * 编辑受保人信息表数据
     * @param dto
     * @param appointmentBizId
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Result<Insurant> editInsurantData(ApiInsurantInfoDto dto, String appointmentBizId) {
        if (Objects.isNull(dto)){
            //受保人信息对象不能为空
            throw new BusinessException("受保人信息不能为空");
        }
        if (StringUtils.isBlank(dto.getInsurantBizId())) {
            throw new BusinessException("受保人信息表唯一业务ID不能为空");
        }
        Result<Insurant> result = checkInsurantIsExist(dto.getInsurantBizId());
        //受保人信息信息
        Insurant insurant = result.getData();
        Long insurantId = insurant.getId();

        //与投保人关系
        if (RelTypeEnum.MYSELF.getItemValue().equals(dto.getPolicyholderRel())) {
            //与投保人关系如果是本人，直接查询投保人信息表更新数据到受保人信息表中
            Policyholder policyholder = iPolicyholderService.queryOne(appointmentBizId,"");
            if (!Objects.isNull(policyholder)) {
                log.info("与投保人关系如果是本人，直接查询投保人信息表更新数据到受保人信息表中之前result.getData(),{}", JSON.toJSONString(result));
                log.info("与投保人关系如果是本人，直接查询投保人信息表更新数据到受保人信息表中之前,{}", JSON.toJSONString(insurant));
                BeanUtils.copyProperties(policyholder,insurant);
                insurant.setId(insurantId);
                insurant.setAppointmentBizId(appointmentBizId);
                log.info("与投保人关系如果是本人，直接查询投保人信息表更新数据到受保人信息表中之后,{}", JSON.toJSONString(insurant));
                iInsurantService.saveOrUpdate(insurant);

                //查询投保人税务列表信息
                Result<List<Taxation>> listResult = apiTaxationService.list(ApiObjectTaxationDto.builder().objectBizId(policyholder.getPolicyholderBizId()).build());
                if (!CollectionUtils.isEmpty(listResult.getData())) {
                    List<ApiTaxationDto> apiTaxationDtoList = listResult.getData().stream().map(d -> {
                        ApiTaxationDto apiTaxationDto = new ApiTaxationDto();
                        apiTaxationDto.setTaxCountry(d.getTaxCountry());
                        apiTaxationDto.setTaxId(d.getTaxId());
                        return apiTaxationDto;
                    }).collect(Collectors.toList());
                    apiTaxationService.saveTaxationList(ApiObjectTaxationDto.builder()
                            .objectBizId(insurant.getInsurantBizId())
                            .objectName(CommonEnum.UID_TYPE_INSURANT.getName())
                            .objectTableName(CommonEnum.UID_TYPE_INSURANT.getCode())
                            .objectType(CommonEnum.UID_TYPE_INSURANT.getCode())
                            .apiTaxationDtoList(apiTaxationDtoList)
                            .build());
                }

                //查询投保人证件列表信息
                Result<List<ApiRelObjectCertificateListResponse>> certificateListResult = apiRelObjectCertificateFeignClient.list(ApiRelObjectCertificateListRequest.builder().objectBizId(policyholder.getPolicyholderBizId()).build());
                if (!CollectionUtils.isEmpty(certificateListResult.getData())) {
                    List<ApiCertificateDto> apiCertificateDtoList = certificateListResult.getData()
                            .stream().map(d -> {
                                ApiCertificateDto apiCertificateDto = new ApiCertificateDto();
                                BeanUtils.copyProperties(d,apiCertificateDto);
                                return apiCertificateDto;
                            }).collect(Collectors.toList());
                    //添加受保人证件列表信息
                    apiRelObjectCertificateFeignClient.addRelObjectCertificateList(ApiRelObjectCertificateListAddRequest.builder()
                            .objectBizId(insurant.getInsurantBizId())
                            .objectName(CommonEnum.UID_TYPE_INSURANT.getName())
                            .objectTableName(CommonEnum.UID_TYPE_INSURANT.getCode())
                            .objectType(CommonEnum.UID_TYPE_INSURANT.getCode())
                            .apiCertificateDtoList(apiCertificateDtoList)
                            .build());
                }
                return Result.success(insurant);
            }
        }

        BeanUtils.copyProperties(dto,insurant);
        //预约信息主表唯一业务ID
        insurant.setAppointmentBizId(appointmentBizId);
        //地址列表（json串）
        insurant.setAddressList(CommonUtil.getAddressListJsonStr(dto.getAddressList()));
        iInsurantService.saveOrUpdate(insurant);

        //添加受保人税务列表信息
        if (!CollectionUtils.isEmpty(dto.getApiTaxationDtoList())) {
            apiTaxationService.saveTaxationList(ApiObjectTaxationDto.builder()
                    .objectBizId(insurant.getInsurantBizId())
                    .objectName(CommonEnum.UID_TYPE_INSURANT.getName())
                    .objectTableName(CommonEnum.UID_TYPE_INSURANT.getCode())
                    .objectType(CommonEnum.UID_TYPE_INSURANT.getCode())
                    .apiTaxationDtoList(dto.getApiTaxationDtoList())
                    .build());
        }

        //添加受保人证件列表信息
        if (!CollectionUtils.isEmpty(dto.getApiCertificateDtoList())) {
            apiRelObjectCertificateFeignClient.addRelObjectCertificateList(ApiRelObjectCertificateListAddRequest.builder()
                    .objectBizId(insurant.getInsurantBizId())
                    .objectName(CommonEnum.UID_TYPE_INSURANT.getName())
                    .objectTableName(CommonEnum.UID_TYPE_INSURANT.getCode())
                    .objectType(CommonEnum.UID_TYPE_INSURANT.getCode())
                    .apiCertificateDtoList(dto.getApiCertificateDtoList())
                    .build());
        }
        return Result.success(insurant);
    }

    /**
     * 校验受保人信息是否存在
     * @param insurantBizId
     * @return
     */
    public Result<Insurant> checkInsurantIsExist(String insurantBizId) {
        Insurant insurant = iInsurantService.queryOne(insurantBizId);
        if (Objects.isNull(insurant)) {
            //数据不存在
            throw new BusinessException(ResultCode.NULL_ERROR.getCode(),ResultCode.NULL_ERROR.getMessage());
        }
        return Result.success(insurant);
    }

}
