package com.qs.mp.web.controller.api.admin;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.qs.mp.admin.domain.*;
import com.qs.mp.admin.domain.excel.TicketExcel;
import com.qs.mp.admin.domain.param.*;
import com.qs.mp.admin.domain.vo.TicketAwardsVO;
import com.qs.mp.admin.domain.vo.TicketBoxVO;
import com.qs.mp.admin.service.*;
import com.qs.mp.channel.domain.Channel;
import com.qs.mp.channel.domain.param.ChannelParam;
import com.qs.mp.channel.domain.vo.ChannelVO;
import com.qs.mp.channel.service.IChannelService;
import com.qs.mp.channel.service.IChannelUserRelService;
import com.qs.mp.common.annotation.Log;
import com.qs.mp.common.constant.UserConstants;
import com.qs.mp.common.core.domain.AjaxResult;
import com.qs.mp.common.core.page.TableDataInfo;
import com.qs.mp.common.enums.*;
import com.qs.mp.common.exception.ServiceException;
import com.qs.mp.common.pulsar.PulsarClientService;
import com.qs.mp.common.utils.AESUtil;
import com.qs.mp.common.utils.LogUtil;
import com.qs.mp.common.utils.RSAUtil;
import com.qs.mp.system.domain.SysUser;
import com.qs.mp.system.service.ISysUserService;
import com.qs.mp.utils.ExcelUtil;
import com.qs.mp.web.controller.common.BaseApiController;
import io.swagger.annotations.*;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import ma.glasnost.orika.MapperFacade;
import org.apache.commons.lang3.StringUtils;
import org.apache.pulsar.client.api.PulsarClientException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.stereotype.Component;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

/**
 * @auther zhongcp
 * @create 2022-02-28 16:17:48
 * @describe 盲票管理前端控制器
 */
@Api(tags = "盲票管理API")
@RestController
@RequestMapping("/api/v1/mp/admin/ticket/box/*")
@Component
public class TicketBoxMgrController extends BaseApiController {

	@Autowired
	private ITicketBoxService ticketBoxService;

	@Autowired
	private ITicketService ticketService;

	@Autowired
	private ITicketAwardsPrizeService ticketAwardsPrizeService;

	@Autowired
	private ITicketAwardsService ticketAwardsService;

	@Autowired
	private PulsarClientService pulsarClientService;

	@Autowired
	private MapperFacade mapperFacade;

	@Autowired
	private ITicketBoxChannelService ticketBoxChannelService;

	@Autowired
	private IChannelService channelService;

	@Value("${mp.exportUrl}")
	private String exportUrl;

	@Value("${export.page-size}")
	private int pageSize;

	@Value("${server.env}")
	private String env;

	/**
	 * 查询所有盲票组列表
	 *
	 * @return
	 */
	@PostMapping("/list")
	@PreAuthorize("@ss.hasPermi('business:ticket:list')")
	@ApiOperation("查询所有盲票组列表")
	@ApiResponses(
			@ApiResponse(code = 200, message = "查询成功", response = TicketBox.class)
	)
	public TableDataInfo list(@RequestBody TicketBoxQueryParam ticketBoxQueryParam) {
		startPage();
		QueryWrapper<TicketBox> queryWrapper = new QueryWrapper<TicketBox>();
		queryWrapper.like(null != ticketBoxQueryParam && StringUtils.isNotBlank(ticketBoxQueryParam.getTitle()), "title", ticketBoxQueryParam.getTitle());
		queryWrapper.eq(null != ticketBoxQueryParam && null != ticketBoxQueryParam.getType(), "type", ticketBoxQueryParam.getType());
		queryWrapper.eq(null != ticketBoxQueryParam && null != ticketBoxQueryParam.getStatus(), "status", ticketBoxQueryParam.getStatus());
		// 排除指定票组
		if (CollectionUtils.isNotEmpty(ticketBoxQueryParam.getExcludeBoxIds())) {
			queryWrapper.notIn("box_id", ticketBoxQueryParam.getExcludeBoxIds());
		}
		queryWrapper.orderByAsc("FIELD(`status`, 'wait', 'doing', 'done', 'on', 'off')").orderByDesc("box_id");
		List<TicketBox> list = ticketBoxService.list(queryWrapper);
		return getDataTable(list);
	}

