package com.liquidnet.service.platform.service.impl.goblin;

import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.support.ExcelTypeEnum;
import com.alibaba.excel.write.metadata.style.WriteCellStyle;
import com.alibaba.excel.write.style.HorizontalCellStyleStrategy;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.liquidnet.commons.lang.util.IDGenerator;
import com.liquidnet.commons.lang.util.StringUtil;
import com.liquidnet.service.goblin.dto.vo.GoblinGoodsInfoVo;
import com.liquidnet.service.goblin.dto.vo.GoblinNftExActivityVo;
import com.liquidnet.service.goblin.dto.vo.GoblinNftExSkuVo;
import com.liquidnet.service.goblin.dto.vo.GoblinNftSkuVo;
import com.liquidnet.service.goblin.entity.*;
import com.liquidnet.service.goblin.mapper.*;
import com.liquidnet.service.goblin.param.GoblinNftExActivityParam;
import com.liquidnet.service.goblin.service.IGoblinNftExActivityService;
import com.liquidnet.service.platform.utils.GoblinRedisUtils;
import com.liquidnet.service.platform.utils.ObjectUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.ss.usermodel.HorizontalAlignment;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletResponse;
import java.io.OutputStream;
import java.net.URLEncoder;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.*;

/**
 * @Author: wll
 * @Description: nft兑换活动服务实现
 * @Date:Create：in 2022/4/19 4:35 下午
 */


@Service
@Slf4j
public class GoblinNftExActivityServiceImpl implements IGoblinNftExActivityService {

    @Autowired
    private GoblinNftExActivityMapper goblinNftExActivityMapper;
    @Autowired
    private GoblinNftExCodeMapper goblinNftExCodeMapper;
    @Autowired
    private GoblinNftExSkuMapper goblinNftExSkuMapper;
    @Autowired
    private GoblinGoodsSkuMapper goblinGoodsSkuMapper;

    @Override
    public String add(GoblinNftExActivityParam goblinNftExActivityParam) {
        LocalDateTime now = LocalDateTime.now();
        GoblinNftExActivity goblinNftExActivity = GoblinNftExActivity.getNew();
        BeanUtils.copyProperties(goblinNftExActivityParam, goblinNftExActivity);
        goblinNftExActivity.setActivityId(IDGenerator.nextSnowId());
        goblinNftExActivity.setCreatedAt(now);
        // mysql数据
        long s = System.currentTimeMillis();
        goblinNftExActivityMapper.addGoblinNftExActivity(goblinNftExActivity);
        log.debug("#MYS耗时:{}ms", System.currentTimeMillis() - s);
        return goblinNftExActivity.getActivityId();
    }

    @Override
    public PageInfo<GoblinNftExActivityVo> pageList(GoblinNftExActivityParam goblinNftExActivityParam) {

        PageHelper.startPage(goblinNftExActivityParam.getPageNum(), 20, true);


        /*
         * 获取分页nft兑换活动数据
         */
        long s = System.currentTimeMillis();
        List<GoblinNftExActivity> goblinNftExActivities = goblinNftExActivityMapper.selectPageList(goblinNftExActivityParam.getTitle(), goblinNftExActivityParam.getStartTime(),
                goblinNftExActivityParam.getEndTime());
        log.debug("#MYS耗时:{}ms", System.currentTimeMillis() - s);

        StringBuffer activityIds = new StringBuffer();
        for (GoblinNftExActivity GoblinNftExActivity : goblinNftExActivities) {
            activityIds.append(GoblinNftExActivity.getActivityId()).append(",");
        }


        ArrayList<GoblinNftExActivityVo> goblinNftExActivityArrayList = ObjectUtil.getGoblinNftExActivityArrayList();
        if (StringUtil.isNotBlank(activityIds)) {
            activityIds.deleteCharAt(activityIds.length() - 1);

            long k = System.currentTimeMillis();
            List<GoblinNftExCode> goblinNftExCodes = goblinNftExCodeMapper.selectByActivityIds(activityIds.toString());
            log.debug("#MYS耗时:{}ms", System.currentTimeMillis() - k);

            for (GoblinNftExActivity goblinNftExActivity : goblinNftExActivities) {
                Integer countNumber = 0;
                Integer useNumber = 0;
                Integer unUseNumber = 0;
                for (GoblinNftExCode goblinNftExCode : goblinNftExCodes) {
                    if (goblinNftExActivity.getActivityId().equals(goblinNftExCode.getActivityId())) {
                        countNumber++;
                        switch (goblinNftExCode.getState()) {
                            case 2:
                                useNumber++;
                                break;
                            default:
                                unUseNumber++;
                        }
                    }
                }

                goblinNftExActivity.setCountNumber(countNumber);
                goblinNftExActivity.setUseNumber(useNumber);
                goblinNftExActivity.setUnUseNumber(unUseNumber);
                goblinNftExActivityArrayList.add(GoblinNftExActivityVo.getNew().copy(goblinNftExActivity));
            }
        }

        PageInfo<GoblinNftExActivityVo> pageInfo = new PageInfo<>(goblinNftExActivityArrayList);
        return pageInfo;
    }

