package com.trade.admin.tradingplatform.service.impl;

import cn.hutool.core.util.StrUtil;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.trade.admin.system.domain.entity.SysUser;
import com.trade.admin.system.security.utils.SecurityUtils;
import com.trade.admin.system.service.ISysUserService;
import com.trade.admin.tradingplatform.service.TradingPlatformService;
import com.trade.common.constant.HttpStatus;
import com.trade.common.core.page.GridPage;
import com.trade.common.exception.ValidatorException;
import com.trade.common.utils.ConstantUtil;
import com.trade.common.utils.LoggerUtil;
import com.trade.common.utils.bean.BeanUtils;
import com.trade.common.validate.ValidatorGroup;
import com.trade.common.validate.ValidatorUtil;
import com.trade.service.DictConstants;
import com.trade.service.TransStruct;
import com.trade.service.serialNum.service.SerialNumberGenerator;
import com.trade.service.thirdparty.xiaotu.configuration.XiaotuConfiguration;
import com.trade.service.thirdparty.xiaotu.dto.*;
import com.trade.service.thirdparty.xiaotu.service.XiaotuRequestService;
import com.trade.service.tradingplatform.domain.TradingPlatform;
import com.trade.service.tradingplatform.domain.TradingPlatformInsurance;
import com.trade.service.tradingplatform.domain.TradingPlatformQualification;
import com.trade.service.tradingplatform.dto.*;
import com.trade.service.tradingplatform.service.TradingPlatformBaseService;
import com.trade.service.tradingplatform.service.TradingPlatformInsuranceBaseService;
import com.trade.service.tradingplatform.service.TradingPlatformQualificationBaseService;
import org.slf4j.Logger;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.Collections;
import java.util.List;
import java.util.Objects;

/**
 * 贸易平台服务实现类
 *
 * @author hlb
 * @since 2024-06-05 17:00:44
 */
@Service("tradingPlatformService")
public class TradingPlatformServiceImpl implements TradingPlatformService {

    private static final Logger log = LoggerUtil.logger(LoggerUtil.LogFileNameEnum.SERVICES_LOG);
    @Resource
    private TradingPlatformBaseService tradingPlatformBaseService;
    @Resource
    private TradingPlatformQualificationBaseService tradingPlatformQualificationBaseService;
    @Resource
    private TradingPlatformInsuranceBaseService tradingPlatformInsuranceBaseSService;
    @Resource
    private SerialNumberGenerator serialNumberGenerator;
    @Resource
    private TransStruct transStruct;
    @Resource
    private XiaotuRequestService xiaotuRequestService;
    @Resource
    private XiaotuConfiguration xiaotuConfiguration;
    @Resource
    private ISysUserService sysUserService;

    @Override
    public GridPage<TradingPlatformBaseInfo> getPages(TradingPlatformSearchDto search) {
        Page<TradingPlatformBaseInfo> page = PageHelper.startPage(search.getPage(), search.getRows());
        List<TradingPlatformBaseInfo> result = tradingPlatformBaseService.findBySearch(search);
        return new GridPage<>(search.getRows(), search.getPage(), page.getTotal(), result);
    }

    @Override
    public List<TradingPlatform> getList() {
        return tradingPlatformBaseService.lambdaQuery().eq(TradingPlatform::getDraft, false).list();
    }