	@PostMapping("/update")
	@PreAuthorize("@ss.hasPermi('business:ticket:edit')")
	@ApiOperation("更新盲票信息")
	public AjaxResult update(@RequestBody TicketBoxUpdateParam param) {
		return AjaxResult.success(ticketBoxService.updateTicketBox(param));
	}



	@PostMapping("/update/sortWeight")
	@PreAuthorize("@ss.hasPermi('business:ticket:edit')")
	@ApiOperation("更新盲票排序权重")
	public AjaxResult updateSortWeight(@RequestBody TicketUpdateSortWeightParam param) {

		TicketBox ticketBox = new TicketBox();
		ticketBox.setBoxId(param.getBoxId());
		ticketBox.setSortWeight(param.getSortWeight());
		return AjaxResult.success(ticketBoxService.updateById(ticketBox));
	}



	/**
	 * 查看盲票详情
	 */
	@PostMapping("/detail")
	@PreAuthorize("@ss.hasPermi('business:ticket:query')")
	@ApiOperation(value = "查看盲票详情" , notes = "根据盲票组ID，获取盲票信息")
	@ApiResponses(
			@ApiResponse(code = 200, message = "查询成功", response = TicketBoxVO.class)
	)
	public AjaxResult getInfo(@RequestBody TicketBoxParam param) {
		if (com.qs.mp.common.utils.StringUtils.isBlank(param.getBoxId())) {
			return AjaxResult.error("参数异常，盲票组ID缺失");
		}
		TicketBox ticketBox = ticketBoxService.getById(param.getBoxId());
		TicketBoxVO ticketBoxVO = mapperFacade.map(ticketBox, TicketBoxVO.class);
		// 设置经销商信息
		if (TicketBoxSaleChannelTypeEnum.PART.getValue().equals(ticketBox.getSaleChannelType())) {
			List<TicketBoxChannel> ticketBoxChannelList = ticketBoxChannelService.list(new LambdaQueryWrapper<TicketBoxChannel>().eq(TicketBoxChannel::getBoxId, ticketBox.getBoxId()));
			if (CollectionUtils.isNotEmpty(ticketBoxChannelList)) {
				List<Long> channelIds = ticketBoxChannelList.stream().map(TicketBoxChannel::getChannelId).collect(Collectors.toList());
				List<Channel> channelList = channelService.list(new LambdaQueryWrapper<Channel>().select(Channel::getChannelId, Channel::getName)
						.in(Channel::getChannelId, channelIds));
				ticketBoxVO.setChannelList(channelList);
			}
		}
		List<TicketAwards> ticketAwardsList = ticketAwardsService.list(new LambdaQueryWrapper<TicketAwards>()
				.eq(TicketAwards::getBoxId, ticketBox.getBoxId()).orderByAsc(TicketAwards::getSort));
		List<TicketAwardsVO> ticketAwardsVOS = mapperFacade.mapAsList(ticketAwardsList, TicketAwardsVO.class);
		for (TicketAwardsVO ticketAwardsVO : ticketAwardsVOS) {
			QueryWrapper<TicketAwardsPrize> queryWrapper = new QueryWrapper<>();
			queryWrapper.eq("t1.awards_id", ticketAwardsVO.getAwardsId());
			ticketAwardsVO.setPrizeList(ticketAwardsPrizeService.listByQueryWrapper(queryWrapper));
		}
		ticketBoxVO.setAwardsList(ticketAwardsVOS);
		return AjaxResult.success(ticketBoxVO);
	}

