package com.liquidnet.service.sweet.service.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.liquidnet.commons.lang.util.CollectionUtil;
import com.liquidnet.commons.lang.util.CurrentUtil;
import com.liquidnet.commons.lang.util.IDGenerator;
import com.liquidnet.commons.lang.util.StringUtil;
import com.liquidnet.service.base.ErrorMapping;
import com.liquidnet.service.base.ResponseDto;
import com.liquidnet.service.base.SqlMapping;
import com.liquidnet.service.base.constant.MQConst;
import com.liquidnet.service.sweet.entity.SweetDoudou;
import com.liquidnet.service.sweet.entity.SweetDoudouActive;
import com.liquidnet.service.sweet.mapper.SweetDoudouMapper;
import com.liquidnet.service.sweet.param.SweetDouDouCheckParam;
import com.liquidnet.service.sweet.param.SweetDouDouParam;
import com.liquidnet.service.sweet.service.ISweetDoudouService;
import com.liquidnet.service.sweet.utils.QueueUtils;
import com.liquidnet.service.sweet.utils.RedisDataUtils;
import com.liquidnet.service.sweet.vo.SweetDouDouActiveVo;
import com.liquidnet.service.sweet.vo.SweetDouDouScopeVo;
import com.liquidnet.service.sweet.vo.SweetDouDouVo;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.ss.usermodel.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.InputStream;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * doudou预约签名CD记录表 服务实现类
 * </p>
 *
 * @author jiangxiulong
 * @since 2025-06-04
 */
@Slf4j
@Service
public class SweetDoudouServiceImpl extends ServiceImpl<SweetDoudouMapper, SweetDoudou> implements ISweetDoudouService {
    @Autowired
    private RedisDataUtils redisDataUtils;
    @Autowired
    QueueUtils queueUtils;

    @Override
    public ResponseDto<SweetDouDouVo> info(String activeId) {
        String uid = CurrentUtil.getCurrentUid();
        SweetDouDouVo vo = redisDataUtils.getSweetDouDou(uid, activeId);
        return ResponseDto.success(vo);
    }

    @Override
    public ResponseDto<SweetDouDouVo> create(SweetDouDouParam param) {
        String uid = CurrentUtil.getCurrentUid();
        SweetDouDouVo vo = redisDataUtils.getSweetDouDou(uid, param.getActiveId());
        if (null != vo) {
            return ResponseDto.failure("您已经预约过啦~");
        }
        String nextSnowId = IDGenerator.nextSnowId();
        String username = param.getUsername();
        String phone = param.getPhone();
        String activeId = param.getActiveId();
        String imgUrl = param.getImgUrl();
        String mark = param.getMark();

        SweetDouDouVo entityVo = SweetDouDouVo.getNew();
        entityVo.setDoudouId(nextSnowId);
        entityVo.setUsername(username);
        entityVo.setPhone(phone);
        entityVo.setActiveId(activeId);
        entityVo.setImgUrl(imgUrl);
        entityVo.setMark(mark);
        entityVo.setUserId(uid);
        entityVo.setStatus(1);


        LinkedList<String> sqls = CollectionUtil.linkedListString();
        LinkedList<Object[]> sqlsDataA = CollectionUtil.linkedListObjectArr();
        sqls.add(SqlMapping.get("sweet_doudou.insert"));
        sqlsDataA.add(new Object[]{
                nextSnowId, uid, username, phone, activeId, imgUrl, mark
        });
        queueUtils.sendMsgByRedis(MQConst.SweetQueue.SWEET_ANSWER_INSERT.getKey(),
                SqlMapping.gets(sqls, sqlsDataA));

        redisDataUtils.setSweetDouDou(entityVo);

        return ResponseDto.success(entityVo);
    }

    @Override
    public ResponseDto check(SweetDouDouCheckParam param) {
        if (!checkScope(param.getAuthMobile())) {
            log.info("无权核验, authMoible: {}", param.getAuthMobile());
            return ResponseDto.failure(ErrorMapping.get("20003"));
        }

        SweetDouDouVo vo = redisDataUtils.getSweetDouDou(param.getUserId(), param.getActiveId());
        if (null == vo) {
            return ResponseDto.failure(ErrorMapping.get("90091"));
        }
        if (!vo.getDoudouId().equals(param.getDoudouId())) {
            return ResponseDto.failure(ErrorMapping.get("90095"));
        }

        // 判断状态
        if (vo.getStatus().equals(1)) {
            return ResponseDto.failure(ErrorMapping.get("90092"));
        } else if (vo.getStatus().equals(2)) {
            return ResponseDto.failure(ErrorMapping.get("90093"));
        } else if (vo.getStatus().equals(4)) {
            return ResponseDto.failure(ErrorMapping.get("90094"));
        }

        vo.setStatus(4);

        LinkedList<String> sqls = CollectionUtil.linkedListString();
        LinkedList<Object[]> sqlsDataA = CollectionUtil.linkedListObjectArr();
        sqls.add(SqlMapping.get("sweet_doudou.update"));
        sqlsDataA.add(new Object[]{
                vo.getStatus(), LocalDateTime.now(), vo.getDoudouId()
        });
        queueUtils.sendMsgByRedis(MQConst.SweetQueue.SWEET_ANSWER_INSERT.getKey(),
                SqlMapping.gets(sqls, sqlsDataA));

        redisDataUtils.setSweetDouDou(vo);

        return ResponseDto.success();
    }