    @Override
    public TradingPlatformDto queryById(Long id) {
        return tradingPlatformBaseService.findDetailInfoById(id);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Long saveTradingPlatform(Boolean confirmed, TradingPlatformDto tradingPlatformDto) {
        checkUnique(tradingPlatformDto);
        TradingPlatform rawTradingPlatform = null;
        if (tradingPlatformDto.getId() != null && confirmed) {
            rawTradingPlatform = tradingPlatformBaseService.getById(tradingPlatformDto.getId());
            if (rawTradingPlatform == null) {
                throw new ValidatorException(HttpStatus.ERROR, "未找到对应的贸易平台信息！");
            }
        }
        String userNickName = SecurityUtils.getUserNickName();
        this.checkParams(confirmed, tradingPlatformDto);
        if (tradingPlatformDto.getId() == null) {
            String tradePlatformCode = serialNumberGenerator.nextValue(ConstantUtil.TRADE_PLATFORM);
            tradingPlatformDto.setPlatformCode(tradePlatformCode);
            tradingPlatformDto.setCreateBy(userNickName);
        } else {
            if (StrUtil.isEmpty(tradingPlatformDto.getPlatformCode())) {
                throw new ValidatorException(HttpStatus.ERROR, "平台编码不能为空！");
            }
            tradingPlatformDto.setUpdateBy(userNickName);
        }
        tradingPlatformDto.setDraft(!confirmed);
        TradingPlatform tradingPlatform = save(tradingPlatformDto);
        // 小图退税 用户及企业信息更新
        syncInfoToXiaotu(confirmed, tradingPlatform, rawTradingPlatform);
        return tradingPlatform.getId();
    }

    private void checkUnique(TradingPlatformDto tradingPlatformDto) {
        boolean anyMatch = tradingPlatformBaseService.lambdaQuery()
                .eq(TradingPlatform::getPlatformName, tradingPlatformDto.getPlatformName()).list().stream()
                .anyMatch(item -> !Objects.equals(item.getId(), tradingPlatformDto.getId()));
        if (anyMatch) {
            throw new ValidatorException(HttpStatus.ERROR, "平台名称已存在！");
        }
        anyMatch = tradingPlatformBaseService.lambdaQuery()
                .eq(TradingPlatform::getCertNo, tradingPlatformDto.getCertNo()).list().stream()
                .anyMatch(item -> !Objects.equals(item.getId(), tradingPlatformDto.getId()));
        if (anyMatch) {
            throw new ValidatorException(HttpStatus.ERROR, "统一社会信用代码/注册号已存在！");
        }
        if (StrUtil.isNotEmpty(tradingPlatformDto.getTaxNum())) {
            anyMatch = tradingPlatformBaseService.lambdaQuery()
                    .eq(TradingPlatform::getTaxNum, tradingPlatformDto.getTaxNum()).list().stream()
                    .anyMatch(item -> !Objects.equals(item.getId(), tradingPlatformDto.getId()));
            if (anyMatch) {
                throw new ValidatorException(HttpStatus.ERROR, "纳税人识别号已存在！");
            }
        }
        if (StrUtil.isNotEmpty(tradingPlatformDto.getCustomsEnterpriseCode())) {
            anyMatch = tradingPlatformBaseService.lambdaQuery()
                    .eq(TradingPlatform::getCustomsEnterpriseCode, tradingPlatformDto.getCustomsEnterpriseCode()).list()
                    .stream().anyMatch(item -> !Objects.equals(item.getId(), tradingPlatformDto.getId()));
            if (anyMatch) {
                throw new ValidatorException(HttpStatus.ERROR, "海关企业代码已存在！");
            }
        }
    }

    /**
     * 同步小图退税用户及企业信息
     * 
     * @param confirmed
     * @param tradingPlatform
     * @param rawTradingPlatform
     */
    private void syncInfoToXiaotu(Boolean confirmed, TradingPlatform tradingPlatform,
            TradingPlatform rawTradingPlatform) {
        // 暂存或者测试模式，不同步信息至小图
        if (!confirmed || xiaotuConfiguration.getTestMode()
                || !DictConstants.DISTRICT_CN_MAINLAND.equals(tradingPlatform.getDistrictCode())) {
            return;
        }
        SysUser sysUser = sysUserService.selectUserById(tradingPlatform.getXtAdminUserId());
        // 首次提交。（或者小图退税用户id和企业id都为空）
        if (rawTradingPlatform == null || rawTradingPlatform.getDraft()
                || (StrUtil.isEmpty(rawTradingPlatform.getXtUserId())
                        && StrUtil.isEmpty(rawTradingPlatform.getXtEid()))) {
            String xtUserId = getOrCreateXtUser(sysUser);
            String xtEid = null;
            EnterpriseInfo enterpriseInfo = xiaotuRequestService.searchEnterprise(xtUserId, tradingPlatform.getCertNo(),
                    null);
            if (enterpriseInfo != null) {
                xtEid = enterpriseInfo.getSbqyuuid();
            } else {
                // 企业信息注册
                RegisterEnterpriseRequest registerEnterpriseRequest = new RegisterEnterpriseRequest();
                registerEnterpriseRequest.setHgqyDm(tradingPlatform.getCustomsEnterpriseCode());
                registerEnterpriseRequest.setNsrmc(tradingPlatform.getPlatformName());
                registerEnterpriseRequest.setNsrsbh(tradingPlatform.getTaxNum());
                registerEnterpriseRequest.setShxydm(tradingPlatform.getCertNo());
                registerEnterpriseRequest.setDqcode(tradingPlatform.getTaxAuthorityArea());
                registerEnterpriseRequest.setCktsqylxDm(DictConstants.ENTERPRISE_TYPE_EXTERNAL_TRADE);
                registerEnterpriseRequest.setYhuuid1(xtUserId);
                registerEnterpriseRequest.setHstqysqbz(DictConstants.SYS_YES);
                registerEnterpriseRequest.setTsfwxybz(DictConstants.SYS_YES);
                RegisterEnterpriseResponse registerEnterpriseResponse = xiaotuRequestService
                        .registerEnterprise(registerEnterpriseRequest);
                xtEid = registerEnterpriseResponse.getSbqyuuid();
            }
            tradingPlatform.setXtEid(xtEid);
            tradingPlatform.setXtUserId(xtUserId);
            tradingPlatformBaseService.updateById(tradingPlatform);
        } else {
            // 更新企业信息
            tradingPlatform.setXtEid(rawTradingPlatform.getXtEid());
            tradingPlatform.setXtUserId(rawTradingPlatform.getXtUserId());
            updateXtEnterprise(tradingPlatform, rawTradingPlatform);
            if (!Objects.equals(tradingPlatform.getXtAdminUserId(), rawTradingPlatform.getXtAdminUserId())) {
                String xtUserId = getOrCreateXtUser(sysUser);
                // 解绑用户、企业关系
                xiaotuRequestService.unbindUserAndEnterprise(rawTradingPlatform.getXtUserId(),
                        tradingPlatform.getXtEid());
                // 绑定用户、企业关系
                xiaotuRequestService.bindUserAndEnterprise(xtUserId, tradingPlatform.getXtEid());
                tradingPlatform.setXtUserId(xtUserId);
                tradingPlatformBaseService.updateById(tradingPlatform);
            }
        }
    }

    /**
     * 更新小图退税企业信息
     * 
     * @param tradingPlatform
     * @param rawTradingPlatform
     */
    private void updateXtEnterprise(TradingPlatform tradingPlatform, TradingPlatform rawTradingPlatform) {
        // 海关代码、税号、主管税务机关不变，则不更新
        if (StrUtil.equals(tradingPlatform.getTaxNum(), rawTradingPlatform.getTaxNum())
                && StrUtil.equals(tradingPlatform.getCustomsEnterpriseCode(),
                        rawTradingPlatform.getCustomsEnterpriseCode())
                && StrUtil.equals(tradingPlatform.getTaxAuthorityArea(), rawTradingPlatform.getTaxAuthorityArea())) {
            return;
        }
        UpdateEnterpriseRequest updateEnterpriseRequest = new UpdateEnterpriseRequest();
        updateEnterpriseRequest.setSbqyuuid(tradingPlatform.getXtEid());
        updateEnterpriseRequest.setNsrmc(tradingPlatform.getPlatformName());
        updateEnterpriseRequest.setNsrsbh(tradingPlatform.getTaxNum());
        updateEnterpriseRequest.setDqcode(tradingPlatform.getTaxAuthorityArea());
        updateEnterpriseRequest.setCktsqylxDm(DictConstants.ENTERPRISE_TYPE_EXTERNAL_TRADE);
        updateEnterpriseRequest.setYhuuid1(tradingPlatform.getXtUserId());
        updateEnterpriseRequest.setHstqysqbz(DictConstants.SYS_YES);
        updateEnterpriseRequest.setTsfwxybz(DictConstants.SYS_YES);
        updateEnterpriseRequest.setHgqyDm(tradingPlatform.getCustomsEnterpriseCode());
        updateEnterpriseRequest.setYxbz(DictConstants.SYS_YES);
        xiaotuRequestService.updateEnterprise(updateEnterpriseRequest);
    }

    /**
     * 获取或创建小图退税用户信息
     * 
     * @param sysUser
     * @return
     */
    private String getOrCreateXtUser(SysUser sysUser) {
        // 根据登录账号查询小图退税用户信息
        UserInfoDto xtUserInfo = xiaotuRequestService.searchUserByUserName(sysUser.getPhonenumber());
        if (xtUserInfo != null) {
            return xtUserInfo.getYhuuid1();
        } else {
            RegisterUserRequest userRequest = new RegisterUserRequest();
            userRequest.setXm(sysUser.getNickName());
            userRequest.setYddh(sysUser.getPhonenumber());
            userRequest.setJsDm(RegisterUserRequest.WMSCAntd);
            return xiaotuRequestService.registerUser(userRequest).getYhuuid1();
        }
    }

    private TradingPlatform save(TradingPlatformDto tradingPlatformDto) {
        TradingPlatform tradingPlatform = new TradingPlatform();
        BeanUtils.copyProperties(tradingPlatformDto, tradingPlatform, "createBy", "gmtCreate", "updateBy",
                "gmtModified");
        tradingPlatformBaseService.saveOrUpdate(tradingPlatform);
        TradingPlatformInsuranceDto insuranceDto = tradingPlatformDto.getInsurance();
        if (insuranceDto != null) {
            TradingPlatformInsurance tradePlatformInsurance = new TradingPlatformInsurance();
            BeanUtils.copyProperties(insuranceDto, tradePlatformInsurance, "id", "createBy", "gmtCreate", "updateBy",
                    "gmtModified");
            tradePlatformInsurance.setPlatformId(tradingPlatform.getId());
            tradePlatformInsurance.setPlatformCode(tradingPlatform.getPlatformCode());
            TradingPlatformInsurance rawOne = tradingPlatformInsuranceBaseSService
                    .findByPlatformId(tradingPlatform.getId());
            if (rawOne != null) {
                tradePlatformInsurance.setId(rawOne.getId());
            }
            tradingPlatformInsuranceBaseSService.saveOrUpdate(tradePlatformInsurance);
        }
        TradingPlatformQualificationDto qualificationDto = tradingPlatformDto.getQualification();
        if (qualificationDto != null) {
            TradingPlatformQualification tradingPlatformQualification = transStruct
                    .transDto2TradingPlatformQualification(qualificationDto);
            tradingPlatformQualification.setPlatformId(tradingPlatform.getId());
            tradingPlatformQualification.setPlatformCode(tradingPlatform.getPlatformCode());
            TradingPlatformQualification rawOne = tradingPlatformQualificationBaseService
                    .findByPlatformId(tradingPlatform.getId());
            if (rawOne != null) {
                tradingPlatformQualification.setId(rawOne.getId());
            }
            tradingPlatformQualificationBaseService.saveOrUpdate(tradingPlatformQualification);
        }
        return tradingPlatform;
    }

    private void checkParams(Boolean confirmed, TradingPlatformDto tradingPlatformDto) {
        if (confirmed) {
            ValidatorUtil.validator(ValidatorGroup.ValidatorType.SUBMIT, tradingPlatformDto);
            if (tradingPlatformDto.getInsurance() != null) {
                ValidatorUtil.validator(ValidatorGroup.ValidatorType.SUBMIT, tradingPlatformDto.getInsurance());
            }
            if (tradingPlatformDto.getQualification() == null) {
                throw new ValidatorException(HttpStatus.ERROR, "贸易平台的资质信息不能为空！");
            }
            ValidatorUtil.validator(ValidatorGroup.ValidatorType.SUBMIT, tradingPlatformDto.getQualification());
            if (DictConstants.SYS_YES.equals(tradingPlatformDto.getHasSinosureInsurance())
                    && tradingPlatformDto.getInsurance() == null) {
                throw new ValidatorException(HttpStatus.ERROR, "贸易平台的保险信息不能为空！");
            }
            if (DictConstants.DISTRICT_CN_MAINLAND.equals(tradingPlatformDto.getDistrictCode())) {
                if (StrUtil.isEmpty(tradingPlatformDto.getTaxAuthorityArea())) {
                    throw new ValidatorException(HttpStatus.ERROR, "主管税务机关不能为空！");
                }
                if (tradingPlatformDto.getXtAdminUserId() == null) {
                    throw new ValidatorException(HttpStatus.ERROR, "出口退税办理人不能为空！");
                }
            }
        } else {
            ValidatorUtil.validator(ValidatorGroup.ValidatorType.ADD, tradingPlatformDto);
            if (tradingPlatformDto.getInsurance() != null) {
                ValidatorUtil.validator(ValidatorGroup.ValidatorType.ADD, tradingPlatformDto.getInsurance());
            }
            if (tradingPlatformDto.getQualification() != null) {
                ValidatorUtil.validator(ValidatorGroup.ValidatorType.ADD, tradingPlatformDto.getQualification());
            }
        }
    }

    @Override
    public List<TradingPlatform> getPermissionTradePlatforms() {
        Long userId = SecurityUtils.getUserId();
        return tradingPlatformBaseService.lambdaQuery().eq(TradingPlatform::getDraft, false)
                .eq(TradingPlatform::getXtAdminUserId, userId).list();
    }
}
