package com.xhpc.payment.service.impl;

import cn.hutool.core.date.DateField;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.io.IoUtil;
import cn.hutool.poi.excel.BigExcelWriter;
import cn.hutool.poi.excel.ExcelUtil;
import com.xhpc.common.api.UserTypeService;
import com.xhpc.common.core.constant.HttpStatus;
import com.xhpc.common.core.constant.StatusConstants;
import com.xhpc.common.core.domain.R;
import com.xhpc.common.core.utils.StringUtils;
import com.xhpc.common.core.web.domain.AjaxResult;
import com.xhpc.common.domain.XhpcRefundOrder;
import com.xhpc.common.security.service.TokenService;
import com.xhpc.common.util.UserTypeUtil;
import com.xhpc.payment.domain.XhpcAppUser;
import com.xhpc.payment.domain.XhpcRefundAudit;
import com.xhpc.payment.mapper.XhpcRefundOrderMapper;
import com.xhpc.payment.mapper.XhpcUserAccountStatementMapper;
import com.xhpc.payment.service.IXhpcRefundOrderService;
import com.xhpc.payment.service.IXhpcRefundOriginalOrderService;
import com.xhpc.system.api.model.LoginUser;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * 退款订单信息 服务层
 *
 * @author ruoyi
 */
@Service
public class XhpcRefundOrderServiceImpl implements IXhpcRefundOrderService {

    @Autowired
    private XhpcRefundOrderMapper xhpcRefundOrderMapper;

    @Autowired
    private XhpcUserAccountStatementMapper xhpcUserAccountStatementMapper;
    @Autowired
    private UserTypeService userTypeService;

    @Autowired
    private TokenService tokenService;
    @Resource
    private IXhpcRefundOriginalOrderService xhpcRefundOriginalOrderService;
    private final ExecutorService executorService = Executors.newFixedThreadPool(40);

    /**
     * 更新 退款订单
     *
     * @param XhpcRefundOrder 退款订单
     */
    @Override
    @Transactional
    public int update(XhpcRefundOrder XhpcRefundOrder) {
        return xhpcRefundOrderMapper.update(XhpcRefundOrder);
    }

    /**
     * 退款订单详情
     *
     * @param rechargeOrderId 退款订单id
     * @return 结果
     */
    @Override
    public Map<String, Object> info(Long rechargeOrderId) {
        return xhpcRefundOrderMapper.info(rechargeOrderId);
    }

    /**
     * 退款订单分页列表
     *
     * @param phone
     * @param rechargeOrderNumber
     * @param status
     * @param createTimeStart
     * @param createTimeEnd
     * @return
     */
    @Override
    public List<Map<String, Object>> page(String phone, String rechargeOrderNumber, String status, String createTimeStart, String createTimeEnd,Integer type,Integer source,Integer userId) {
        LoginUser loginUser = tokenService.getLoginUser();
        return xhpcRefundOrderMapper.page(phone, rechargeOrderNumber, status, createTimeStart, createTimeEnd,type,source,userId,loginUser.getTenantId());
    }


    @Override
    public void export(HttpServletResponse response, String phone, String refundOrderNumber, String status, String createTimeStart, String createTimeEnd, Integer type,Integer source,Integer userId) throws IOException {
        LoginUser loginUser = tokenService.getLoginUser();
        List<Map<String, Object>> list = xhpcRefundOrderMapper.page(phone, refundOrderNumber, status, createTimeStart, createTimeEnd,type,source,userId,loginUser.getTenantId());

// 通过工具类创建writer，默认创建xls格式
        BigExcelWriter writer = ExcelUtil.getBigWriter("RefundOrder_" + System.currentTimeMillis() + ".xlsx");
        writer.addHeaderAlias("refundOrderId", "退款订单id");
        writer.addHeaderAlias("refundOrderNumber", "退款订单编号");
//        writer.addHeaderAlias("alipayId", "电站名称");
//        writer.addHeaderAlias("openId", "桩编号");
        writer.addHeaderAlias("userId", "C端用户id");
        writer.addHeaderAlias("amount", "退款金额");
        writer.addHeaderAlias("examineStatus", "审核状态（0审核中 1审核通过，2审核失败）");
        writer.addHeaderAlias("status", "状态（0退款中 1退款成功，2退款失败，3退款异常）");
        writer.addHeaderAlias("createTime", "退款时间");
        writer.addHeaderAlias("phone", "账号");
        writer.addHeaderAlias("statusName", "退款状态");
        writer.addHeaderAlias("examineStatusName", "审核状态名称");

        // 默认的，未添加alias的属性也会写出，如果想只写出加了别名的字段，可以调用此方法排除之
        writer.setOnlyAlias(true);
        // 一次性写出内容，使用默认样式，强制输出标题
        writer.write(list, true);
        //out为OutputStream，需要写出到的目标流
        response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
        response.setCharacterEncoding("utf-8");
//        //response为HttpServletResponse对象
//        response.setContentType("application/vnd.ms-excel;charset=utf-8");
//        //test.xls是弹出下载对话框的文件名，不能为中文，中文请自行编码
//        response.setHeader("Content-Disposition", "attachment;filename=退款订单列表.xls");
        ServletOutputStream out = response.getOutputStream();

        writer.flush(out, true);
        // 关闭writer，释放内存
        writer.close();
        //此处记得关闭输出Servlet流
        IoUtil.close(out);

    }

