package org.dromara.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import lombok.RequiredArgsConstructor;
import org.apache.commons.lang3.ObjectUtils;
import org.dromara.common.core.domain.R;
import org.dromara.common.core.utils.MapstructUtils;
import org.dromara.common.core.utils.StringUtils;
import org.dromara.common.mybatis.core.page.PageQuery;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.common.redis.utils.RedisUtils;
import org.dromara.domain.propertyRepair.PropertyRepair;
import org.dromara.domain.propertyRepair.bo.PropertyRepairBo;
import org.dromara.domain.propertyRepair.vo.PropertyRepairVo;
import org.dromara.domain.staffManage.StaffManage;
import org.dromara.mapper.PropertyRepairMapper;
import org.dromara.mapper.StaffManageMapper;
import org.dromara.service.IPropertyRepairService;
import org.dromara.utils.DateUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;

import static org.dromara.common.core.constant.Constants.*;
import static org.dromara.common.satoken.utils.LoginHelper.getUserId;

/**
 * 物业报修Service业务层处理
 *
 * @author boman
 * @date 2025-04-11
 */
@RequiredArgsConstructor
@Service
public class PropertyRepairServiceImpl implements IPropertyRepairService {

    private final PropertyRepairMapper baseMapper;
    private final StaffManageMapper staffManageMapper;

    /**
     * 查询物业报修
     *
     * @param repairId 主键
     * @return 物业报修
     */
    @Override
    public PropertyRepairVo queryById(Long repairId) {
        return baseMapper.selectVoById(repairId);
    }

    /**
     * 分页查询物业报修列表
     *
     * @param bo        查询条件
     * @param pageQuery 分页参数
     * @return 物业报修分页列表
     */
    @Override
    public TableDataInfo<PropertyRepairVo> queryPageList(PropertyRepairBo bo, PageQuery pageQuery) {
        LambdaQueryWrapper<PropertyRepair> lqw = buildQueryWrapper(bo);
        Page<PropertyRepairVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
        return TableDataInfo.build(result);
    }

    /**
     * 查询符合条件的物业报修列表
     *
     * @param bo 查询条件
     * @return 物业报修列表
     */
    @Override
    public List<PropertyRepairVo> queryList(PropertyRepairBo bo) {
        LambdaQueryWrapper<PropertyRepair> lqw = buildQueryWrapper(bo);
        return baseMapper.selectVoList(lqw);
    }

    private LambdaQueryWrapper<PropertyRepair> buildQueryWrapper(PropertyRepairBo bo) {
        Map<String, Object> params = bo.getParams();
        LambdaQueryWrapper<PropertyRepair> lqw = Wrappers.lambdaQuery();
        lqw.orderByAsc(PropertyRepair::getRepairId);
        lqw.eq(bo.getPortalId() != null, PropertyRepair::getPortalId, bo.getPortalId());
        lqw.eq(StringUtils.isNotBlank(bo.getHouseAddress()), PropertyRepair::getHouseAddress, bo.getHouseAddress());
        lqw.eq(bo.getRepairTime() != null, PropertyRepair::getRepairTime, bo.getRepairTime());
        lqw.eq(bo.getUserId() != null, PropertyRepair::getUserId, bo.getUserId());
        lqw.eq(StringUtils.isNotBlank(bo.getPhoneNumber()), PropertyRepair::getPhoneNumber, bo.getPhoneNumber());
        lqw.eq(StringUtils.isNotBlank(bo.getRepairTitle()), PropertyRepair::getRepairTitle, bo.getRepairTitle());
        lqw.eq(StringUtils.isNotBlank(bo.getMaintenanceCategory()), PropertyRepair::getMaintenanceCategory, bo.getMaintenanceCategory());
        lqw.eq(StringUtils.isNotBlank(bo.getRepairDetails()), PropertyRepair::getRepairDetails, bo.getRepairDetails());
        lqw.eq(StringUtils.isNotBlank(bo.getRepairImages()), PropertyRepair::getRepairImages, bo.getRepairImages());
        lqw.eq(StringUtils.isNotBlank(bo.getRepairStatus()), PropertyRepair::getRepairStatus, bo.getRepairStatus());
        lqw.like(StringUtils.isNotBlank(bo.getStaffName()), PropertyRepair::getStaffName, bo.getStaffName());
        lqw.eq(bo.getStaffId() != null, PropertyRepair::getStaffId, bo.getStaffId());
        lqw.eq(StringUtils.isNotBlank(bo.getStaffPhone()), PropertyRepair::getStaffPhone, bo.getStaffPhone());
        lqw.eq(bo.getVisitTime() != null, PropertyRepair::getVisitTime, bo.getVisitTime());
        lqw.eq(StringUtils.isNotBlank(bo.getVisitPhoto()), PropertyRepair::getVisitPhoto, bo.getVisitPhoto());
        lqw.eq(bo.getCompletionTime() != null, PropertyRepair::getCompletionTime, bo.getCompletionTime());
        lqw.eq(StringUtils.isNotBlank(bo.getCompletionPhoto()), PropertyRepair::getCompletionPhoto, bo.getCompletionPhoto());
        lqw.eq(StringUtils.isNotBlank(bo.getRepairCompletionDetails()), PropertyRepair::getRepairCompletionDetails, bo.getRepairCompletionDetails());
        return lqw;
    }