    @Override
    public List<GoblinNftSkuVo> selectNftSkuByActivityId(String activityId) {

        ArrayList<GoblinNftSkuVo> goblinNftSkuVoArrayList = ObjectUtil.getGoblinNftSkuVoArrayList();

        // 获取兑换活动
        GoblinNftExActivity goblinNftExActivity = goblinNftExActivityMapper.selectByActivityId(activityId);
        if (goblinNftExActivity == null) {
            return goblinNftSkuVoArrayList;
        }

        // 获取兑换活动和sku的关联
        List<GoblinNftExSku> goblinNftExSkus = goblinNftExSkuMapper.selectGoblinNftExSkuByActivityIds(activityId);
        if (goblinNftExSkus.size() <= 0){
            return goblinNftSkuVoArrayList;
        }

        StringBuffer skuIds = new StringBuffer();
        Map<String,GoblinNftExSku> goblinNftExSkuMap = new HashMap<>();
        for (GoblinNftExSku goblinNftExSku : goblinNftExSkus) {
            skuIds.append(goblinNftExSku.getSkuId()).append(",");
            goblinNftExSkuMap.put(goblinNftExSku.getSkuId(),goblinNftExSku);
        }



        List<GoblinGoodsSku> goblinGoodsSkus = goblinGoodsSkuMapper.selectBySkuIds(skuIds.toString());


        // 根据活动id获取code码
        List<GoblinNftExCode> goblinNftExCodes = goblinNftExCodeMapper.selectByActivityIds(activityId);


        Map<String, List<GoblinNftExCode>> codeMap = new HashMap<>();
        for (GoblinNftExCode goblinNftExCode : goblinNftExCodes) {
            if (StringUtil.isNotBlank(goblinNftExCode.getSkuId())){
                if (codeMap.get(goblinNftExCode.getSkuId()) == null) {
                    codeMap.put(goblinNftExCode.getSkuId(), new ArrayList<>());
                }
                codeMap.get(goblinNftExCode.getSkuId()).add(goblinNftExCode);
            }else if (StringUtil.isNotBlank(goblinNftExCode.getBoxSkuId())){
                if (codeMap.get(goblinNftExCode.getSkuId()) == null) {
                    codeMap.put(goblinNftExCode.getSkuId(), new ArrayList<>());
                }
                codeMap.get(goblinNftExCode.getSkuId()).add(goblinNftExCode);
            }
        }



        for (GoblinGoodsSku goblinGoodsSku : goblinGoodsSkus) {

            GoblinNftSkuVo goblinNftSkuVo = GoblinNftSkuVo.getNew().copy(goblinGoodsSku);

            // 构建
            GoblinNftExSku goblinNftExSku = goblinNftExSkuMap.get(goblinNftSkuVo.getSkuId());
            GoblinNftExSkuVo goblinNftExSkuVo = GoblinNftExSkuVo.getNew().copy(goblinNftExSku);

            Integer countNumber = 0;
            Integer useNumber = 0;
            Integer unUseNumber = 0;

            List<GoblinNftExCode> gCodes = codeMap.get(goblinGoodsSku.getSkuId());
            if (gCodes == null) {
                continue;
            }
            for (GoblinNftExCode goblinNftExCode : gCodes) {
                countNumber++;
                switch (goblinNftExCode.getState()) {
                    case 2:
                        useNumber++;
                        break;
                    default:
                        unUseNumber++;
                }
            }
            goblinNftSkuVo.setCountNumber(countNumber);
            goblinNftSkuVo.setUseNumber(useNumber);
            goblinNftSkuVo.setUnUseNumber(unUseNumber);
            goblinNftSkuVo.setGoblinNftExSkuVo(goblinNftExSkuVo);
            goblinNftSkuVoArrayList.add(goblinNftSkuVo);
        }



        return goblinNftSkuVoArrayList;
    }

