package com.zsElectric.boot.business.service.impl;

import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.zsElectric.boot.business.mapper.*;
import com.zsElectric.boot.business.model.entity.*;
import com.zsElectric.boot.business.model.form.applet.AppInvokeChargeForm;
import com.zsElectric.boot.business.model.form.applet.AppStopChargeForm;
import com.zsElectric.boot.business.model.query.applet.AppChargeOrderInfoQuery;
import com.zsElectric.boot.business.model.vo.applet.AppChargeVO;
import com.zsElectric.boot.business.model.vo.applet.AppUserInfoVO;
import com.zsElectric.boot.business.service.AppletHomeService;
import com.zsElectric.boot.business.service.UserAccountService;
import com.zsElectric.boot.charging.dto.StartChargingRequestDTO;
import com.zsElectric.boot.charging.dto.StartChargingResponseVO;
import com.zsElectric.boot.charging.service.ChargingBusinessService;
import com.zsElectric.boot.charging.vo.EquipmentAuthResponseVO;
import com.zsElectric.boot.charging.vo.StopChargingOperationResponseVO;
import com.zsElectric.boot.common.constant.ConnectivityConstants;
import com.zsElectric.boot.common.constant.SystemConstants;
import com.zsElectric.boot.core.exception.BusinessException;
import com.zsElectric.boot.security.util.SecurityUtils;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.zsElectric.boot.business.service.ChargeOrderInfoService;
import com.zsElectric.boot.business.model.form.ChargeOrderInfoForm;
import com.zsElectric.boot.business.model.query.ChargeOrderInfoQuery;
import com.zsElectric.boot.business.model.vo.ChargeOrderInfoVO;
import com.zsElectric.boot.business.converter.ChargeOrderInfoConverter;

import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.Objects;

import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.StrUtil;