	/**
	 * 新增盲票
	 *
	 * @param
	 * @return
	 */
	@Log(title = "盲票新增", businessType = BusinessType.INSERT)
	@ApiOperation(value = "新增盲票", notes = "管理端创建盲票")
	@PostMapping("/create")
	@PreAuthorize("@ss.hasPermi('business:ticket:add')")
	public AjaxResult create(@Validated @RequestBody TicketBoxCreateParam param) {
		if (param.getType() == TicketTypeEnum.OFFLINE) {
			if (param.getPkgSalePrice() == null || param.getPkgSalePrice() == 0) {
				return AjaxResult.error("采购单价必须大于0");
			}
			if (param.getPkgUnit() == null || param.getPkgUnit() == 0) {
				return AjaxResult.error("每包张数必须大于0");
			}
		}
		if (param.getAwardsList().size() <= 1) {
			return AjaxResult.error("至少需要两个奖级");
		}
		String boxId = ticketBoxService.createTicketBox(param);
		if (StringUtils.isNotBlank(boxId)) {
			return AjaxResult.success();
		}
		return AjaxResult.error("创建失败");
	}

	/**
	 * 盲票上下架
	 *
	 * @param
	 * @return
	 */
	@Log(title = "盲票上下架", businessType = BusinessType.UPDATE)
	@ApiOperation(value = "盲票上下架", notes = "管理端盲票上下架")
	@PostMapping("/put")
	@PreAuthorize("@ss.hasPermi('business:ticket:on')")
	public AjaxResult putOnOff(@RequestBody TicketBox param) {
		if (StringUtils.isBlank(param.getBoxId()) || param.getStatus() == null) {
				return AjaxResult.error("参数缺失");
		}
		TicketBox ticketBox = ticketBoxService.getById(param.getBoxId());
		if (param.getStatus() == TicketBoxStatusEnum.PUT_OFF) {
			if (ticketBox.getStatus() != TicketBoxStatusEnum.PUT_ON) {
				return AjaxResult.error("当前状态不是已上架，不能下架");
			}
			ticketBoxService.update(new LambdaUpdateWrapper<TicketBox>()
					.set(TicketBox::getStatus, TicketBoxStatusEnum.PUT_OFF)
					.set(TicketBox::getManualOff, 1)
					.eq(TicketBox::getBoxId, ticketBox.getBoxId()));
		} else if (param.getStatus() == TicketBoxStatusEnum.PUT_ON) {
			if (ticketBox.getStatus() != TicketBoxStatusEnum.PUT_OFF && ticketBox.getStatus() != TicketBoxStatusEnum.DONE) {
				return AjaxResult.error("当前状态不是待上架或已下架，不能上架");
			}
			ticketBoxService.update(new LambdaUpdateWrapper<TicketBox>().set(TicketBox::getStatus, TicketBoxStatusEnum.PUT_ON)
					.eq(TicketBox::getBoxId, ticketBox.getBoxId()));
		}

		return AjaxResult.success("操作成功");
	}

	/**
	 * 盲票删除
	 *
	 * @param
	 * @return
	 */
	@Log(title = "盲票删除", businessType = BusinessType.DELETE)
	@ApiOperation(value = "盲票删除", notes = "管理端盲票删除")
	@PostMapping("/remove")
	@PreAuthorize("@ss.hasPermi('business:ticket:remove')")
	public AjaxResult remove(@RequestBody TicketBox param) {
		if (StringUtils.isBlank(param.getBoxId())) {
			return AjaxResult.error("参数缺失");
		}
		TicketBox ticketBox = ticketBoxService.getById(param.getBoxId());
		if (ticketBox.getStatus() != TicketBoxStatusEnum.DONE) {
			return AjaxResult.error("当前状态不是待上架，不能删除");
		}
		ticketBoxService.removeTicketBox(param.getBoxId());
		return AjaxResult.success("删除成功");
	}