    @Override
    public Map<String, Object> sumMoney(String phone, String refundOrderNumber, String status, String createTimeStart, String createTimeEnd, Integer type) {
        LoginUser loginUser = tokenService.getLoginUser();
        //昨日用户的活跃度
        Date newDate1 = DateUtil.offset(new Date(), DateField.DAY_OF_MONTH, -1);
        String time1 = DateUtil.format(newDate1, "yyyy-MM-dd HH:mm:ss");
        //7天用户的活跃度
        Date newDate2 = DateUtil.offset(new Date(), DateField.DAY_OF_MONTH, -7);
        String time2 = DateUtil.format(newDate2, "yyyy-MM-dd HH:mm:ss");
        //一个月用户的活跃度
        Date newDate3 = DateUtil.offset(new Date(), DateField.DAY_OF_MONTH, -30);
        String time3 = DateUtil.format(newDate3, "yyyy-MM-dd HH:mm:ss");
        //3个月天用户的活跃度
        Date newDate4 = DateUtil.offset(new Date(), DateField.DAY_OF_MONTH, -90);
        String time4 = DateUtil.format(newDate4, "yyyy-MM-dd HH:mm:ss");

        return xhpcRefundOrderMapper.sumMoney(phone, refundOrderNumber, status, createTimeStart, createTimeEnd, type,loginUser.getTenantId(),time1,time2,time3,time4);
    }

    @Override
    public Map<String, Object> sumUserMoney(String phone, String refundOrderNumber, String status, String createTimeStart, String createTimeEnd, Integer type,Integer userId) {
        LoginUser loginUser = tokenService.getLoginUser();
        return xhpcRefundOrderMapper.sumUserMoney(phone, refundOrderNumber, status, createTimeStart, createTimeEnd, type,loginUser.getTenantId(),userId);
    }
    /**
     * 新增 退款订单
     *
     * @param appUserId C端用户id
     * @param amount    充值金额
     * @param type      退款渠道（1微信 2支付宝）
     * @return
     */
    @Override
    @Transactional
    public AjaxResult addRefundOrder(String appUserId, BigDecimal amount, String type, String refundOrderNumber, String openid, String remark,Integer userType,String tenantId) {
        long userId = Long.parseLong(appUserId);
        List<Map<String, Object>> list = xhpcRefundOrderMapper.getNotChargeOrder(userId,userType,tenantId);
        if (null != list && list.size() > 0) {
            return AjaxResult.error(HttpStatus.ERROR_STATUS, "还有未完成的订单");
        }
        Map<String, Object> objectMap = xhpcUserAccountStatementMapper.appUserInfo(Long.parseLong(appUserId));
        if (StringUtils.isNull(objectMap)) {
            return AjaxResult.error(HttpStatus.DATA_ERROR, "用户不存在");
        }
        String isRefundApplication = StringUtils.valueOf(objectMap.get("isRefundApplication"));
        if ("1".equals(isRefundApplication)) {
            return AjaxResult.error(HttpStatus.DATA_ERROR, "用户已存在退款订单");
        }

        R user = userTypeService.getUser(null,userId , userType, null, tenantId);
        if(user !=null && user.getData() !=null){
            if(!UserTypeUtil.USER_TYPE.equals(userType) && !UserTypeUtil.COMMUNIT_TYPE.equals(userType)){
                return AjaxResult.error(HttpStatus.ERROR_STATUS, "退款失败请重新申请");
            }else if(UserTypeUtil.USER_TYPE.equals(userType)){
                XhpcAppUser xhpcAppUser = new XhpcAppUser();
                xhpcAppUser.setAppUserId(Long.parseLong(appUserId));
                xhpcAppUser.setIsRefundApplication(UserTypeUtil.REFUND_APPLICATION_ONE);
                xhpcUserAccountStatementMapper.updateAppUserRefundApplication(xhpcAppUser);
            }else{
                xhpcRefundOrderMapper.updateRefundApplication(userId,UserTypeUtil.REFUND_APPLICATION_ONE);
            }
        }

        XhpcRefundOrder xhpcRefundOrder = new XhpcRefundOrder();
        xhpcRefundOrder.setUserId(userId);
        xhpcRefundOrder.setAmount(amount);
        xhpcRefundOrder.setRefundOrderNumber(refundOrderNumber);
        xhpcRefundOrder.setType(Integer.parseInt(type));
        xhpcRefundOrder.setRemark(remark);
        xhpcRefundOrder.setSource(userType);
        xhpcRefundOrder.setCreateTime(new Date());
        xhpcRefundOrder.setUpdateTime(new Date());
        if (StatusConstants.OPERATION_WX_TYPE.equals(type)) {
            xhpcRefundOrder.setOpenId(openid);
        } else {
            xhpcRefundOrder.setAlipayId(openid);
        }
        xhpcRefundOrderMapper.insert(xhpcRefundOrder);

        return AjaxResult.success();
    }