    @Override
    public void excel(HttpServletResponse httpServletResponse, GoblinNftExActivityParam goblinNftExActivityParam) {

        /*
         * 获取分页nft兑换活动数据
         */
        long s = System.currentTimeMillis();
        List<GoblinNftExActivity> goblinNftExActivities = goblinNftExActivityMapper.selectPageList(goblinNftExActivityParam.getTitle(), goblinNftExActivityParam.getStartTime(),
                goblinNftExActivityParam.getEndTime());
        log.debug("#MYS耗时:{}ms", System.currentTimeMillis() - s);

        StringBuffer activityIds = new StringBuffer();
        for (GoblinNftExActivity GoblinNftExActivity : goblinNftExActivities) {
            activityIds.append(GoblinNftExActivity.getActivityId()).append(",");
        }


        ArrayList<GoblinNftExActivityVo> goblinNftExActivityArrayList = ObjectUtil.getGoblinNftExActivityArrayList();
        if (StringUtil.isNotBlank(activityIds)) {
            activityIds.deleteCharAt(activityIds.length() - 1);

            long k = System.currentTimeMillis();
            List<GoblinNftExCode> goblinNftExCodes = goblinNftExCodeMapper.selectByActivityIds(activityIds.toString());
            log.debug("#MYS耗时:{}ms", System.currentTimeMillis() - k);

            for (GoblinNftExActivity goblinNftExActivity : goblinNftExActivities) {
                Integer countNumber = 0;
                Integer useNumber = 0;
                Integer unUseNumber = 0;
                for (GoblinNftExCode goblinNftExCode : goblinNftExCodes) {
                    if (goblinNftExActivity.getActivityId().equals(goblinNftExCode.getActivityId())) {
                        countNumber++;
                        switch (goblinNftExCode.getState()) {
                            case 2:
                                useNumber++;
                                break;
                            default:
                                unUseNumber++;
                        }
                    }
                }

                goblinNftExActivity.setCountNumber(countNumber);
                goblinNftExActivity.setUseNumber(useNumber);
                goblinNftExActivity.setUnUseNumber(unUseNumber);
                goblinNftExActivityArrayList.add(GoblinNftExActivityVo.getNew().copy(goblinNftExActivity));
            }
        }

        try{
            writeExcel(httpServletResponse,goblinNftExActivityArrayList,"活动excel","sheet1",GoblinNftExActivityVo.class);
        }catch (Exception e){
            log.error("导出excel失败！");
        }


    }


    /**
     * 导出
     *
     * @param response
     * @param data
     * @param fileName
     * @param sheetName
     * @param clazz
     * @throws Exception
     */
    public static void writeExcel(HttpServletResponse response, List<? extends Object> data, String fileName,
                                  String sheetName, Class clazz) throws Exception {
        // 表头样式
        WriteCellStyle headWriteCellStyle = new WriteCellStyle();
        // 设置表头居中对齐
        headWriteCellStyle.setHorizontalAlignment(HorizontalAlignment.CENTER);
        // 内容样式
        WriteCellStyle contentWriteCellStyle = new WriteCellStyle();
        // 设置内容靠左对齐
        contentWriteCellStyle.setHorizontalAlignment(HorizontalAlignment.LEFT);
        HorizontalCellStyleStrategy horizontalCellStyleStrategy =
                new HorizontalCellStyleStrategy(headWriteCellStyle, contentWriteCellStyle);
        EasyExcel.write(getOutputStream(fileName, response), clazz).excelType(ExcelTypeEnum.XLSX).sheet(sheetName)
                .registerWriteHandler(horizontalCellStyleStrategy).doWrite(data);

    }

    private static OutputStream getOutputStream(String fileName, HttpServletResponse response) throws Exception {
        fileName = URLEncoder.encode(fileName, "UTF-8");
        response.setContentType("application/vnd.ms-excel");
        response.setCharacterEncoding("utf-8");
        response.setHeader("Content-disposition", "attachment;filename=" + fileName + "-" + LocalDate.now() + ".xlsx");
        return response.getOutputStream();
    }

}