    @Override
    public ResponseDto<SweetDouDouVo> detail(SweetDouDouCheckParam param) {
        if (!checkScope(param.getAuthMobile())) {
            log.info("无权核验, authMoible: {}", param.getAuthMobile());
            return ResponseDto.failure(ErrorMapping.get("20003"));
        }
        SweetDouDouVo vo = redisDataUtils.getSweetDouDou(param.getUserId(), param.getActiveId());
        if (vo == null) {
            return ResponseDto.failure(ErrorMapping.get("90091"));
        }
        if (!vo.getDoudouId().equals(param.getDoudouId())) {
            return ResponseDto.failure(ErrorMapping.get("90095"));
        }
        return ResponseDto.success(vo);
    }

    @Override
    public boolean winningUpload(MultipartFile file) {
        List<SweetDouDouVo> fileSweetDouDouVos = getSweetDouDouVoListByFile(file);
        if (fileSweetDouDouVos.isEmpty()) {
            log.error("文件是空的");
            return false;
        }

        for (SweetDouDouVo fileDouDouVo : fileSweetDouDouVos) {
            SweetDouDouVo vo = redisDataUtils.getSweetDouDou(fileDouDouVo.getUserId(), fileDouDouVo.getActiveId());
            if (vo != null) {
                vo.setStatus(fileDouDouVo.getStatus());
                redisDataUtils.setSweetDouDou(vo);
                log.info("更新Redis成功");

                LinkedList<String> sqls = CollectionUtil.linkedListString();
                LinkedList<Object[]> sqlsDataA = CollectionUtil.linkedListObjectArr();
                sqls.add(SqlMapping.get("sweet_doudou.update"));
                sqlsDataA.add(new Object[]{
                        fileDouDouVo.getStatus(), LocalDateTime.now(), vo.getDoudouId()
                });
                queueUtils.sendMsgByRedis(MQConst.SweetQueue.SWEET_ANSWER_INSERT.getKey(),
                        SqlMapping.gets(sqls, sqlsDataA));

                log.info("更新MySQL消息发送成功");
            }
        }
        return true;
    }

    @Override
    public ResponseDto<List<SweetDouDouActiveVo>> getActiveList() {
        final String uid = CurrentUtil.getCurrentUid();
        if (StringUtil.isBlank(uid)){
            log.error("用户未登录");
            return ResponseDto.success();
        }

        // 1. 获取活动列表，并设置进行状态
        List<SweetDoudouActive> sweetDoudouActiveList = redisDataUtils.getSweetDouDouActive();
        if (sweetDoudouActiveList.isEmpty()){
            log.info("暂无活动");
            return ResponseDto.success();
        }

        List<SweetDouDouActiveVo> sweetDouDouActiveVos = new ArrayList<>(sweetDoudouActiveList.size());
        for (SweetDoudouActive doudouActive : sweetDoudouActiveList) {
            SweetDouDouActiveVo douDouActiveVo = getSweetDouDouActiveVo(doudouActive);
            if (douDouActiveVo == null) continue;
            sweetDouDouActiveVos.add(douDouActiveVo);
        }

        return ResponseDto.success(sweetDouDouActiveVos);
    }

    private SweetDouDouActiveVo getSweetDouDouActiveVo(SweetDoudouActive doudouActive) {
        // 1. 判断活动是否已经开始或结束
        Integer activeStatus = checkActiveStatus(doudouActive.getBeginAt(), doudouActive.getEndAt());
        if (activeStatus.equals(1)){
            log.info("活动未开始, activeId: {}, title: {}.", doudouActive.getActiveId(), doudouActive.getTitle());
            return null;
        }
        SweetDouDouActiveVo douDouActiveVo = SweetDouDouActiveVo.getNew().copy(doudouActive);
        douDouActiveVo.setActiveStatus(activeStatus);

        final String uid = CurrentUtil.getCurrentUid();
        if (StringUtil.isBlank(uid)){
            douDouActiveVo.setStatus(0);
        } else {
            SweetDouDouVo sweetDouDou = redisDataUtils.getSweetDouDou(uid, doudouActive.getActiveId());
            if (sweetDouDou == null) {
                douDouActiveVo.setStatus(0);
            }else {
                douDouActiveVo.setStatus(sweetDouDou.getStatus());
                douDouActiveVo.setUserId(sweetDouDou.getUserId());
                douDouActiveVo.setDoudouId(sweetDouDou.getDoudouId());
            }
        }
        return douDouActiveVo;
    }