	/*@Log(title = "盲票导出", businessType = BusinessType.EXPORT)
	@PostMapping("/export")
	@PreAuthorize("@ss.hasPermi('business:ticket:export')")
	public AjaxResult exportTicket(@RequestBody BathIdParam ids) {
		if (null == ids || null == ids.getIds() || ids.getIds().size() == 0) {
			return AjaxResult.error("请选择需要导出的盲票组");
		}
		TicketBox ticketBox = ticketBoxService.getById(ids.getIds().get(0));
		if (null == ticketBox || StringUtils.isBlank(ticketBox.getBoxId())) {
			return AjaxResult.error("选择的盲票组数据异常， 请联系管理员或重试");
		}
		List<TicketExcel> excelList = new ArrayList<TicketExcel>();
		List<Ticket> listAll = new ArrayList<Ticket>();
		// 首先查询要导出的数据总数
		LambdaQueryWrapper<Ticket> queryWrapper = new LambdaQueryWrapper<Ticket>();
		queryWrapper.eq(Ticket::getBoxId, ids.getIds().get(0));
		int totalSize = ticketService.count(queryWrapper);
		if (totalSize == 0) {
			return AjaxResult.error("选择的盲票组中没有可导出的数据");
		}

		if(totalSize > pageSize) {
			int totalPage = totalSize%pageSize == 0 ? totalSize/pageSize : totalSize/pageSize+1;
			for (int i = 0; i < totalPage; i++) {
				LambdaQueryWrapper<Ticket> pageQueryWrapper = new LambdaQueryWrapper<Ticket>();
				pageQueryWrapper.select(Ticket::getSerialNo, Ticket::getDrawNum, Ticket::getCipherLuckyNum);
				pageQueryWrapper.eq(Ticket::getBoxId, ids.getIds().get(0));
				pageQueryWrapper.last("limit "+ (i*pageSize) +", " + pageSize);
				List<Ticket> list = ticketService.list(pageQueryWrapper);
				if(null != list && list.size() > 0 ) {
					listAll.addAll(list);
				}
			}
		}else {
			listAll = ticketService.list(queryWrapper);
		}

		if(null != listAll && listAll.size() > 0 ) {
			listAll.sort(Comparator.comparing(Ticket::getSerialNo));
			for (Ticket ticket : listAll) {
				if (null != ticket && StringUtils.isNotBlank(ticket.getSerialNo())
						&& StringUtils.isNotBlank(ticket.getDrawNum())
						&& StringUtils.isNotBlank(ticket.getCipherLuckyNum())) {
					TicketExcel ticketExcel = new TicketExcel();
					ticketExcel.setSerialNo(ticket.getSerialNo());
					ticketExcel.setUrl(exportUrl + ticket.getSerialNo());
					ticketExcel.setDrawNum(ticket.getDrawNum());
					if (!ServerEnvEnum.PROD.getCode().equals(env)) {
						ticketExcel.setCipherLuckyNum(RSAUtil.decrypt(ticket.getCipherLuckyNum()));
					}
					excelList.add(ticketExcel);
				}
			}
		}

		ExcelUtil<TicketExcel> util = new ExcelUtil<TicketExcel>(TicketExcel.class);
		return util.exportExcel(excelList, ticketBox.getTitle(), false);
	}


    @GetMapping("/importTemplate")
    public AjaxResult importTemplate()
    {
        ExcelUtil<TicketExcel> util = new ExcelUtil<TicketExcel>(TicketExcel.class);
        return util.importTemplateExcel("盲票导出数据",false);
    }

	@Log(title = "盲票导入", businessType = BusinessType.IMPORT)
	@PostMapping("/importTicket")
	public AjaxResult importTicket(MultipartFile file) {
		// 获取文件内的盲票数据列表
		try {
			ExcelUtil<TicketExcel> util = new ExcelUtil<TicketExcel>(TicketExcel.class);
			List<TicketExcel> ticketExcelList = util.importExcel(file.getInputStream());
			if(null == ticketExcelList || ticketExcelList.size() == 0) {
				return AjaxResult.error("导入失败，选择的导入文件中没有有效的数据");
			}
			int successNum = ticketService.importTicket(ticketExcelList);
			if(successNum == 0) {
				return AjaxResult.error("导入失败，请联系管理员");
			}
			return AjaxResult.success("导入成功， 导入数据条数："+successNum);
			// 数据处理
		} catch (Exception e) {
			return AjaxResult.error("导入失败，请联系管理员");
		}
	}*/