/**
 * 充电订单信息服务实现类
 *
 * @author zsElectric
 * @since 2025-12-17 19:13
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class ChargeOrderInfoServiceImpl extends ServiceImpl<ChargeOrderInfoMapper, ChargeOrderInfo> implements ChargeOrderInfoService {

    private final ChargeOrderInfoConverter chargeOrderInfoConverter;

    private final ChargingBusinessService chargingBusinessService;

    private final UserInfoMapper userInfoMapper;

    private final FirmInfoMapper firmInfoMapper;

    private final CouponMapper couponMapper;

    private final CouponTemplateMapper couponTemplateMapper;

    private final UserAccountService userAccountService;

    private final AppletHomeService appletHomeService;

    //充电订单号前缀
    private final String ORDER_NO_PREFIX = "CD";
    //设备流水号前缀
    private final String EQUIPMENT_NO_PREFIX = "SB";

    /**
    * 获取充电订单信息分页列表
    *
    * @param queryParams 查询参数
    * @return {@link IPage<ChargeOrderInfoVO>} 充电订单信息分页列表
    */
    @Override
    public IPage<ChargeOrderInfoVO> getChargeOrderInfoPage(ChargeOrderInfoQuery queryParams) {
        Page<ChargeOrderInfoVO> pageVO = this.baseMapper.getChargeOrderInfoPage(
                new Page<>(queryParams.getPageNum(), queryParams.getPageSize()),
                queryParams
        );
        return pageVO;
    }
    
    /**
     * 获取充电订单信息表单数据
     *
     * @param id 充电订单信息ID
     * @return 充电订单信息表单数据
     */
    @Override
    public ChargeOrderInfoForm getChargeOrderInfoFormData(Long id) {
        ChargeOrderInfo entity = this.getById(id);
        return chargeOrderInfoConverter.toForm(entity);
    }
    
    /**
     * 新增充电订单信息
     *
     * @param formData 充电订单信息表单对象
     * @return 是否新增成功
     */
    @Override
    public boolean saveChargeOrderInfo(ChargeOrderInfoForm formData) {
        ChargeOrderInfo entity = chargeOrderInfoConverter.toEntity(formData);
        return this.save(entity);
    }
    
    /**
     * 更新充电订单信息
     *
     * @param id   充电订单信息ID
     * @param formData 充电订单信息表单对象
     * @return 是否修改成功
     */
    @Override
    public boolean updateChargeOrderInfo(Long id,ChargeOrderInfoForm formData) {
        ChargeOrderInfo entity = chargeOrderInfoConverter.toEntity(formData);
        return this.updateById(entity);
    }
    
    /**
     * 删除充电订单信息
     *
     * @param ids 充电订单信息ID，多个以英文逗号(,)分割
     * @return 是否删除成功
     */
    @Override
    public boolean deleteChargeOrderInfos(String ids) {
        Assert.isTrue(StrUtil.isNotBlank(ids), "删除的充电订单信息数据为空");
        // 逻辑删除
        List<Long> idList = Arrays.stream(ids.split(","))
                .map(Long::parseLong)
                .toList();
        return this.removeByIds(idList);
    }

    @Override
    public IPage<ChargeOrderInfoVO> getPage(AppChargeOrderInfoQuery queryParams) {
        queryParams.setUserId(SecurityUtils.getUserId());

        Page<ChargeOrderInfoVO> pageVO = this.baseMapper.getPage(
                new Page<>(queryParams.getPageNum(), queryParams.getPageSize()),
                queryParams
        );
        return pageVO;
    }

    @Override
    public AppChargeVO invokeCharge(AppInvokeChargeForm formData) {

        log.info("启动充电开始,用户ID:{},设备认证流水号:{},充电桩编号:{}", SecurityUtils.getUserId(), formData.getEquipAuthSeq(), formData.getEquipmentId());

        try {
            AppChargeVO appInvokeChargeVO = new AppChargeVO();

            //必要校验
            Long userId = SecurityUtils.getUserId();
            Assert.isTrue(userId != null, "用户ID不能为空");

            AppUserInfoVO userInfo = userInfoMapper.getAppletUserInfo(userId);
            Assert.isTrue(userInfo != null, "用户信息不存在");

            //判断有没有正在进行中的订单
            Long count = this.baseMapper.selectCount(Wrappers.lambdaQuery(ChargeOrderInfo.class).eq(ChargeOrderInfo::getUserId, userId).in(ChargeOrderInfo::getStatus, SystemConstants.STATUS_ZERO, SystemConstants.STATUS_ONE, SystemConstants.STATUS_TWO));
            Assert.isTrue(count == 0, "您有正在进行中的订单，请等待完成！");


            //请求设备认证
            EquipmentAuthResponseVO equipmentAuthResponseVO = chargingBusinessService.queryEquipAuth(formData.getEquipAuthSeq(),
                    formData.getConnectorId());

            if (!Objects.equals(equipmentAuthResponseVO.getSuccStat(), SystemConstants.STATUS_ONE)) {
                throw new BusinessException("设备认证失败");
            }


            //生成系统充电订单号及互联互通充电订单号
            assert userId != null;
            String chargeOrderNo = generateNo(ORDER_NO_PREFIX, userId);
            String startChargeSeq = ConnectivityConstants.OPERATOR_ID + chargeOrderNo;
            //生成设备流水号（格式"运营商ID+唯一编号"）
            String equipAuthSeq = ConnectivityConstants.OPERATOR_ID + generateNo(EQUIPMENT_NO_PREFIX, userId);

            //创建订单
            ChargeOrderInfo chargeOrderInfo = new ChargeOrderInfo();

            chargeOrderInfo.setUserId(userId);
            chargeOrderInfo.setEquipmentId(formData.getEquipmentId());
            chargeOrderInfo.setEquipAuthSeq(equipAuthSeq);
            chargeOrderInfo.setChargeOrderNo(chargeOrderNo);
            chargeOrderInfo.setStartChargeSeq(startChargeSeq);
            chargeOrderInfo.setPhoneNum(userInfo.getPhone());
            chargeOrderInfo.setThirdPartyStationId(formData.getStationId());
            chargeOrderInfo.setOrderType(formData.getOrderType());
            //预支付金额
            BigDecimal preAmt = appletHomeService.calculateAvailableChargingAmount(formData.getConnectorInfoId());
            chargeOrderInfo.setPreAmt(preAmt);

            //判断用户是否绑定企业
            if (ObjectUtil.isNotEmpty(userInfo.getFirmId())) {
                FirmInfo firmInfo = firmInfoMapper.selectById(userInfo.getFirmId());
                if(firmInfo != null && Objects.equals(firmInfo.getStatus(), SystemConstants.STATUS_ONE)) {
                    chargeOrderInfo.setFirmId(firmInfo.getId());
                    chargeOrderInfo.setOrderType(SystemConstants.STATUS_ONE);
                }
            }
            //优惠券
            if(ObjectUtil.isNotEmpty(formData.getCouponId())) {
                Coupon coupon = couponMapper.selectById(formData.getCouponId());
                if(coupon != null && Objects.equals(coupon.getStatus(), SystemConstants.STATUS_ONE)) {
                    CouponTemplate couponTemplate = couponTemplateMapper.selectById(coupon.getTemplateId());
                    chargeOrderInfo.setCouponId(coupon.getId());
                    chargeOrderInfo.setCouponPrice(couponTemplate.getDiscountPrice());
                }
            }

            //启动充电
            StartChargingRequestDTO requestDTO = new StartChargingRequestDTO();
            requestDTO
                    .setStartChargeSeq(startChargeSeq)
                    .setConnectorID(formData.getConnectorId())
                    .setPhoneNum(userInfo.getPhone())
                    //预支付金额
                    .setChargingAmt(preAmt.toString())
            ;
            StartChargingResponseVO startChargingResponseVO = chargingBusinessService.startCharging(requestDTO);
            if (!Objects.equals(startChargingResponseVO.getSuccStat(), SystemConstants.STATUS_ZERO)) {
                throw new BusinessException("启动充电失败");
            }

            //保存订单
            this.save(chargeOrderInfo);

            appInvokeChargeVO.setChargeOrderNo(chargeOrderNo);
            appInvokeChargeVO.setChargeOrderId(chargeOrderInfo.getId());
            return appInvokeChargeVO;
        } catch (Exception e) {
            throw new BusinessException("启动充电失败，系统错误，请联系客服处理！");
        }
    }

    @Override
    public AppChargeVO stopCharge(AppStopChargeForm formData) {
        try {
            AppChargeVO appInvokeChargeVO = new AppChargeVO();

            //订单
            ChargeOrderInfo chargeOrderInfo = this.getById(formData.getChargeOrderId());
            if(ObjectUtil.isEmpty(chargeOrderInfo)){
                throw new BusinessException("订单不存在");
            }
            StopChargingOperationResponseVO stopChargingOperationResponseVO = chargingBusinessService.stopCharging(chargeOrderInfo.getStartChargeSeq(), chargeOrderInfo.getConnectorId());

            if (!Objects.equals(stopChargingOperationResponseVO.getSuccStat(), SystemConstants.STATUS_ZERO)) {
                throw new BusinessException("停止充电失败");
            }

            //保存订单
            this.save(chargeOrderInfo);

            appInvokeChargeVO.setChargeOrderId(chargeOrderInfo.getId());
            appInvokeChargeVO.setChargeOrderNo(chargeOrderInfo.getChargeOrderNo());
            return appInvokeChargeVO;
        } catch (Exception e) {
            throw new BusinessException("停止充电失败，系统错误，请联系客服处理！");
        }
    }

    @Override
    public void orderSettlement(Long chargeOrderId) {
        Long userId = SecurityUtils.getUserId();
        ChargeOrderInfo chargeOrderInfo = this.getById(chargeOrderId);

        //平台收费总金额
        BigDecimal totalCharge = chargeOrderInfo.getRealCost();

        //账户变动及日志记录
        userAccountService.updateAccountBalanceAndLog(
                userId,
                totalCharge,
                SystemConstants.CHANGE_TYPE_REDUCE,
                "充电扣款",
                chargeOrderInfo.getId()
        );
    }

    /**
     * 创建商户订单号
     * 要求 32个字符内，只能是数字、大小写字母_-|*且在同一个商户号下唯一
     * 组成 两位前缀 + 17位时间戳 + 9位id补零 + 4位随机数 合计32位
     *
     * @param head 例如 商品-SP 退款-TK 等等
     * @param id   用户id
     * @return
     */
    public String generateNo(String head, Long id) {
        StringBuilder uid = new StringBuilder(id.toString());
        Date date = new Date();
        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmssSSS");
        int length = uid.length();
        for (int i = 0; i < 9 - length; i++) {
            uid.insert(0, "0");
        }
        return head + sdf.format(date) + uid + (int) ((Math.random() * 9 + 1) * 1000);
    }

}