    /**
     * 新增物业报修
     *
     * @param bo 物业报修
     * @return 是否新增成功
     */
    @Override
    public Boolean insertByBo(PropertyRepairBo bo) {
        PropertyRepair add = MapstructUtils.convert(bo, PropertyRepair.class);
        validEntityBeforeSave(add);
        Long userId = getUserId();
        add.setUserId(userId);
        boolean flag = baseMapper.insert(add) > 0;
        if (flag) {
            bo.setRepairId(add.getRepairId());
            String userRepairKey = PROPERTY_REPAIR_NO + userId;
            //往redis中新增 个人 物业未完成的报修数量 app统计使用
            Object userNum = RedisUtils.getCacheObject(userRepairKey);
            if (ObjectUtils.isNotEmpty(userNum)) {
                RedisUtils.setCacheObject(userRepairKey, (int) userNum + 1);
            } else {
                RedisUtils.setCacheObject(userRepairKey, 1);
            }
            //往redis中新增 总数 物业未完成的报修数量 app统计使用
            Object allNum = RedisUtils.getCacheObject(PROPERTY_REPAIR_NO_ALL);
            if (ObjectUtils.isNotEmpty(allNum)) {
                RedisUtils.setCacheObject(PROPERTY_REPAIR_NO_ALL, (int) allNum + 1);
            } else {
                RedisUtils.setCacheObject(PROPERTY_REPAIR_NO_ALL, 1);
            }
        }
        return flag;
    }

    /**
     * 修改物业报修
     *
     * @param bo 物业报修
     * @return 是否修改成功
     */
    @Override
    public Boolean updateByBo(PropertyRepairBo bo) {
        PropertyRepair update = MapstructUtils.convert(bo, PropertyRepair.class);
        validEntityBeforeSave(update);
        Long userId = getUserId();
        String repairStatus = update.getRepairStatus();
        if (FOR.equals(repairStatus)) {
            //判断如果维修完成，把维修人员的状态改成空闲
            StaffManage staffManage = new StaffManage();
            staffManage.setStaffId(update.getStaffId());
            staffManage.setStatus(ONE);
            staffManageMapper.updateById(staffManage);
            String userRepairKey = PROPERTY_REPAIR_NO + userId;
            //往redis中新增 个人 物业未完成的报修数量 app统计使用
            Object userNum = RedisUtils.getCacheObject(userRepairKey);
            if (ObjectUtils.isNotEmpty(userNum)) {
                RedisUtils.setCacheObject(userRepairKey, Math.max((int) userNum - 1, 0));
            } else {
                RedisUtils.setCacheObject(userRepairKey, 0);
            }
            //往redis中新增 总数 物业未完成的报修数量 app统计使用
            Object allNum = RedisUtils.getCacheObject(PROPERTY_REPAIR_NO_ALL);
            if (ObjectUtils.isNotEmpty(allNum)) {
                RedisUtils.setCacheObject(PROPERTY_REPAIR_NO_ALL, Math.max((int) allNum - 1, 0));
            } else {
                RedisUtils.setCacheObject(PROPERTY_REPAIR_NO_ALL, 0);
            }
        }

        return baseMapper.updateById(update) > 0;
    }

    /**
     * 保存前的数据校验
     */
    private void validEntityBeforeSave(PropertyRepair entity) {
        //TODO 做一些数据校验,如唯一约束
    }

    /**
     * 校验并批量删除物业报修信息
     *
     * @param ids     待删除的主键集合
     * @param isValid 是否进行有效性校验
     * @return 是否删除成功
     */
    @Override
    public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
        if (isValid) {
            //TODO 做一些业务上的校验,判断是否需要校验
        }
        return baseMapper.deleteByIds(ids) > 0;
    }

    /**
     * 指派物业报修人员
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public R<Void> assign(PropertyRepair propertyRepair) {
        Long staffId = propertyRepair.getStaffId();
        StaffManage staffManageOld = staffManageMapper.selectById(staffId);
        if (TWO.equals(staffManageOld.getStatus())) {
            return R.fail("当前人员处于不在空闲状态无法指派");
        }
        //报修ID/维修人员姓名/维修人员ID/维修人员手机号
        //指派后修改该物业报修表的状态的
        propertyRepair.setRepairStatus(TWO);
        boolean flag = baseMapper.updateById(propertyRepair) > 0;
        //int i = baseMapper.updateById(propertyRepair);
        //修改维修人员的状态
        if (flag) {
            StaffManage staffManage = new StaffManage();
            staffManage.setStaffId(propertyRepair.getStaffId());
            staffManage.setStatus(TWO);
            staffManageMapper.updateById(staffManage);
        }
        return R.ok();
    }

    /**
     * 物业保修一周统计（当前时间往前推7天）
     */
    @Override
    public Map<String, Object> statisticsQx() {
        Map<String, Object> mapList = new HashMap<>();
        List<String> weekDays = DateUtils.getPreviousSevenDays(DateUtils.YYYY_MM_DD);
        String starTime = weekDays.get(0);
        String endTime = weekDays.get(weekDays.size() - 1);
        mapList.put("x", weekDays);
        //查询两个日期内的保修数据
        List<PropertyRepair> propertyRepairs = baseMapper.selectPropertyRepairListByTime(starTime, endTime);
        List<Integer> numList = new ArrayList<>();
        for (int i = 0; i < weekDays.size(); i++) {
            int num = 0;
            for (PropertyRepair propertyRepair : propertyRepairs) {
                String day = DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD, propertyRepair.getRepairTime());
                if (day.equals(weekDays.get(i))) {
                    num++;
                }
            }
            numList.add(num);
        }
        mapList.put("y", numList);
        return mapList;
    }
}
