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.CollectionUtil;
import com.liquidnet.commons.lang.util.IDGenerator;
import com.liquidnet.commons.lang.util.StringUtil;
import com.liquidnet.service.base.ResponseDto;
import com.liquidnet.service.goblin.dto.vo.*;
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.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;
    @Autowired
    GoblinNftExCodeTaskMapper goblinNftExCodeTaskMapper;

    @Override
    public ResponseDto<Object> add(GoblinNftExActivityParam goblinNftExActivityParam) {

        // 根据名称查询
        String title = goblinNftExActivityParam.getTitle();
        GoblinNftExActivity goblinNftExActivityShow = goblinNftExActivityMapper.selectByTitle(title, goblinNftExActivityParam.getUid());
        if (goblinNftExActivityShow != null) {
            return ResponseDto.failure("活动名称已存在!");
        }

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

    @Override
    public PageInfoVo 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(), goblinNftExActivityParam.getUid());

        // 获取活动数量
        int count = goblinNftExActivityMapper.selectActivityCount(goblinNftExActivityParam.getTitle(), goblinNftExActivityParam.getStartTime(),
                goblinNftExActivityParam.getEndTime(), goblinNftExActivityParam.getUid());

        log.debug("#MYS耗时:{}ms", System.currentTimeMillis() - s);

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


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

            // 根据活动ids查询正在生成的兑换码
            List<GoblinNftExCodeTask> goblinNftExCodeTasks = goblinNftExCodeTaskMapper.selectByActivityIds(activityIds.toString());

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

            for (GoblinNftExActivity goblinNftExActivity : goblinNftExActivities) {
                for (GoblinNftExCodeTask goblinNftExCodeTask : goblinNftExCodeTasks) {
                    if (goblinNftExActivity.getActivityId().equals(goblinNftExCodeTask.getActivityId())) {
                        goblinNftExActivity.setIsDisplay(1);
                        break;
                    }
                }

                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));
            }
        }


        PageInfoVo pageInfoVo = PageInfoVo.getNew();
        pageInfoVo.setList(goblinNftExActivityArrayList);
        pageInfoVo.setTotal(count);
        // PageInfoVo pageInfo = new PageInfoVo(goblinNftExActivityArrayList, count, 0);
        return pageInfoVo;
    }

    @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();
        for (GoblinNftExSku goblinNftExSku : goblinNftExSkus) {
            skuIds.append(goblinNftExSku.getSkuId()).append(",");
        }


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


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

        for (GoblinGoodsSku goblinGoodsSku : goblinGoodsSkus) {

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

            GoblinNftExSku nftExSku = GoblinNftExSku.getNew();
            for (GoblinNftExSku goblinNftExSku : goblinNftExSkus) {
                if (goblinGoodsSku.getSkuId().equals(goblinNftExSku.getSkuId())) {
                    nftExSku = goblinNftExSku;
                    break;
                }
            }

            GoblinNftExSkuVo goblinNftExSkuVo = GoblinNftExSkuVo.getNew().copy(nftExSku);

            Integer countNumber = 0;
            Integer useNumber = 0;
            Integer unUseNumber = 0;
            ArrayList<GoblinNftExCode> gCodes = ObjectUtil.getGoblinNftExCodeArrayList();
            for (GoblinNftExCode goblinNftExCode : goblinNftExCodes) {
                /* if (StringUtil.isNotBlank(goblinNftExCode.getBoxSkuId()) && goblinNftExCode.getBoxSkuId().equals(goblinGoodsSku.getSkuId())) {
                    gCodes.add(goblinNftExCode);
                }
                if (StringUtil.isBlank(goblinNftExCode.getBoxSkuId()) && goblinNftExCode.getSkuId().equals(goblinGoodsSku.getSkuId())) {
                    gCodes.add(goblinNftExCode);
                }*/

                if (goblinNftExCode.getSkuId().equals(goblinGoodsSku.getSkuId())){
                    gCodes.add(goblinNftExCode);
                }
            }

            if (gCodes == null || gCodes.size() <= 0) {
                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();
        PageHelper.startPage(goblinNftExActivityParam.getPageNum(), 20, true);
        List<GoblinNftExActivity> goblinNftExActivities = goblinNftExActivityMapper.selectPageList(goblinNftExActivityParam.getTitle(), goblinNftExActivityParam.getStartTime(),
                goblinNftExActivityParam.getEndTime(), goblinNftExActivityParam.getUid());
        log.debug("#MYS耗时:{}ms", System.currentTimeMillis() - s);

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


        ArrayList<ActivityExcelVo> activityExcelVoArrayList = ObjectUtil.getActivityExcelVoArrayList();
        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++;
                        }
                    }
                }
                ActivityExcelVo activityExcelVo = ActivityExcelVo.getNew();
                activityExcelVo.setTitle(goblinNftExActivity.getTitle());
                activityExcelVo.setExcelTime(goblinNftExActivity.getCreatedAt().toString());
                activityExcelVo.setCountNumber(countNumber);
                activityExcelVo.setUseNumber(useNumber);
                activityExcelVo.setUnUseNumber(unUseNumber);
                activityExcelVoArrayList.add(activityExcelVo);
            }
        }

        try {
            writeExcel(httpServletResponse, activityExcelVoArrayList, "活动excel", "sheet1", ActivityExcelVo.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();
    }

}
