package com.buy507.mall.service.impl;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;

import cn.hutool.core.date.DateUtil;
import com.buy507.mall.mapper.UmsMemberAccountTransactionMapper;
import com.buy507.mall.model.*;
import org.apache.poi.hssf.usermodel.HSSFCell;
import org.apache.poi.hssf.usermodel.HSSFCellStyle;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.BorderStyle;
import org.apache.poi.ss.usermodel.HorizontalAlignment;
import org.apache.poi.ss.usermodel.VerticalAlignment;
import org.apache.poi.ss.usermodel.Workbook;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import com.buy507.mall.component.RedisLock;
import com.buy507.mall.dao.DmsMemberWithdrawApplyDao;
import com.buy507.mall.dto.MemberWithdrawApplyResult;
import com.buy507.mall.mapper.DmsMemberTradeRecordMapper;
import com.buy507.mall.mapper.DmsMemberWithdrawApplyMapper;
import com.buy507.mall.mapper.UmsMemberMapper;
import com.buy507.mall.service.DmsMemberWithdrawApplyService;
import com.github.pagehelper.PageHelper;

@Service
public class DmsMemberWithdrawApplyServiceImpl implements DmsMemberWithdrawApplyService {
	
	@Autowired
	private DmsMemberWithdrawApplyDao dao;
	
	@Autowired
	private DmsMemberWithdrawApplyMapper memberWithdrawApplyMapper;

	@Autowired
	private UmsMemberMapper memberMapper;
	
	@Autowired
	private DmsMemberTradeRecordMapper memberTradeRecordMapper;
	
	@Autowired
    private RedisLock redisLock;

	@Autowired
	private UmsMemberAccountTransactionMapper accountTransactionMapper;
	
	
	@Override
	public List<MemberWithdrawApplyResult> list(String startTime, String endTime, Integer paymentStatus, Integer pageSize, Integer pageNum) {
		PageHelper.startPage(pageNum, pageSize);
		return queryList(startTime, endTime, paymentStatus);
	}

	@Override
	public void payment(List<Long> ids) {
		DmsMemberWithdrawApply withdrawApply = null;
		UmsMember member = null;
		DmsMemberTradeRecord tradeRecord = null; 
		Date date = new Date();
		for(Long id : ids) {
			withdrawApply = memberWithdrawApplyMapper.selectOneById(id);
			if(withdrawApply != null && withdrawApply.getPaymentStatus() == 0) {
				
				member = memberMapper.selectByPrimaryKey(withdrawApply.getMemberId());
				withdrawApply.setPaymentStatus(1); //付款状态：0->未打款；1->已打款；2->打款失败
				withdrawApply.setPaymentTime(date);
				memberWithdrawApplyMapper.updateById(withdrawApply);
				
				//写入会员交易记录表
				tradeRecord = new DmsMemberTradeRecord();
				tradeRecord.setMemberId(member.getId());
				tradeRecord.setItemType(ItemType.Withdraw); //提现
				tradeRecord.setNote("提现成功");
				tradeRecord.setTitle("提现成功");
				tradeRecord.setValue(withdrawApply.getValue());
				tradeRecord.setType(1); //收支类型：0->收入；1->支出
				tradeRecord.setCreateTime(date);
				memberTradeRecordMapper.insert(tradeRecord);
				
				while(true) {
					long time = System.currentTimeMillis() + RedisLock.TIMEOUT;
					if(redisLock.lock(String.valueOf(member.getId()), String.valueOf(time))) {
						member = memberMapper.selectByPrimaryKey(member.getId());
						member.setFreeze(member.getFreeze().subtract(withdrawApply.getValue())); //修改冻结值
						memberMapper.updateByPrimaryKey(member);

						// 写入会员流水记录表
						UmsMemberAccountTransaction memberTransaction = new UmsMemberAccountTransaction();
						memberTransaction.setMemberId(member.getId());
						memberTransaction.setRevenueAmount(withdrawApply.getValue());  // 提现金额
						memberTransaction.setRemarks("提现");  // 备注
						memberTransaction.setCreateTime(DateUtil.date());  // 提现时间
						accountTransactionMapper.insert(memberTransaction);  // 保存流水记录

						redisLock.unlock(String.valueOf(member.getId()), String.valueOf(time));
						break;
					}
				}
				
			}
		}

	}

