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.enums.BusinessType;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.utils.bean.BeanUtils;
import com.ruoyi.web.domain.dto.event.EventAddRequest;
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.entity.PersonInfo;
import com.ruoyi.web.domain.vo.PersonInfoVO;
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.EventAssignService;
import com.ruoyi.web.service.EventService;
import com.ruoyi.web.service.EventTypeAssigneeService;
import com.ruoyi.web.service.PersonInfoService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.Arrays;
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 PersonInfoService personInfoService;

    @Resource
    private EventAssignService eventAssignService;

    @Resource
    private EventTypeAssigneeService eventTypeAssigneeService;

    /**
     * 添加事件并分配给对应负责人
     *
     * @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);

            // 通过系统用户id 获取对应 人口表id
            Long userId = SecurityUtils.getUserId();
            QueryWrapper<PersonInfo> wrapper = new QueryWrapper<>();
            wrapper.select("id")
                    .eq("user_id",userId);
            List<PersonInfo> personInfoList = personInfoService.list(wrapper);
            if (!personInfoList.isEmpty()) {
                PersonInfo personInfo = personInfoList.get(0);
                event.setSubmitterId(personInfo.getId());
            } else {
                throw new ServiceException("找不到申报人");
            }

            //数据校验
            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) {
        // 根据事件类型查找对应的负责人 id 集合
        List<Integer> userIds = getPersonIdsByEventType(eventType);

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

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


//    /**
//     * 根据事件类型获取负责人列表
//     * @param eventType
//     * @return
//     */
//    @Override
//    public List<PersonInfoVO> getPersonInfoVOByEventType(Integer eventType) {
//        return eventTypeAssigneeService.getListEventPersonInfoVO(eventType);
//    }


    /**
     * 根据事件类型获取负责人系统用户ID列表
     *
     * @param eventType 事件类型
     * @return 负责人ID列表
     */
    private List<Integer> getPersonIdsByEventType(Integer eventType) {
        // 获取负责人列表
        List<PersonInfoVO> listEventPersonInfoVO = eventTypeAssigneeService.getListEventPersonInfoVO(eventType);
        List<Integer> userIds = listEventPersonInfoVO.stream().map(
                personInfoVO -> {
                    return personInfoVO.getUserId();
                }).collect(Collectors.toList());

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


    /**
     * 删除
     *
     * @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);
        // todo 同步删除 分配表 记录

        // 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 事件id
     * @return
     */
    @Override
    public EventVO getEventById(int id) {
        if (id <= 0) {
            throw new ServiceException("id不能为空或id异常");
        }
        // 获取登录用户id
        Long userId = SecurityUtils.getUserId();
        Event 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.user_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::getUserId)
                .collect(Collectors.toList());

        // 4. 批量查询 有效的负责人信息
        List<PersonInfoVO> chargeUserList ;
        if (ObjectUtil.isNotEmpty(userIds)){
            chargeUserList = personInfoService.getPersonInfoVOListByUserIds(userIds);
        }else{
            chargeUserList=null;
        }
        eventVO.setChargeUserList(chargeUserList);

        // 5. 通过填报人id 查询村民姓名
        Integer submitterId = event.getSubmitterId();
        PersonInfo personInfo = personInfoService.getById(submitterId);
        eventVO.setSubmitterName(personInfo.getRealname());

        // 6. 查询处理人
        QueryWrapper<EventAssign> wrapper = new QueryWrapper<>();
        wrapper.select("user_id")
                .eq("event_id", event.getId())
                .eq("status", 1);
        EventAssign eventAssign = eventAssignService.getOne(wrapper);
        if (ObjectUtil.isNotEmpty(eventAssign)){
            // 事件已经处理 有处理人
            Integer userId = eventAssign.getUserId();
            //if (userId == 1) {
            if (SecurityUtils.isAdmin(userId.longValue())) {
                eventVO.setProcessUserName("超级管理员");
            }else{
                QueryWrapper<PersonInfo> queryWrapper2 = new QueryWrapper<>();
                queryWrapper2.select("id", "realname")
                        .eq("user_id", userId);
                PersonInfo processPersonInfo = personInfoService.getOne(queryWrapper2);

                if (processPersonInfo != null) {
                    eventVO.setProcessUserName(processPersonInfo.getRealname());
                } else {
                    eventVO.setProcessUserName(null);
                }
            }
        } else {
            // 事件还未处理 没有处理人
            eventVO.setProcessUserName(null);
        }
        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;
        }

        // 从对象中取值
        String description = eventQueryRequest.getDescription();
        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();

        // 事件描述、事件类别、事发地点、填报人id(人口表id)、状态
        queryWrapper.like(StrUtil.isNotBlank(description), "description", description);
        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.user_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, String processResult,Date processTime) {
        Long userId = SecurityUtils.getUserId();
        if (eventId == null || userId == null) {
            throw new ServiceException("参数不能为空");
        }
        // 1. 事件主表CAS：尝试抢占锁,只能修改状态为 0 的事件
        UpdateWrapper<Event> casUpdate = new UpdateWrapper<>();
        if (ObjectUtil.isEmpty(processTime)){
            processTime = new Date();
        }
        casUpdate.eq("id", eventId)
                .eq("status", "0")
                .set("status", "1")
                .set("process_result", processResult)
                .set("process_time", processTime)
                .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("user_id", userId)
                    .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("user_id", userId)
                    .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("user_id", userId)
                    .eq("status", "0")
                    .set("status", "2")
                    .set("update_time", new Date());
            eventAssignMapper.update(null, meLose);
            return false;
        }
    }

    /**
     * 再次派发：仅在事件未完结时允许；存在则重置为未完结并标记再派发，不存在则插入
     */
    // todo 校验事件类型 与 负责人类型 是否匹配
    @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();
        // 通过人口id 获取 系统用户id
        List<Integer> userIds = personInfoService.getUserIdListByPersonIds(personIds);
        for (Integer uid : userIds) {
            // 先尝试更新存在的数据
            UpdateWrapper<EventAssign> reset = new UpdateWrapper<>();
            reset.eq("event_id", eventId)
                    .eq("user_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.setUserId(uid);
                add.setStatus("0");
                add.setIsReassign("1");
                add.setCreateTime(now);
                add.setUpdateTime(now);
                eventAssignMapper.insert(add);
            }
        }
    }

    @Override
    public Page<Event> pageCunMin(EventQueryRequest eventQueryRequest) {
        long current = eventQueryRequest.getPageNum();
        long size = eventQueryRequest.getPageSize();
        String keyWord = eventQueryRequest.getKeyWord();
        // 获取登录用户id
        Long userId = SecurityUtils.getUserId();
        QueryWrapper<Event> wrapper = new QueryWrapper<Event>().eq("submitter_id", userId);
        if (StringUtils.isNotBlank(keyWord)){
            wrapper.and(i ->  i.like("location",keyWord).or().like("description",keyWord));

        }
       Page<Event>   page = this.page(new Page<>(current, size),
                wrapper );


        return page;
    }
}