package shop.alien.store.service.impl;

import com.alibaba.fastjson.JSONObject;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import shop.alien.entity.store.LifeCoupon;
import shop.alien.entity.store.LifeDiscountCoupon;
import shop.alien.entity.store.LifeNotice;
import shop.alien.entity.store.StoreImg;
import shop.alien.entity.store.StoreInfo;
import shop.alien.entity.store.StoreUser;
import shop.alien.entity.store.vo.WebSocketVo;
import shop.alien.entity.storePlatform.StoreOperationalActivity;
import shop.alien.entity.storePlatform.StoreOperationalActivityAchievement;
import shop.alien.entity.storePlatform.StoreOperationalActivitySignup;
import shop.alien.entity.storePlatform.vo.StoreOperationalActivityDetailVo;
import shop.alien.entity.storePlatform.vo.StoreOperationalActivityMySignupVo;
import shop.alien.entity.storePlatform.vo.StoreOperationalActivitySignupCheckVo;
import shop.alien.mapper.LifeCouponMapper;
import shop.alien.mapper.LifeDiscountCouponMapper;
import shop.alien.mapper.LifeNoticeMapper;
import shop.alien.mapper.StoreImgMapper;
import shop.alien.mapper.StoreInfoMapper;
import shop.alien.mapper.StoreUserMapper;
import shop.alien.mapper.storePlantform.StoreOperationalActivityAchievementMapper;
import shop.alien.mapper.storePlantform.StoreOperationalActivityMapper;
import shop.alien.mapper.storePlantform.StoreOperationalActivitySignupMapper;
import shop.alien.store.config.BaseRedisService;
import shop.alien.store.config.WebSocketProcess;
import shop.alien.store.dto.StoreOperationalActivitySignupDto;
import shop.alien.store.service.StoreOperationalActivityService;
import shop.alien.util.common.Constants;
import shop.alien.util.type.LifeNoticeUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.List;