    public Integer checkActiveStatus(String beginAt, String endAt) {
        final String nowTime = com.liquidnet.commons.lang.util.DateUtil.getNowTime();
        if (null != beginAt && null != endAt && !beginAt.isEmpty() && !endAt.isEmpty()) {
            if (com.liquidnet.commons.lang.util.DateUtil.compareStrDay(nowTime, beginAt) < 0) { // 当前时间小雨开始时间 还未开始呢
                // 未开始
                return 1;
            } else if (com.liquidnet.commons.lang.util.DateUtil.compareStrDay(endAt, nowTime) < 0) { // 解释时间大于当前时间 已过期
                // 已结束
                return 3;
            }else {
                // 进行中
                return 2;
            }
        }
        return 3;
    }

    @Override
    public ResponseDto<SweetDouDouActiveVo> getActiveDetail(String activeId) {
        List<SweetDoudouActive> sweetDoudouActiveList = redisDataUtils.getSweetDouDouActive();
        if (sweetDoudouActiveList.isEmpty()){
            log.info("暂无活动");
            return ResponseDto.success();
        }

        List<SweetDoudouActive> sweetDoudouActives = sweetDoudouActiveList.stream()
                .filter(s -> s.getActiveId().equals(activeId))
                .collect(Collectors.toList());

        if (sweetDoudouActives.isEmpty()) {
            log.info("暂无活动");
            return ResponseDto.failure(ErrorMapping.get("90096"));
        }
        return ResponseDto.success(getSweetDouDouActiveVo(sweetDoudouActives.get(0)));
    }

    private List<SweetDouDouVo> getSweetDouDouVoListByFile(MultipartFile file) {
        // 1. 验证文件类型
        if (!isExcelFile(file)) {
            log.error("请上传excel文件");
            return Collections.emptyList();
        }
        ArrayList<SweetDouDouVo> sweetDouDouVos = new ArrayList<>();
        try (InputStream inputStream = file.getInputStream();
             Workbook workbook = WorkbookFactory.create(inputStream)) {

            Sheet sheet = workbook.getSheetAt(0); // 获取第一个工作表
            Iterator<Row> rowIterator = sheet.iterator();

            // 跳过列名行
            if (rowIterator.hasNext()) rowIterator.next();

            // 2. 处理数据行
            while (rowIterator.hasNext()) {
                Row row = rowIterator.next();
                if (isRowEmpty(row)) continue; // 跳过空行

                SweetDouDouVo vo = SweetDouDouVo.getNew();
                vo.setDoudouId(getStringValue(row.getCell(0)));
                vo.setUserId(getStringValue(row.getCell(1)));
                vo.setActiveId(getStringValue(row.getCell(2)));
                vo.setUsername(getStringValue(row.getCell(3)));
                vo.setPhone(getStringValue(row.getCell(4)));
                vo.setImgUrl(getStringValue(row.getCell(5)));
                String cell7 = getStringValue(row.getCell(6));
                vo.setStatus(cell7.equals("1") ? 3 : 2);

                sweetDouDouVos.add(vo);
            }

            return sweetDouDouVos;
        } catch (Exception e) {
            log.error("error", e);
            return Collections.emptyList();
        }
    }

    // 辅助方法实现
    private boolean isExcelFile(MultipartFile file) {
        String fileName = file.getOriginalFilename();
        return fileName != null &&
                (fileName.endsWith(".xls") || fileName.endsWith(".xlsx"));
    }

    private boolean isRowEmpty(Row row) {
        for (int i = 0; i < 7; i++) {
            Cell cell = row.getCell(i, Row.MissingCellPolicy.CREATE_NULL_AS_BLANK);
            if (cell != null && cell.getCellType() != CellType.BLANK) {
                return false;
            }
        }
        return true;
    }

    private String getStringValue(Cell cell) {
        if (cell == null) return "";

        switch (cell.getCellType()) {
            case STRING:
                return cell.getStringCellValue().trim();
            case NUMERIC:
                return String.valueOf((int) cell.getNumericCellValue());
            case BOOLEAN:
                return String.valueOf(cell.getBooleanCellValue());
            default:
                return "";
        }
    }

    private boolean checkScope(String authMobile) {
        SweetDouDouScopeVo sweetDouDouScopeVo = redisDataUtils.getSweetDouDouScopeVo(authMobile);
        return sweetDouDouScopeVo != null;
    }
}