	@Override
	public void paymentFailed(Long id, String failedReason) {
		DmsMemberWithdrawApply withdrawApply = memberWithdrawApplyMapper.selectOneById(id);
		if(withdrawApply != null && withdrawApply.getPaymentStatus() == 0) {
			UmsMember member = memberMapper.selectByPrimaryKey(withdrawApply.getMemberId());
			withdrawApply.setPaymentStatus(2); //付款状态：0->未打款；1->已打款；2->打款失败
			withdrawApply.setPaymentTime(null);
			withdrawApply.setFailedReason(failedReason);			
			memberWithdrawApplyMapper.updateById(withdrawApply);
			
			//将冻结的余额还原
			while(true) {
				long time = System.currentTimeMillis() + RedisLock.TIMEOUT;
				if(redisLock.lock(String.valueOf(member.getId()), String.valueOf(time))) {
					member = memberMapper.selectByPrimaryKey(member.getId());
					member.setBalance(member.getBalance().add(withdrawApply.getValue())); //修改余额
					member.setFreeze(member.getFreeze().subtract(withdrawApply.getValue()));
					memberMapper.updateByPrimaryKey(member);
					redisLock.unlock(String.valueOf(member.getId()), String.valueOf(time));
					break;
				}
			}
		}
	}

	@Override
	public Workbook exportExcel(String startTime, String endTime, Integer paymentStatus) {
		List<MemberWithdrawApplyResult> queryList = queryList(startTime, endTime, paymentStatus);
		
		// 第一步，创建一个webbook，对应一个Excel文件
		HSSFWorkbook wb = new HSSFWorkbook();
		// 第二步，在webbook中添加一个sheet,对应Excel文件中的sheet
		HSSFSheet sheet = wb.createSheet("提现列表");
		// 第三步，在sheet中添加表头第0行,注意老版本poi对Excel的行数列数有限制short
		HSSFRow row = sheet.createRow((int) 0);
		// 第四步，创建单元格，并设置值表头 设置表头居中
		HSSFCellStyle headerStyle = wb.createCellStyle();
		headerStyle.setBorderBottom(BorderStyle.THIN);
		headerStyle.setBorderLeft(BorderStyle.THIN);//左边框
		headerStyle.setBorderTop(BorderStyle.THIN);//上边框
		headerStyle.setBorderRight(BorderStyle.THIN);//右边框
		headerStyle.setAlignment(HorizontalAlignment.CENTER);//水平居中
		headerStyle.setVerticalAlignment(VerticalAlignment.CENTER);//垂直居中
		
		HSSFCell cell = row.createCell(0);
		cell.setCellValue("姓名");
		cell.setCellStyle(headerStyle);
		cell = row.createCell(1);
		cell.setCellValue("电话");
		cell.setCellStyle(headerStyle);
		cell = row.createCell(2);
		cell.setCellValue("提现金额");
		cell.setCellStyle(headerStyle);
		cell = row.createCell(3);
		cell.setCellValue("手续费");
		cell.setCellStyle(headerStyle);
		cell = row.createCell(4);
		cell.setCellValue("打款金额");
		cell.setCellStyle(headerStyle);
		cell = row.createCell(5);
		cell.setCellValue("提现方式");
		cell.setCellStyle(headerStyle);
		cell = row.createCell(6);
		cell.setCellValue("微信账号");
		cell.setCellStyle(headerStyle);
		cell = row.createCell(7);
		cell.setCellValue("微信昵称");
		cell.setCellStyle(headerStyle);
		cell = row.createCell(8);
		cell.setCellValue("账户名");
		cell.setCellStyle(headerStyle);
		cell = row.createCell(9);
		cell.setCellValue("银行名称");
		cell.setCellStyle(headerStyle);
		cell = row.createCell(10);
		cell.setCellValue("银行卡号");
		cell.setCellStyle(headerStyle);
		cell = row.createCell(11);
		cell.setCellValue("开户行地址");
		cell.setCellStyle(headerStyle);
		cell = row.createCell(12);
		cell.setCellValue("打款状态");
		cell.setCellStyle(headerStyle);
		cell = row.createCell(13);
		cell.setCellValue("失败原因");
		cell.setCellStyle(headerStyle);
		cell = row.createCell(14);
		cell.setCellValue("打款时间");
		cell.setCellStyle(headerStyle);
		cell = row.createCell(15);
		cell.setCellValue("申请时间");
		cell.setCellStyle(headerStyle);
		
		MemberWithdrawApplyResult apply = null;
		String withdrawTypeName = "";
		String paymentStatusName = "";
		SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm");
		
		HSSFCellStyle style = wb.createCellStyle();
		style.setBorderBottom(BorderStyle.THIN);
		style.setBorderLeft(BorderStyle.THIN);//左边框
		style.setBorderTop(BorderStyle.THIN);//上边框
		style.setBorderRight(BorderStyle.THIN);//右边框
		
		for (int i = 0; i < queryList.size(); i++) {
			row = sheet.createRow((int) i + 1);
			apply = queryList.get(i);
			// 第五步，创建单元格，并设置值
			cell = row.createCell(0);
			cell.setCellStyle(style);
			cell.setCellValue(apply.getName()); //会员姓名
			
			cell = row.createCell(1);
			cell.setCellStyle(style);
			cell.setCellValue(apply.getPhone()); //电话
			
			cell = row.createCell(2);
			cell.setCellStyle(style);
			cell.setCellValue(String.valueOf(apply.getValue())); //提现金额
			
			cell = row.createCell(3);
			cell.setCellStyle(style);
			cell.setCellValue(String.valueOf(apply.getPoundage())); //手续费
			
			cell = row.createCell(4);
			cell.setCellStyle(style);
			cell.setCellValue(String.valueOf(apply.getActualValue())); //打款金额
			
			if(apply.getWithdrawType() == 1) {
				withdrawTypeName = "微信";
			} else if(apply.getWithdrawType() == 2) {
				withdrawTypeName = "银行卡";
			} else {
				withdrawTypeName = "支付宝";
			}
			
			cell = row.createCell(5);
			cell.setCellStyle(style);
			cell.setCellValue(withdrawTypeName); //提现方式
			
			cell = row.createCell(6);
			cell.setCellStyle(style);
			cell.setCellValue(apply.getWechatAccount()); //微信账号
			
			cell = row.createCell(7);
			cell.setCellStyle(style);
			cell.setCellValue(apply.getWechatNickname()); //微信昵称
			
			cell = row.createCell(8);
			cell.setCellStyle(style);
			cell.setCellValue(apply.getAccountName()); //账户名
			
			cell = row.createCell(9);
			cell.setCellStyle(style);
			cell.setCellValue(apply.getBankName()); //银行名称
			
			cell = row.createCell(10);
			cell.setCellStyle(style);
			cell.setCellValue(apply.getBankCardNum()); //银行卡号
			
			cell = row.createCell(11);
			cell.setCellStyle(style);
			cell.setCellValue(apply.getOpenBankAddress()); //开户行地址
			
			if(apply.getPaymentStatus() == 1) {
				paymentStatusName = "已打款";
			} else if(apply.getPaymentStatus() == 2) {
				paymentStatusName = "打款失败";
			} else {
				paymentStatusName = "未打款";
			}
			
			cell = row.createCell(12);
			cell.setCellStyle(style);
			cell.setCellValue(paymentStatusName); //打款状态
			
			cell = row.createCell(13);
			cell.setCellStyle(style);
			cell.setCellValue(apply.getFailedReason()); //失败原因
			
			cell = row.createCell(14);
			cell.setCellStyle(style);
			if(apply.getPaymentTime() == null) {
				cell.setCellValue("");
			} else {
				cell.setCellValue(sdf.format(apply.getPaymentTime())); //打款时间
			}
			
			cell = row.createCell(15);
			cell.setCellStyle(style);
			cell.setCellValue(sdf.format(apply.getCreateTime())); //申请时间
		}
		
		return wb;
	}
	
	
	private List<MemberWithdrawApplyResult> queryList(String startTime, String endTime, Integer paymentStatus) {
		Date start = null;
		Date end = null;
		SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
		if (!StringUtils.isEmpty(startTime)) {
            String startStr = startTime + " 00:00:00";
            try {
                start = sdf.parse(startStr);
            } catch (ParseException e) {
                e.printStackTrace();
            }
        }
		
		if(!StringUtils.isEmpty(endTime)) {
			String endStr = endTime + " 23:59:59";
			try {
                end = sdf.parse(endStr);
            } catch (ParseException e) {
                e.printStackTrace();
            }
		}
		
		return dao.selectByExample(start, end, paymentStatus);
	}

}