/**
 * 用户端运营活动服务实现
 *
 * @author system
 * @since 2025-01-XX
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class StoreOperationalActivityServiceImpl implements StoreOperationalActivityService {

    private final StoreOperationalActivityMapper activityMapper;
    private final StoreOperationalActivityAchievementMapper achievementMapper;
    private final StoreImgMapper imgMapper;
    private final LifeDiscountCouponMapper lifeDiscountCouponMapper;
    private final LifeCouponMapper lifeCouponMapper;
    private final StoreInfoMapper storeInfoMapper;
    private final StoreOperationalActivitySignupMapper signupMapper;
    private final BaseRedisService baseRedisService;
    private final LifeNoticeMapper lifeNoticeMapper;

    private final LifeNoticeUtil lifeNoticeUtil;
    private final StoreUserMapper storeUserMapper;
    private final WebSocketProcess webSocketProcess;

    @Override
    public StoreOperationalActivityDetailVo getActivityDetail(Integer id, Integer userId) {
        /**
         * 活动详情查询：
         * 1. 校验活动ID有效性；
         * 2. 组装详情数据（报名状态、报名人数、活动图片等）；
         * 3. 根据用户报名状态计算 detailStatus。
         */
        log.info("StoreOperationalActivityServiceImpl.getActivityDetail: id={}, userId={}", id, userId);
        if (id == null) {
            throw new IllegalArgumentException("活动ID不能为空");
        }
        StoreOperationalActivity activity = activityMapper.selectById(id);
        if (activity == null) {
            return null;
        }

        StoreOperationalActivityDetailVo vo = new StoreOperationalActivityDetailVo();
        BeanUtils.copyProperties(activity, vo);
        vo.setStatusName(resolveStatusName(activity.getStatus()));
        // 报名状态相关字段填充
        fillSignupFlags(vo, activity, userId);
        // 报名人数统计
        fillSignupCounts(vo);
        Integer signupStatus = resolveCurrentUserSignupStatus(activity.getId(), userId);
        // 详情按钮状态计算
        vo.setDetailStatus(resolveDetailStatus(activity, signupStatus));

        // 设置优惠券名称（判空处理）
        if (activity.getCouponId() != null) {
            LifeDiscountCoupon coupon = lifeDiscountCouponMapper.selectByIdIncludeDeleted(activity.getCouponId());
            if (coupon != null) {
                vo.setCouponName(coupon.getName());
            }
        }

        // 设置代金券名称（判空处理）
        if (activity.getVoucherId() != null) {
            LifeCoupon voucher = lifeCouponMapper.selectById(String.valueOf(activity.getVoucherId()));
            if (voucher != null) {
                vo.setVoucherName(voucher.getName());
            }
        }

        // 店铺信息与活动图片
        attachStoreInfo(vo);
        fillActivityImages(vo);
        return vo;
    }

    @Override
    public StoreOperationalActivityDetailVo getActivityDetailForPlatform(Integer id, Integer userId) {
        /**
         * 活动详情查询：
         * 1. 校验活动ID有效性；
         * 2. 组装详情数据（报名状态、报名人数、活动图片等）；
         * 3. 根据用户报名状态计算 detailStatus。
         */
        log.info("StoreOperationalActivityController.getActivityDetailForPlatform id={}, userId={}", id, userId);
        if (id == null) {
            throw new IllegalArgumentException("活动ID不能为空");
        }
        StoreOperationalActivity activity = activityMapper.selectById(id);
        if (activity == null) {
            return null;
        }

        StoreOperationalActivityDetailVo vo = new StoreOperationalActivityDetailVo();
        BeanUtils.copyProperties(activity, vo);
        vo.setStatusName(resolveStatusName(activity.getStatus()));
        // 报名状态相关字段填充
        fillSignupFlags(vo, activity, userId);
        // 报名人数统计
        fillSignupCounts(vo);
        Integer signupStatus = resolveCurrentUserSignupStatus(activity.getId(), userId);
        // 详情按钮状态计算
        vo.setDetailStatus(resolveDetailStatus(activity, signupStatus));

        // 设置优惠券名称（判空处理）
        if (activity.getCouponId() != null) {
            LifeDiscountCoupon coupon = lifeDiscountCouponMapper.selectByIdIncludeDeleted(activity.getCouponId());
            if (coupon != null) {
                vo.setCouponName(coupon.getName());
            }
        }

        // 设置代金券名称（判空处理）
        if (activity.getVoucherId() != null) {
            LifeCoupon voucher = lifeCouponMapper.selectById(String.valueOf(activity.getVoucherId()));
            if (voucher != null) {
                vo.setVoucherName(voucher.getName());
            }
        }

        // 店铺信息与活动图片
        attachStoreInfo(vo);
        fillActivityImages(vo);
        return vo;
    }

    @Override
    public StoreOperationalActivitySignupCheckVo checkSignup(Integer activityId, Integer userId) {
        log.info("StoreOperationalActivityServiceImpl.checkSignup: activityId={}, userId={}", activityId, userId);
        if (activityId == null) {
            throw new IllegalArgumentException("活动ID不能为空");
        }
        if (userId == null) {
            throw new IllegalArgumentException("用户ID不能为空");
        }
        StoreOperationalActivity activity = activityMapper.selectById(activityId);
        if (activity == null) {
            throw new IllegalArgumentException("活动不存在");
        }

        Integer signupCount = signupMapper.countSignupByActivityId(activityId);
        Integer limitPeople = activity.getActivityLimitPeople();
        boolean full = limitPeople != null && limitPeople > 0 && signupCount != null && signupCount >= limitPeople;

        Integer userSignupCount = signupMapper.countSignedUpByActivityAndUser(activityId, userId);
        boolean signedUp = userSignupCount != null && userSignupCount > 0;

        StoreOperationalActivitySignupCheckVo vo = new StoreOperationalActivitySignupCheckVo();
        vo.setCurrentSignupCount(signupCount != null ? signupCount : 0);
        vo.setActivityLimitPeople(limitPeople);
        vo.setFull(full);
        vo.setSignedUp(signedUp);
        return vo;
    }

    @Override
    public List<StoreOperationalActivityMySignupVo> listMySignups(Integer userId) {
        /**
         * 我的报名列表：
         * - 聚合活动基础信息、报名审核状态、成果状态等字段；
         * - 计算列表展示状态（status）与状态文案（statusLabel）；
         * - 只返回未删除的数据。
         */
        if (userId == null) {
            throw new IllegalArgumentException("用户ID不能为空");
        }
        List<StoreOperationalActivityMySignupVo> list = signupMapper.selectMySignups(userId);
        if (list == null || list.isEmpty()) {
            return Collections.emptyList();
        }
        for (StoreOperationalActivityMySignupVo item : list) {
            if (item == null) {
                continue;
            }
            // 基于报名时间窗口生成展示文案（报名未开始/报名中/报名已结束）
            item.setStatusLabel(resolveSignupStatusLabel(item.getSignupStatus(), item.getActivityStatus()));
            // 基于活动状态、报名审核状态与成果状态计算列表展示状态
            item.setStatus(resolveMySignupStatus(item));
        }
        return list;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean deleteSignup(Integer activityId, Integer signupId) {
        if (activityId == null) {
            throw new IllegalArgumentException("活动ID不能为空");
        }
        if (signupId == null) {
            throw new IllegalArgumentException("报名ID不能为空");
        }
        StoreOperationalActivitySignup signup = signupMapper.selectById(signupId);
        if (signup == null || (signup.getDeleteFlag() != null && signup.getDeleteFlag() == 1)) {
            throw new IllegalArgumentException("报名信息不存在或已删除");
        }
        if (!activityId.equals(signup.getActivityId())) {
            throw new IllegalArgumentException("报名信息与活动不匹配");
        }
        int deletedSignup = signupMapper.delete(new LambdaQueryWrapper<StoreOperationalActivitySignup>()
                .eq(StoreOperationalActivitySignup::getId, signupId)
                .eq(StoreOperationalActivitySignup::getActivityId, activityId));
        int deletedAchievement = achievementMapper.delete(new LambdaQueryWrapper<StoreOperationalActivityAchievement>()
                .eq(StoreOperationalActivityAchievement::getSignupId, signupId)
                .eq(StoreOperationalActivityAchievement::getActivityId, activityId));
        log.info("deleteSignup success. activityId={}, signupId={}, deletedSignup={}, deletedAchievement={}",
                activityId, signupId, deletedSignup, deletedAchievement);
        return deletedSignup > 0 || deletedAchievement > 0;
    }

    @Override
    public boolean signup(StoreOperationalActivitySignupDto dto) {
        if (dto == null) {
            throw new IllegalArgumentException("报名参数不能为空");
        }
        if (dto.getActivityId() == null) {
            throw new IllegalArgumentException("活动ID不能为空");
        }
        if (dto.getUserId() == null) {
            throw new IllegalArgumentException("用户ID不能为空");
        }
        if (dto.getPhone() == null || dto.getPhone().trim().isEmpty()) {
            throw new IllegalArgumentException("手机号不能为空");
        }

        StoreOperationalActivity activity = activityMapper.selectById(dto.getActivityId());
        if (activity == null) {
            throw new IllegalArgumentException("活动不存在");
        }
        validateSignupTime(activity);

        String lockKey = "activity:signup:" + dto.getActivityId();
        String lockVal = baseRedisService.lock(lockKey, 5000, 5000);
        if (lockVal == null) {
            throw new IllegalArgumentException("系统繁忙，请稍后再试");
        }

        try {
            Integer userSignupCount = signupMapper.countApprovedByActivityAndUser(dto.getActivityId(), dto.getUserId());
            if (userSignupCount != null && userSignupCount > 0) {
                throw new IllegalArgumentException("已成功报名，请勿重复报名");
            }

            Integer samePhoneCount = signupMapper.countByActivityIdAndPhone(dto.getActivityId(), dto.getPhone().trim());
            if (samePhoneCount != null && samePhoneCount > 0) {
                throw new IllegalArgumentException("同一活动同一手机号已报名，不允许重复报名");
            }

            Integer approvedCount = signupMapper.countSignupByActivityId(dto.getActivityId());
            Integer limitPeople = activity.getActivityLimitPeople();
            if (limitPeople != null && limitPeople > 0 && approvedCount != null && approvedCount >= limitPeople) {
                throw new IllegalArgumentException("当前报名人数已满");
            }

            StoreOperationalActivitySignup signup = new StoreOperationalActivitySignup();
            signup.setActivityId(dto.getActivityId());
            signup.setStoreId(activity.getStoreId());
            signup.setUserId(dto.getUserId());
            signup.setUserName(dto.getUserName());
            signup.setPhone(dto.getPhone());
            signup.setStatus(0);
            signup.setSignupTime(new Date());
            signup.setDeleteFlag(0);
            signup.setCreatedUserId(dto.getUserId());
            boolean result = signupMapper.insert(signup) > 0;

            // 报名成功后给商家发送通知
            if (result) {
                try {
                    sendSignupNoticeToStore(signup.getId(), activity);
                } catch (Exception e) {
                    log.error("发送活动报名通知失败，signupId={}, error={}", signup.getId(), e.getMessage(), e);
                }
            }

            return result;
        } finally {
            baseRedisService.unlock(lockKey, lockVal);
        }
    }

    private void validateSignupTime(StoreOperationalActivity activity) {
        Integer status = activity.getStatus();
        if (status == null || (status != 2 && status != 5)) {
            throw new IllegalArgumentException("活动状态不允许报名");
        }
        Date now = new Date();
        if (activity.getSignupStartTime() != null && now.before(activity.getSignupStartTime())) {
            throw new IllegalArgumentException("未到报名时间");
        }
        if (activity.getSignupEndTime() != null && now.after(activity.getSignupEndTime())) {
            throw new IllegalArgumentException("报名已结束");
        }
//        if (activity.getStartTime() != null && status == 5 && now.before(activity.getStartTime())) {
//            throw new IllegalArgumentException("活动未开始");
//        }
//        if (activity.getEndTime() != null && now.after(activity.getEndTime())) {
//            throw new IllegalArgumentException("活动已结束");
//        }
    }

    private String resolveStatusName(Integer status) {
        if (status == null) {
            return null;
        }
        switch (status) {
            case 1:
                return "待审核";
            case 2:
                return "未开始";
            case 3:
                return "审核拒绝";
            case 4:
                return "已售罄";
            case 5:
                return "进行中";
            case 6:
                return "已下架";
            case 7:
                return "已结束";
            default:
                return null;
        }
    }

    private void attachStoreInfo(StoreOperationalActivityDetailVo vo) {
        if (vo == null || vo.getStoreId() == null) {
            return;
        }
        StoreInfo storeInfo = storeInfoMapper.selectById(vo.getStoreId());
        if (storeInfo != null) {
            vo.setStoreName(storeInfo.getStoreName());
        }
    }

    private void fillActivityImages(StoreOperationalActivityDetailVo vo) {
        if (vo == null || vo.getStoreId() == null || vo.getId() == null) {
            return;
        }
        StoreImg titleImg = imgMapper.selectOne(new LambdaQueryWrapper<StoreImg>()
                .eq(StoreImg::getStoreId, vo.getStoreId())
                .eq(StoreImg::getBusinessId, vo.getId())
                .eq(StoreImg::getImgType, 26)
                .eq(StoreImg::getDeleteFlag, 0));
        if (titleImg != null) {
            vo.setActivityTitleImgUrl(titleImg.getImgUrl());
        }

        java.util.List<StoreImg> detailImgs = imgMapper.selectList(new LambdaQueryWrapper<StoreImg>()
                .eq(StoreImg::getStoreId, vo.getStoreId())
                .eq(StoreImg::getBusinessId, vo.getId())
                .eq(StoreImg::getImgType, 27)
                .eq(StoreImg::getDeleteFlag, 0));
        if (detailImgs != null && !detailImgs.isEmpty()) {
            List<String> detailUrls = new ArrayList<>();
            for (StoreImg item : detailImgs) {
                if (item != null && item.getImgUrl() != null && !item.getImgUrl().trim().isEmpty()) {
                    detailUrls.add(item.getImgUrl().trim());
                }
            }
            vo.setActivityDetailImgUrlList(detailUrls);
        }
    }

    private void fillSignupCounts(StoreOperationalActivityDetailVo vo) {
        if (vo == null || vo.getId() == null) {
            return;
        }
        Integer signupCount = signupMapper.countSignupByActivityId(vo.getId());
        Integer approvedCount = signupMapper.countApprovedByActivityId(vo.getId());
        vo.setCurrentSignupCount(signupCount != null ? signupCount : 0);
        vo.setCurrentApprovedCount(approvedCount != null ? approvedCount : 0);
    }

    private void fillSignupFlags(StoreOperationalActivityDetailVo vo, StoreOperationalActivity activity, Integer userId) {
        if (vo == null || activity == null) {
            return;
        }
        vo.setInSignupTime(resolveInSignupTime(activity));
        if (userId == null) {
            vo.setSignedUp(false);
            return;
        }
        Integer signupCount = signupMapper.countSignedUpByActivityAndUser(activity.getId(), userId);
        vo.setSignedUp(signupCount != null && signupCount > 0);
    }

    private boolean resolveInSignupTime(StoreOperationalActivity activity) {
        if (activity == null) {
            return false;
        }
        Date now = new Date();
        Date start = activity.getSignupStartTime();
        Date end = activity.getSignupEndTime();
        if (start != null && now.before(start)) {
            return false;
        }
        if (end != null && now.after(end)) {
            return false;
        }
        return true;
    }

    private Integer resolveDetailStatus(StoreOperationalActivity activity, Integer signupStatus) {
        if (activity == null) {
            return null;
        }
        Date now = new Date();
        if (activity.getStatus() != null && activity.getStatus() == 7) {
            return 0;
        }
        if (activity.getEndTime() != null && now.after(activity.getEndTime())) {
            return 0;
        }
        Integer status = activity.getStatus();
        if (status != null && (status == 0 || status == 1 || status == 3 || status == 4 || status == 6)) {
            return 1;
        }
        if (signupStatus != null && signupStatus == 2
                && activity.getStartTime() != null && now.before(activity.getStartTime())) {
            return 2;
        }
        if (activity.getSignupEndTime() != null && now.after(activity.getSignupEndTime())) {
            if (status != null && status == 5 && signupStatus != null && signupStatus == 2) {
                return 3;
            }
            return 1;
        }
        if (signupStatus != null) {
            if (signupStatus == 2) {
                return 3;
            }
            if (signupStatus == 0) {
                return 4;
            }
            if (signupStatus == 1) {
                if (activity.getSignupEndTime() != null && now.before(activity.getSignupEndTime())) {
                    return 5;
                }
                return 1;
            }
        }
        return 5;
    }

    private Integer resolveCurrentUserSignupStatus(Integer activityId, Integer userId) {
        if (userId == null || activityId == null) {
            return null;
        }
        return signupMapper.selectLatestSignupStatus(activityId, userId);
    }

    private String resolveSignupStatusLabel(Integer signupStatus, Integer activityStatus) {
        if (signupStatus == null) {
            return null;
        }
        if (signupStatus == 0) {
            return "报名未开始";
        }
        if (signupStatus == 1) {
            return "报名中";
        }
        if (signupStatus == 2) {
            return "报名已结束";
        }
        return null;
    }

    private Integer resolveMySignupStatus(StoreOperationalActivityMySignupVo item) {
        /**
         * 列表状态计算规则：
         * 1 -> 活动已结束且无成果
         * 2 -> 活动已结束且有成果
         * 3 -> 活动进行中且有成果
         * 4 -> 活动进行中且已报名无成果
         * 5 -> 活动未开始且报名已拒绝
         * 6 -> 活动未开始且报名成功
         * 7 -> 报名审核中
         */
        if (item == null) {
            return null;
        }
        Date now = new Date();
        Integer activityStatus = item.getActivityStatus();
        boolean hasAchievement = item.getHasAchievement() != null && item.getHasAchievement() == 1;
        Integer auditStatus = item.getSignupAuditStatus();
        Date startTime = item.getStartTime();
        Date endTime = item.getEndTime();
        boolean ended = (activityStatus != null && (activityStatus == 7 || activityStatus == 6))
                || (endTime != null && now.after(endTime));
        if (ended) {
            return hasAchievement ? 2 : 1;
        }
        if (activityStatus != null && activityStatus == 5 && auditStatus == 2) {
            return hasAchievement ? 3 : 4;
        }
        if (activityStatus != null && activityStatus == 5) {
            if (auditStatus == 1) {
                return 5;
            }
            if (auditStatus == 0) {
                return 7;
            }
        }

        if (activityStatus != null && activityStatus == 2) {
            if (auditStatus != null && auditStatus == 1) {
                return 5;
            }
            if (auditStatus != null && auditStatus == 2) {
                return 6;
            }
        }
        if (auditStatus != null && auditStatus == 0
                && startTime != null && !now.after(startTime)) {
            return 7;
        }
        return null;
    }

    /**
     * 发送活动报名通知给商家
     *
     * @param signupId 报名ID
     * @param activity 活动信息
     */
    private void sendSignupNoticeToStore(Integer signupId, StoreOperationalActivity activity) {
        log.info("StoreOperationalActivityServiceImpl.sendSignupNoticeToStore: signupId={}, activityId={}", signupId, activity.getId());

        if (activity.getStoreId() == null) {
            log.warn("活动商户ID为空，无法发送通知，activityId={}", activity.getId());
            return;
        }

        // 查询商户信息
        StoreInfo storeInfo = storeInfoMapper.selectById(activity.getStoreId());
        if (storeInfo == null) {
            log.warn("商户信息不存在，无法发送通知，storeId={}", activity.getStoreId());
            return;
        }

        // 查询商户用户信息（获取手机号）
        LambdaQueryWrapper<StoreUser> userWrapper = new LambdaQueryWrapper<>();
        userWrapper.eq(StoreUser::getStoreId, activity.getStoreId())
                .eq(StoreUser::getDeleteFlag, 0)
                .last("LIMIT 1");
        StoreUser storeUser = storeUserMapper.selectOne(userWrapper);
        if (storeUser == null || storeUser.getPhone() == null) {
            log.warn("商户用户信息不存在或手机号为空，无法发送通知，storeId={}", activity.getStoreId());
            return;
        }

        String phone = storeUser.getPhone();
        String receiverId = "store_" + phone;

        // 构建通知内容
        String message = "您的活动收到了一条新的报名";

        JSONObject contextJson = new JSONObject();
        contextJson.put("signupId", signupId);
        contextJson.put("activityId", activity.getId());
        contextJson.put("activityName", activity.getActivityName());
        contextJson.put("message", message);

        LifeNotice lifeNotice = new LifeNotice();
        lifeNotice.setSenderId("system");
        lifeNotice.setReceiverId(receiverId);
        lifeNotice.setBusinessId(signupId);
        lifeNotice.setTitle("活动报名通知");
        lifeNotice.setContext(contextJson.toJSONString());
        lifeNotice.setNoticeType(Constants.Notice.SYSTEM_NOTICE); // 系统通知
        lifeNotice.setIsRead(0);

        // 保存通知到数据库
        lifeNoticeUtil.fillUserTypeAndRefId(lifeNotice);
        lifeNoticeMapper.insert(lifeNotice);

        // 通过WebSocket发送实时通知
        try {
            WebSocketVo webSocketVo = new WebSocketVo();
            webSocketVo.setSenderId("system");
            webSocketVo.setReceiverId(receiverId);
            webSocketVo.setCategory("notice");
            webSocketVo.setNoticeType("1");
            webSocketVo.setIsRead(0);
            webSocketVo.setText(JSONObject.toJSONString(lifeNotice));

            webSocketProcess.sendMessage(receiverId, JSONObject.toJSONString(webSocketVo));
            log.info("活动报名通知发送成功，signupId={}, receiverId={}", signupId, receiverId);
        } catch (Exception e) {
            log.error("发送WebSocket通知失败，signupId={}, receiverId={}, error={}", signupId, receiverId, e.getMessage(), e);
        }
    }
}