	@Log(title = "导出印刷", businessType = BusinessType.EXPORT)
	@PostMapping("/exportDraw")
	@PreAuthorize("@ss.hasPermi('business:ticket:export')")
	public AjaxResult exportDraw(@RequestBody BathIdParam ids) {
		if (null == ids || null == ids.getIds() || ids.getIds().size() == 0) {
			return AjaxResult.error("请选择需要导出的盲票组");
		}
		TicketBox ticketBox = ticketBoxService.getById(ids.getIds().get(0));
		if (null == ticketBox || StringUtils.isBlank(ticketBox.getBoxId())) {
			return AjaxResult.error("选择的盲票组数据异常， 请联系管理员或重试");
		}
		List<TicketExcel> excelList = new ArrayList<TicketExcel>();
		List<Ticket> listAll = new ArrayList<Ticket>();
		// 首先查询要导出的数据总数
		LambdaQueryWrapper<Ticket> queryWrapper = new LambdaQueryWrapper<Ticket>();
		queryWrapper.eq(Ticket::getBoxId, ids.getIds().get(0));
		int totalSize = ticketService.count(queryWrapper);
		if (totalSize == 0) {
			return AjaxResult.error("选择的盲票组中没有可导出的数据");
		}

		if(totalSize > pageSize) {
			int totalPage = totalSize%pageSize == 0 ? totalSize/pageSize : totalSize/pageSize+1;
			for (int i = 0; i < totalPage; i++) {
				LambdaQueryWrapper<Ticket> pageQueryWrapper = new LambdaQueryWrapper<Ticket>();
				pageQueryWrapper.select(Ticket::getSerialNo, Ticket::getDrawNum, Ticket::getCipherLuckyNum);
				pageQueryWrapper.eq(Ticket::getBoxId, ids.getIds().get(0));
				pageQueryWrapper.last("limit "+ (i*pageSize) +", " + pageSize);
				List<Ticket> list = ticketService.list(pageQueryWrapper);
				if(null != list && list.size() > 0 ) {
					listAll.addAll(list);
				}
			}
		}else {
			listAll = ticketService.list(queryWrapper);
		}

		if(null != listAll && listAll.size() > 0 ) {
			listAll.sort(Comparator.comparing(Ticket::getSerialNo));
			for (Ticket ticket : listAll) {
				if (null != ticket && StringUtils.isNotBlank(ticket.getSerialNo())
						&& StringUtils.isNotBlank(ticket.getDrawNum())
						&& StringUtils.isNotBlank(ticket.getCipherLuckyNum())) {
					TicketExcel ticketExcel = new TicketExcel();
					ticketExcel.setSerialNo(ticket.getSerialNo());
					if (ticketBox.getIsEncrypt() == 1){
						// 加密序列号
						ticketExcel.setUrl(exportUrl + AESUtil.encrypt(ticket.getSerialNo()));
					}else {
						ticketExcel.setUrl(exportUrl + ticket.getSerialNo());
					}
					if (!ServerEnvEnum.PROD.getCode().equals(env)) {
						ticketExcel.setDrawNum(formatDraw(ticket.getDrawNum()));
						ticketExcel.setCipherLuckyNum(RSAUtil.decrypt(ticket.getCipherLuckyNum()));
					}
					excelList.add(ticketExcel);
				}
			}
		}

		ExcelUtil<TicketExcel> util = new ExcelUtil<TicketExcel>(TicketExcel.class);
		return util.exportExcel(excelList, ticketBox.getTitle(), false);
	}


	/**
	 * 导出印刷格式化
	 * @param drawNum
	 * @return
	 */
	private String formatDraw(String drawNum) {
		if(StringUtils.isNotBlank(drawNum)) {
			try {
				List<String> drawList = new ArrayList<String>();
				JSONArray jsonArray = JSONArray.parseArray(drawNum);
				if(null != jsonArray && jsonArray.size() > 0) {
					for (int i = 0; i < jsonArray.size(); i++) {
						JSONObject jo = jsonArray.getJSONObject(i);
						if(null != jo && jo.containsKey("name")
								&& jo.containsKey("num")) {
							drawList.add(jo.getString("name")+","+jo.getString("num"));
						}
					}
				}
				if(null != drawList && drawList.size() >0) {
					return StringUtils.join(drawList.toArray(), ",");
				}
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
		return "";

	}


}