    @Override
    @Transactional
    public AjaxResult addCycRefundOrder(String appUserId, BigDecimal amount, String type, String refundOrderNumber,Integer userType,String tenantId) {
        long userId = Long.parseLong(appUserId);
        List<Map<String, Object>> list = xhpcRefundOrderMapper.getNotChargeOrder(userId,userType,tenantId);
        if (null != list && list.size() > 0) {
            return AjaxResult.error(HttpStatus.ERROR_STATUS, "还有未完成的订单");
        }
        Map<String, Object> objectMap = xhpcUserAccountStatementMapper.getAppInternetUser(Long.parseLong(appUserId));
        if (StringUtils.isNull(objectMap)) {
            return AjaxResult.error(HttpStatus.DATA_ERROR, "用户不存在");
        }
        XhpcRefundOrder xhpcRefundOrder = new XhpcRefundOrder();
        xhpcRefundOrder.setUserId(userId);
        xhpcRefundOrder.setAmount(amount);
        xhpcRefundOrder.setRefundOrderNumber(refundOrderNumber);
        xhpcRefundOrder.setType(Integer.parseInt(type));
        xhpcRefundOrder.setRemark("川逸充微信退款");
        xhpcRefundOrder.setSource(userType);
        xhpcRefundOrder.setCreateTime(new Date());
        xhpcRefundOrder.setUpdateTime(new Date());

        xhpcRefundOrderMapper.insert(xhpcRefundOrder);

        return AjaxResult.success();
    }



    /**
     * 通过用户id查询未完成退款订单
     *
     * @param userId 用户id
     * @return 结果
     */
    @Override
    public Map<String, Object> getNotRefundOrder(Long userId,Integer userType,String tenantId) {
        return xhpcRefundOrderMapper.getNotRefundOrder(userId,userType,tenantId);
    }

    /**
     * 修改退款订单信息
     *
     * @param xhpcRefundOrder 退款订单信息
     * @return 结果
     */
    @Override
    public int updateStatus(XhpcRefundOrder xhpcRefundOrder) {
        return xhpcRefundOrderMapper.updateStatus(xhpcRefundOrder);
    }

    @Override
    public int countXhpcRealTimeOrder(Long userId,Integer source,String tenantId) {
        return xhpcRefundOrderMapper.countXhpcRealTimeOrder(userId,source,tenantId);
    }

    @Override
    public int countXhpcChargeOrder(Long userId,Integer source,String tenantId) {
        return xhpcRefundOrderMapper.countXhpcChargeOrder(userId,source,tenantId);
    }

    @Override
    public List<Long> moneyPage(Integer type) {

        return xhpcRefundOrderMapper.moneyPage(type);
    }

    @Override
    public List<Map<String, Object>> cycMoneyPage() {
        //查询是否有未退款的川逸充用户
        return xhpcRefundOrderMapper.cycAppInternetUserPage();
    }
    @Override
    public List<Map<String, Object>> administratorReview() {
        return xhpcRefundOrderMapper.administratorReview();
    }

    @Override
    public void updateXhpcRefundOrder(Long refundOrderId) {
        xhpcRefundOrderMapper.updateXhpcRefundOrder(refundOrderId);
    }

    @Override
    public void updateXhpcRefundOrderBalance(Long refundOrderId,String balance) {
        xhpcRefundOrderMapper.updateXhpcRefundOrder(refundOrderId);
    }

}
