package shop.alien.lawyer.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import shop.alien.entity.result.R;
import shop.alien.entity.store.LawyerUserViolation;
import shop.alien.entity.store.LifeNotice;
import shop.alien.entity.store.vo.LifeMessageVo;
import shop.alien.entity.store.vo.LifeNoticeVo;
import shop.alien.lawyer.service.LawyerNoticeService;
import shop.alien.mapper.LawyerUserViolationMapper;
import shop.alien.mapper.LifeMessageMapper;
import shop.alien.mapper.LifeNoticeMapper;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 律师通知服务实现类
 *
 * @author system
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class LawyerNoticeServiceImpl extends ServiceImpl<LifeNoticeMapper, LifeNotice> implements LawyerNoticeService {

    /**
     * 系统发送者标识
     */
    private static final String SYSTEM_SENDER = "system";

    /**
     * 平台类型：1-平台
     */
    private static final String PLATFORM_TYPE_ONE = "1";

    /**
     * 店铺审核通知标题
     */
    private static final String STORE_AUDIT_NOTICE_TITLE = "店铺审核通知";

    /**
     * 删除标识：0-未删除
     */
    private static final Integer DELETE_FLAG_NOT_DELETED = 0;

    /**
     * 未读标识：0-未读
     */
    private static final Integer IS_READ_UNREAD = 0;

    /**
     * 已读标识：1-已读
     */
    private static final Integer IS_READ_READ = 1;

    /**
     * 发送者ID分隔符
     */
    private static final String SENDER_ID_SEPARATOR = "_";

    /**
     * 店铺类型标识
     */
    private static final String STORE_TYPE = "store";

    /**
     * 用户类型标识
     */
    private static final String USER_TYPE = "user";

    /**
     * 报告上下文类型范围
     */
    private static final String REPORT_CONTEXT_TYPE_RANGE = "1,2,3,6";

    private final LifeNoticeMapper lifeNoticeMapper;

    private final LifeMessageMapper lifeMessageMapper;

    private final LawyerUserViolationMapper lawyerUserViolationMapper;

    @Override
    public R<IPage<LifeNoticeVo>> getLawyerNoticeList(Integer pageNum, Integer pageSize, String receiverId, Integer noticeType) {
        // 构建查询条件
        LambdaQueryWrapper<LifeNotice> queryWrapper = buildQueryWrapper(receiverId, noticeType);
        
        // 使用分页查询，避免查询全部数据
        IPage<LifeNotice> noticePage = new Page<>(pageNum, pageSize);
        IPage<LifeNotice> noticeResult = lifeNoticeMapper.selectPage(noticePage, queryWrapper);
        
        List<LifeNotice> lifeNoticeList = noticeResult.getRecords();
        if (CollectionUtil.isEmpty(lifeNoticeList)) {
            return R.data(createEmptyPageResult(pageNum, pageSize));
        }

        // 提取业务ID列表
        List<Integer> businessIdList = extractBusinessIdList(lifeNoticeList);
        
        // 获取违规信息映射
        Map<Integer, String> lawyerUserViolationMap = getLifeUserViolationMap(businessIdList);
        
        // 提取发送者ID并按类型分组
        Map<String, List<String>> senderIdGroupMap = extractSenderIdGroupMap(lifeNoticeList);
        
        // 获取用户信息列表
        List<LifeMessageVo> userList = getUserList(senderIdGroupMap);
        
        // 转换为VO列表
        List<LifeNoticeVo> noticeVoList = convertToNoticeVoList(lifeNoticeList, userList);
        
        // 设置平台类型
        setPlatformType(noticeVoList, lawyerUserViolationMap);
        
        // 构建分页结果
        IPage<LifeNoticeVo> result = new Page<>(pageNum, pageSize);
        result.setRecords(noticeVoList);
        result.setTotal(noticeResult.getTotal());
        result.setPages(noticeResult.getPages());
        result.setCurrent(noticeResult.getCurrent());
        result.setSize(noticeResult.getSize());
        
        return R.data(result);
    }

    /**
     * 构建查询条件
     *
     * @param receiverId 接收人ID
     * @param noticeType 通知类型
     * @return 查询条件包装器
     */
    private LambdaQueryWrapper<LifeNotice> buildQueryWrapper(String receiverId, Integer noticeType) {
        LambdaQueryWrapper<LifeNotice> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(LifeNotice::getReceiverId, receiverId)
                .eq(LifeNotice::getNoticeType, noticeType)
                .eq(LifeNotice::getDeleteFlag, DELETE_FLAG_NOT_DELETED)
                .orderByDesc(LifeNotice::getCreatedTime);
        return queryWrapper;
    }

    /**
     * 创建空的分页结果
     *
     * @param pageNum  页码
     * @param pageSize 每页大小
     * @return 空的分页结果
     */
    private IPage<LifeNoticeVo> createEmptyPageResult(Integer pageNum, Integer pageSize) {
        IPage<LifeNoticeVo> result = new Page<>(pageNum, pageSize);
        result.setRecords(Collections.emptyList());
        result.setTotal(0L);
        result.setPages(0);
        return result;
    }

    /**
     * 提取业务ID列表
     *
     * @param lifeNoticeList 通知列表
     * @return 业务ID列表
     */
    private List<Integer> extractBusinessIdList(List<LifeNotice> lifeNoticeList) {
        return lifeNoticeList.stream()
                .map(LifeNotice::getBusinessId)
                .filter(Objects::nonNull)
                .distinct()
                .collect(Collectors.toList());
    }

    /**
     * 获取违规信息映射
     *
     * @param businessIdList 业务ID列表
     * @return 违规信息映射，key为业务ID，value为报告上下文类型
     */
    private Map<Integer, String> getLifeUserViolationMap(List<Integer> businessIdList) {
        if (CollectionUtil.isEmpty(businessIdList)) {
            return Collections.emptyMap();
        }
        
        List<LawyerUserViolation> lawyerUserViolationList = lawyerUserViolationMapper.selectBatchIds(businessIdList);
        if (CollectionUtil.isEmpty(lawyerUserViolationList)) {
            return Collections.emptyMap();
        }
        
        return lawyerUserViolationList.stream()
                .filter(violation -> violation != null && violation.getId() != null)
                .collect(Collectors.toMap(
                        LawyerUserViolation::getId,
                        violation -> StringUtils.defaultString(violation.getReportContextType(), ""),
                        (existing, replacement) -> existing
                ));
    }

    /**
     * 提取发送者ID并按类型分组
     *
     * @param lifeNoticeList 通知列表
     * @return 发送者ID分组映射，key为类型（store/user），value为ID列表
     */
    private Map<String, List<String>> extractSenderIdGroupMap(List<LifeNotice> lifeNoticeList) {
        return lifeNoticeList.stream()
                .map(LifeNotice::getSenderId)
                .filter(senderId -> StringUtils.isNotBlank(senderId) 
                        && !SYSTEM_SENDER.equals(senderId) 
                        && senderId.contains(SENDER_ID_SEPARATOR))
                .collect(Collectors.groupingBy(
                        senderId -> senderId.split(SENDER_ID_SEPARATOR)[0],
                        Collectors.mapping(
                                senderId -> senderId.split(SENDER_ID_SEPARATOR)[1],
                                Collectors.toList()
                        )
                ));
    }

    /**
     * 获取用户信息列表
     *
     * @param senderIdGroupMap 发送者ID分组映射
     * @return 用户信息列表
     */
    private List<LifeMessageVo> getUserList(Map<String, List<String>> senderIdGroupMap) {
        String storePhones = buildPhoneString(senderIdGroupMap.get(STORE_TYPE));
        String userPhones = buildPhoneString(senderIdGroupMap.get(USER_TYPE));
        return lifeMessageMapper.getLifeUserAndStoreUserByPhone(storePhones, userPhones);
    }

    /**
     * 构建手机号字符串
     *
     * @param phoneList 手机号列表
     * @return 手机号字符串，格式：'phone1','phone2'
     */
    private String buildPhoneString(List<String> phoneList) {
        if (CollectionUtil.isEmpty(phoneList)) {
            return "''";
        }
        return "'" + String.join("','", phoneList) + "'";
    }

    /**
     * 转换为通知VO列表
     *
     * @param lifeNoticeList 通知列表
     * @param userList       用户信息列表
     * @return 通知VO列表
     */
    private List<LifeNoticeVo> convertToNoticeVoList(List<LifeNotice> lifeNoticeList, List<LifeMessageVo> userList) {
        if (CollectionUtil.isEmpty(userList)) {
            return lifeNoticeList.stream()
                    .map(this::convertToNoticeVo)
                    .collect(Collectors.toList());
        }
        
        Map<String, LifeMessageVo> userMap = userList.stream()
                .filter(user -> user != null && StringUtils.isNotBlank(user.getPhoneId()))
                .collect(Collectors.toMap(
                        LifeMessageVo::getPhoneId,
                        user -> user,
                        (existing, replacement) -> existing
                ));
        
        return lifeNoticeList.stream()
                .map(notice -> {
                    LifeNoticeVo noticeVo = convertToNoticeVo(notice);
                    LifeMessageVo userInfo = userMap.get(notice.getSenderId());
                    if (userInfo != null && !SYSTEM_SENDER.equals(noticeVo.getSenderId())) {
                        noticeVo.setUserName(userInfo.getUserName());
                        noticeVo.setUserImage(userInfo.getUserImage());
                    }
                    return noticeVo;
                })
                .collect(Collectors.toList());
    }

    /**
     * 转换为通知VO
     *
     * @param notice 通知实体
     * @return 通知VO
     */
    private LifeNoticeVo convertToNoticeVo(LifeNotice notice) {
        LifeNoticeVo noticeVo = new LifeNoticeVo();
        BeanUtils.copyProperties(notice, noticeVo);
        return noticeVo;
    }

    /**
     * 设置平台类型
     *
     * @param noticeVoList           通知VO列表
     * @param lawyerUserViolationMap   违规信息映射
     */
    private void setPlatformType(List<LifeNoticeVo> noticeVoList, Map<Integer, String> lawyerUserViolationMap) {
        for (LifeNoticeVo noticeVo : noticeVoList) {
            if (noticeVo == null) {
                continue;
            }
            
            // 业务ID为空时设置为平台类型
            if (noticeVo.getBusinessId() == null) {
                noticeVo.setPlatformType(PLATFORM_TYPE_ONE);
                continue;
            }
            
            // 店铺审核通知设置为平台类型
            if (STORE_AUDIT_NOTICE_TITLE.equals(noticeVo.getTitle())) {
                noticeVo.setPlatformType(PLATFORM_TYPE_ONE);
                continue;
            }
            
            // 根据违规信息设置平台类型
            String reportContextType = lawyerUserViolationMap.get(noticeVo.getBusinessId());
            if (StringUtils.isNotBlank(reportContextType) 
                    && REPORT_CONTEXT_TYPE_RANGE.contains(reportContextType)) {
                noticeVo.setPlatformType(PLATFORM_TYPE_ONE);
            }
        }
    }

    @Override
    public R<Boolean> hasUnreadNotice(String receiverId) {
        log.info("LawyerNoticeServiceImpl.hasUnreadNotice, receiverId={}", receiverId);
        
        // 参数校验
        if (StringUtils.isBlank(receiverId)) {
            log.warn("接收人ID为空");
            return R.fail("接收人ID不能为空");
        }
        
        // 构建查询条件：查询未读且未删除的通知，使用LIMIT 1优化性能
        LambdaQueryWrapper<LifeNotice> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(LifeNotice::getReceiverId, receiverId)
                .eq(LifeNotice::getIsRead, IS_READ_UNREAD)
                .eq(LifeNotice::getDeleteFlag, DELETE_FLAG_NOT_DELETED)
                .last("LIMIT 1");
        
        // 使用selectOne判断是否存在，数据库找到一条记录即返回，比selectCount更高效
        LifeNotice notice = lifeNoticeMapper.selectOne(queryWrapper);
        boolean hasUnread = notice != null;
        
        log.debug("LawyerNoticeServiceImpl.hasUnreadNotice, receiverId={}, hasUnread={}", receiverId, hasUnread);
        return R.data(hasUnread);
    }

    /**
     * 根据通知ID标记通知为已读
     * <p>
     * 处理流程：
     * 1. 参数校验：通知ID必须大于0且不能为null
     * 2. 构建更新条件：根据ID匹配通知记录
     * 3. 执行更新：将isRead字段设置为1（已读）
     * 4. 返回更新结果：返回受影响的记录数
     * </p>
     * <p>
     * 注意事项：
     * - 如果通知不存在或ID无效，更新操作将不会影响任何记录，返回0
     * - 如果通知已经是已读状态，更新操作仍然会执行但不会改变状态
     * </p>
     *
     * @param id 通知ID，必须大于0且不能为null
     * @return 受影响的记录数，>0表示更新成功，0表示未找到匹配的记录或更新失败
     * @throws IllegalArgumentException 当通知ID无效时抛出
     * @throws RuntimeException        当更新操作异常时抛出
     * @author system
     * @since 2025-01-XX
     */
    @Override
    public int readNoticeById(Integer id) {
        log.info("标记通知为已读开始，id={}", id);

        // 参数校验
        validateNoticeId(id);

        try {
            // 构建更新条件
            LambdaUpdateWrapper<LifeNotice> updateWrapper = buildUpdateWrapper(id);

            // 执行更新操作
            int affectedRows = executeUpdate(updateWrapper);

            // 记录更新结果
            logUpdateResult(id, affectedRows);

            return affectedRows;
        } catch (IllegalArgumentException e) {
            log.warn("标记通知为已读参数校验失败，id={}，错误信息：{}", id, e.getMessage());
            throw e;
        } catch (RuntimeException e) {
            log.error("标记通知为已读异常，id={}，异常信息：{}", id, e.getMessage(), e);
            throw new RuntimeException("标记通知为已读失败：" + e.getMessage(), e);
        } catch (Exception e) {
            log.error("标记通知为已读未知异常，id={}，异常信息：{}", id, e.getMessage(), e);
            throw new RuntimeException("标记通知为已读失败，请稍后重试", e);
        }
    }

    /**
     * 校验通知ID
     * <p>
     * 检查通知ID是否为空或无效
     * </p>
     *
     * @param id 通知ID
     * @throws IllegalArgumentException 当通知ID为空或无效时抛出
     */
    private void validateNoticeId(Integer id) {
        if (id == null) {
            log.warn("标记通知为已读参数校验失败：通知ID为null");
            throw new IllegalArgumentException("通知ID不能为空");
        }

        if (id <= 0) {
            log.warn("标记通知为已读参数校验失败：通知ID无效，id={}", id);
            throw new IllegalArgumentException("通知ID必须大于0");
        }
    }

    /**
     * 构建更新条件包装器
     * <p>
     * 根据通知ID构建更新条件，将isRead字段设置为已读状态
     * </p>
     *
     * @param id 通知ID
     * @return 更新条件包装器
     */
    private LambdaUpdateWrapper<LifeNotice> buildUpdateWrapper(Integer id) {
        LambdaUpdateWrapper<LifeNotice> wrapper = new LambdaUpdateWrapper<>();
        wrapper.eq(LifeNotice::getId, id);
        wrapper.set(LifeNotice::getIsRead, IS_READ_READ);

        log.debug("构建更新条件成功，id={}, isRead={}", id, IS_READ_READ);
        return wrapper;
    }

    /**
     * 执行更新操作
     * <p>
     * 调用Mapper执行更新操作，将通知标记为已读
     * </p>
     *
     * @param updateWrapper 更新条件包装器
     * @return 受影响的记录数
     */
    private int executeUpdate(LambdaUpdateWrapper<LifeNotice> updateWrapper) {
        return lifeNoticeMapper.update(null, updateWrapper);
    }

    /**
     * 记录更新结果日志
     * <p>
     * 根据更新结果记录相应级别的日志
     * </p>
     *
     * @param id          通知ID
     * @param affectedRows 受影响的记录数
     */
    private void logUpdateResult(Integer id, int affectedRows) {
        if (affectedRows > 0) {
            log.info("标记通知为已读成功，id={}，受影响记录数={}", id, affectedRows);
        } else {
            log.warn("标记通知为已读未找到匹配记录，id={}，受影响记录数={}，可能是通知不存在或已被删除", id, affectedRows);
        }
    }
}
