package com.ruoyi.web.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.utils.bean.BeanUtils;
import com.ruoyi.system.mapper.SysUserMapper;
import com.ruoyi.system.service.ISysRoleService;
import com.ruoyi.system.service.ISysUserService;
import com.ruoyi.web.domain.dto.event.EventAddRequest;
import com.ruoyi.web.domain.dto.event.EventEditRequest;
import com.ruoyi.web.domain.dto.event.EventQueryRequest;
import com.ruoyi.web.domain.entity.Event;
import com.ruoyi.web.domain.entity.EventAssign;
import com.ruoyi.web.domain.vo.event.EventVO;
import com.ruoyi.web.mapper.EventAssignMapper;
import com.ruoyi.web.mapper.EventMapper;
import com.ruoyi.web.service.EventService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.Arrays;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

/**
 *
 */
@Service
public class EventServiceImpl extends ServiceImpl<EventMapper, Event>
        implements EventService {

    @Resource
    private EventAssignMapper eventAssignMapper;

    @Resource
    private ISysUserService sysUserService;

    @Resource
    private ISysRoleService sysRoleService;

    @Autowired
    private SysUserMapper sysUserMapper;

    /**
     * 添加事件并分配给对应负责人
     *
     * @param eventAddRequest
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Integer addEvent(EventAddRequest eventAddRequest) {
        if (eventAddRequest == null) {
            throw new ServiceException("请求参数为空");
        }
        try {
            // 转换为实体对象
            Event event = new Event();
            BeanUtil.copyProperties(eventAddRequest, event);
            //数据校验
            validEvent(event, BusinessType.INSERT);

            // 保存到事件表
            this.save(event);

            // 根据事件类型分配负责人
            assignEventToPersons(event.getId(), event.getType());
            return event.getId();
        } catch (Exception e) {
            log.error("添加事件失败", e);
            throw new ServiceException("添加事件失败");
        }
    }

    /**
     * 根据事件类型分配负责人
     *
     * @param eventId   事件ID
     * @param eventType 事件类型
     */
    private void assignEventToPersons(Integer eventId, Integer eventType) {
        // 根据事件类型查找对应的负责人
        List<Integer> personIds = getPersonIdsByEventType(eventType);

        if (personIds.isEmpty()) {
            throw new ServiceException("未找到事件类型对应的负责人");
        }

        Date now = new Date();
        for (Integer personId : personIds) {
            EventAssign eventAssign = new EventAssign();
            eventAssign.setEventId(eventId);
            eventAssign.setPersonId(personId);
            eventAssign.setStatus("0"); // 未完结
            eventAssign.setIsReassign("0"); // 非重新分配
            eventAssign.setCreateTime(now);
            eventAssign.setUpdateTime(now);
            eventAssignMapper.insert(eventAssign);
        }
    }

    /**
     * 根据事件类型获取负责人ID列表
     *
     * @param eventType 事件类型
     * @return 负责人ID列表
     */
    private List<Integer> getPersonIdsByEventType(Integer eventType) {
        // 约定基于角色来选择负责人：通用命名：event_type_{n}
        // 角色：event_type_0 -> 矛盾纠纷类 、 event_type_2 -> 消防隐患类
        String key = "event_type_" + eventType;

        // 使用专门的方法查询用户ID，避免数据权限问题
        List<String> roleKeys = Arrays.asList(key);
        List<Long> userIds = sysUserService.selectUserIdsByRoleKeysForEvent(roleKeys);

        List<Integer> matchedUserIds = userIds.stream()
                .map(Long::intValue)
                .distinct()
                .collect(Collectors.toList());

        // 同时包含超级管理员（user_id = 1）
        if (!matchedUserIds.contains(1)) {
            matchedUserIds.add(1);
        }
        return matchedUserIds;
    }

    /**
     * 删除
     *
     * @param ids
     * @return
     */
    @Override
    public boolean deleteEvent(String ids) {
        if (StrUtil.isBlank(ids)) {
            throw new ServiceException("id不能为空或id异常");
        }

        // 2. 分割ID字符串为List<Integer>
        List<Long> idList = Arrays.stream(ids.split(","))
                .map(String::trim)
                .filter(StrUtil::isNotBlank)
                .map(Long::parseLong)
                .collect(Collectors.toList());

        if (idList.isEmpty()) {
            throw new ServiceException("ID格式异常");
        }

        // 3. 构建删除条件
        QueryWrapper<Event> queryWrapper = new QueryWrapper<>();
        queryWrapper.in("id", idList);

        // 4. 执行删除（返回是否删除成功）
        return remove(queryWrapper);

    }

    /**
     * 编辑
     *
     * @param eventEditRequest
     */
    @Override
    public void editEvent(EventEditRequest eventEditRequest) {
        // 判断是否存在
        Integer id = eventEditRequest.getId();
        Event oldEvent = this.getById(id);
        if (oldEvent == null) {
            throw new ServiceException("没有找到事件");
        }
        Event event = new Event();
        BeanUtil.copyProperties(eventEditRequest, event);
        event.setUpdateTime(new Date());
        // 数据校验
        validEvent(event, BusinessType.UPDATE);

        // 操作数据库
        boolean result = this.updateById(event);
        if (!result) {
            throw new ServiceException("修改事件操作失败");
        }
    }

    /**
     * 校验数据
     *
     * @param event
     */
    public void validEvent(Event event, BusinessType type) {
        if (ObjectUtil.isEmpty(event)) {
            throw new ServiceException("数据为空");
        }
        // 从对象中取值
        Integer id = event.getId();
        Date occurTime = event.getOccurTime();
        Integer eventType = event.getType();
        String location = event.getLocation();
        String description = event.getDescription();
        String photoUrl = event.getPhotoUrl();
        String status = event.getStatus();
        Integer submitterId = event.getSubmitterId();
        String processResult = event.getProcessResult();
        Date processTime = event.getProcessTime();


        // 添加id无需校验，修改时，id 不能为空
        if (type != BusinessType.INSERT && ObjectUtil.isEmpty(id)) {
            throw new ServiceException("id不能为空");
        }
        if (ObjectUtil.isEmpty(occurTime)) {
            throw new ServiceException("事件时间不能为空");
        }
        if (ObjectUtil.isEmpty(eventType)) {
            throw new ServiceException("事件类别不能为空");
        }
        if (StrUtil.isBlank(location)) {
            throw new ServiceException("事件地点不能为空");
        }
        if (ObjectUtil.isEmpty(submitterId)) {
            throw new ServiceException("填报人不能为空");
        }
    }

    /**
     * 根据id查询
     *
     * @param id
     * @return
     */
    @Override
    public EventVO getEventById(int id) {
        if (id <= 0) {
            throw new ServiceException("id不能为空或id异常");
        }
        // 获取登录用户id
        Long userId = SecurityUtils.getUserId();
        Event event = new Event();
        // 若不是管理员 指定查询的 负责人id 为当前登录用户id (负责人只能查询自己的事件)
        if (SecurityUtils.isAdmin(userId)) {
            // 管理员查询
            event = this.getById(id);
        } else {
            // 负责人查询
            QueryWrapper<Event> wrapper = new QueryWrapper<>();
            wrapper.eq("id", id)
                    .exists("SELECT 1 FROM event_assign ea WHERE ea.event_id = event.id AND ea.person_id = " + userId);
            event = this.getOne(wrapper);
        }
        return getEventVO(event);
    }

    /**
     * 获取事件包装类
     *
     * @param event
     * @return
     */
    @Override
    public EventVO getEventVO(Event event) {
        if (ObjectUtil.isEmpty(event)) {
            throw new ServiceException("请求参数不存在");
        }
        EventVO eventVO = new EventVO();
        BeanUtils.copyProperties(event, eventVO);

        // 查询事件的负责人信息
        QueryWrapper<EventAssign> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("event_id", event.getId());
        // 获取事件分配信息列表
        List<EventAssign> eventAssigns = eventAssignMapper.selectList(queryWrapper);
        // 3. 提取负责人ID列表
        List<Integer> userIds = eventAssigns.stream()
                .map(EventAssign::getPersonId)
                .collect(Collectors.toList());

        // 4. 批量查询有效的用户信息
        List<SysUser> chargeUserList = userIds.isEmpty() ?
                Collections.emptyList() :
                sysUserMapper.selectUserListForEvent(userIds);

        // 实际项目中需要根据personId查询用户信息
        eventVO.setChargeUserList(chargeUserList);

        // 5. 查询处理人
//        queryWrapper.eq()

        return eventVO;
    }

    /**
     * 分页获取事件列表
     *
     * @param eventQueryRequest
     * @return
     */
    @Override
    public Page<EventVO> getListEventByPage(EventQueryRequest eventQueryRequest) {
        long current = eventQueryRequest.getPageNum();
        long size = eventQueryRequest.getPageSize();
        // 获取登录用户id
        Long userId = SecurityUtils.getUserId();
        Page<Event> page;
        // 若不是管理员 指定查询的 负责人id 为当前登录用户id (负责人只能查询自己的事件)
        if (SecurityUtils.isAdmin(userId)) {
            // 管理员查询
            page = this.page(new Page<>(current, size),
                    getQueryWrapper(eventQueryRequest, null));
        } else {
            // 负责人查询
            page = this.page(new Page<>(current, size),
                    getQueryWrapper(eventQueryRequest, Math.toIntExact(userId)));
        }
        Page<EventVO> eventVOPage = new Page<>();
        BeanUtils.copyProperties(page, eventVOPage, "records");
        List<EventVO> voList = page.getRecords().stream()
                .map(event -> {
                    EventVO vo = getEventVO(event);
                    return vo;
                })
                .collect(Collectors.toList());
        eventVOPage.setRecords(voList);
        return eventVOPage;
    }


    /**
     * 获取查询条件
     *
     * @param eventQueryRequest
     * @return
     */
    @Override
    public QueryWrapper<Event> getQueryWrapper(EventQueryRequest eventQueryRequest, Integer userId) {
        QueryWrapper<Event> queryWrapper = new QueryWrapper<>();
        if (eventQueryRequest == null) {
            return queryWrapper;
        }

        // 从对象中取值
        Date startTime = eventQueryRequest.getStartTime();
        Date endTime = eventQueryRequest.getEndTime();
        Integer type = eventQueryRequest.getType();
        String location = eventQueryRequest.getLocation();
        String status = eventQueryRequest.getStatus();
        Integer submitterId = eventQueryRequest.getSubmitterId();
        String sortField = eventQueryRequest.getSortField();
        String sortOrder = eventQueryRequest.getSortOrder();

        // 事件类别、事发地点、填报人、状态
        queryWrapper.eq(ObjectUtil.isNotEmpty(type), "type", type);
        queryWrapper.eq(StrUtil.isNotBlank(location), "location", location);
        queryWrapper.eq(StringUtils.isNotBlank(status), "status", status);
        // 修正列名：submitter_id
        queryWrapper.eq(ObjectUtil.isNotEmpty(submitterId), "submitter_id", submitterId);

        // 如果负责人查询，则查询负责人的事件
        if (ObjectUtil.isNotEmpty(userId)) {
            queryWrapper.exists("SELECT 1 FROM event_assign ea WHERE ea.event_id = event.id AND ea.person_id = " + userId);
        }

        // 事发时间范围查询（优先判断范围）
        if (startTime != null && endTime != null) {
            queryWrapper.between("occur_time", startTime, endTime);
        } else if (startTime != null) {
            queryWrapper.ge("occur_time", startTime); // >= 开始日期
        } else if (endTime != null) {
            queryWrapper.le("occur_time", endTime);   // <= 结束日期
        }

        // 排序
        queryWrapper.orderBy(StrUtil.isNotEmpty(sortField), "ascend".equals(sortOrder), sortField);
        return queryWrapper;
    }

    /**
     * 任一负责人处理事件：主表CAS(状态) + 分配表同步
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean handleEvent(Integer eventId, Integer personId, String processResult) {
        if (eventId == null || personId == null) {
            throw new ServiceException("参数不能为空");
        }
        // 1. 事件主表CAS：尝试抢占锁,只能修改状态为 0 的事件
        UpdateWrapper<Event> casUpdate = new UpdateWrapper<>();
        casUpdate.eq("id", eventId)
                .eq("status", "0")
                .set("status", "1")
                .set("process_result", processResult)
                .set("process_time", new Date())
                .set("update_time", new Date());
        int w = this.baseMapper.update(null, casUpdate);

        if (w == 1) {
            // 抢到锁：当前负责人状态 -> 1；其他事件负责人状态 -> 2
            UpdateWrapper<EventAssign> meDone = new UpdateWrapper<>();
            meDone.eq("event_id", eventId)
                    .eq("person_id", personId)
                    .eq("status", "0")
                    .set("status", "1")
                    .set("update_time", new Date());
            eventAssignMapper.update(null, meDone);

            UpdateWrapper<EventAssign> othersDone = new UpdateWrapper<>();
            othersDone.eq("event_id", eventId)
                    .ne("person_id", personId)
                    .eq("status", "0")
                    .set("status", "2")
                    .set("update_time", new Date());
            eventAssignMapper.update(null, othersDone);
            return true;
        } else {
            // 抢锁失败：将当前负责人状态-> 2
            UpdateWrapper<EventAssign> meLose = new UpdateWrapper<>();
            meLose.eq("event_id", eventId)
                    .eq("person_id", personId)
                    .eq("status", "0")
                    .set("status", "2")
                    .set("update_time", new Date());
            eventAssignMapper.update(null, meLose);
            return false;
        }
    }

    /**
     * 再次派发：仅在事件未完结时允许；存在则重置为未完结并标记再派发，不存在则插入
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void reassignEvent(Integer eventId, List<Integer> personIds) {
        if (eventId == null || personIds == null || personIds.isEmpty()) {
            throw new ServiceException("参数不能为空");
        }
        // 校验事件未完结
        Event event = this.getById(eventId);
        if (event == null) {
            throw new ServiceException("事件不存在");
        }
        if (!"0".equals(event.getStatus())) {
            throw new ServiceException("事件已完结，无法再次派发");
        }

        Date now = new Date();
        for (Integer uid : personIds) {
            // 先尝试更新存在的数据
            UpdateWrapper<EventAssign> reset = new UpdateWrapper<>();
            reset.eq("event_id", eventId)
                    .eq("person_id", uid)
                    .set("status", "0")
                    .set("is_reassign", "1")
                    .set("update_time", now);
            int a = eventAssignMapper.update(null, reset);
            // 如果不是原来的事件负责人，添加分配记录
            if (a == 0) {
                // 插入新记录
                EventAssign add = new EventAssign();
                add.setEventId(eventId);
                add.setPersonId(uid);
                add.setStatus("0");
                add.setIsReassign("1");
                add.setCreateTime(now);
                add.setUpdateTime(now);
                eventAssignMapper.insert(add);
            }
        }
    }
}




