package com.srs.dormitory.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.srs.common.core.domain.AjaxResult;
import com.srs.common.core.domain.entity.SysUser;
import com.srs.common.core.redis.RedisCache;
import com.srs.common.utils.SecurityUtils;
import com.srs.common.utils.uuid.UUID;
import com.srs.comprehensive.domain.SrsStudent;
import com.srs.comprehensive.service.ISrsStudentService;
import com.srs.dormitory.domain.*;
import com.srs.dormitory.domain.Dto.*;
import com.srs.dormitory.domain.Vo.PhotoVO;
import com.srs.dormitory.domain.Vo.RepairInfoVo;
import com.srs.dormitory.domain.Vo.RepairListVo;
import com.srs.dormitory.mapper.DmsRepairRecordsMapper;
import com.srs.dormitory.service.*;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.srs.dormitory.utils.BeanCopyUtils;
import com.srs.system.service.ISysDeptService;
import com.srs.system.service.ISysUserService;
import lombok.AllArgsConstructor;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;

import java.time.LocalDateTime;
import java.util.List;
import java.util.Map;
import java.util.Set;

import static com.srs.common.utils.PageUtils.startPage;

/**
 * <p>
 * 维修记录表 服务实现类
 * </p>
 *
 * @author 猪油骨
 * @since 2023-08-04
 */
@Service
//@RequiredArgsConstructor(onConstructor = @__(@Autowired))
public class IDmsRepairRecordsServiceImpl extends ServiceImpl<DmsRepairRecordsMapper, DmsRepairRecords> implements IDmsRepairRecordsService {
    @Autowired
    private  IDmsPhotosService photosService;
    @Autowired
    private  IDmsRepairStatusService statusService;
    @Autowired
    private  RedisCache redisCache;
    @Autowired
    private  ISrsStudentService studentService;
    @Autowired
    private  IDmsDormitoryService dormitoryService;
    @Autowired
    private  IDmsDormitoryUnitService unitService;
    @Autowired
    private  IDmsDormitoryBuildingService buildingService;
    @Autowired
    private  ISysUserService userService;


    @Override
    @Transactional
    public AjaxResult addRepair(AddRepairDto addRepairDto) {
        addRepairDto.setStuNo(SecurityUtils.getUsername());
        DmsRepairRecords records = BeanCopyUtils.copyBean(addRepairDto, DmsRepairRecords.class);
        records.setStatus("0");
        records.setRepairNumber(UUID.randomUUID().toString());
        int insert = baseMapper.insert(records);
        if (insert == 0) throw new RuntimeException("申请失败");

        addRepairDto.getPhotos().forEach(photo -> {
            DmsPhotos dmsPhotos = new DmsPhotos();
            dmsPhotos.setRepairRecordId(records.getId());
            dmsPhotos.setUrl(photo);
            boolean save = photosService.save(dmsPhotos);
            if (!save) throw new RuntimeException("申请失败：保存照片链接时出错");
        });


        DmsRepairStatus dmsRepairStatus = new DmsRepairStatus();
        dmsRepairStatus.setRepairRecordId(records.getId());
        dmsRepairStatus.setStatus("已提交申请，等待管理员审核");
        boolean save = statusService.save(dmsRepairStatus);
        if (!save) throw new RuntimeException("操作失败,请稍后再试");
        return AjaxResult.success("已提交申请，等待管理员审核");
    }


    @Override
    @Transactional
    public AjaxResult audit(AuditDto auditDto) {

        DmsRepairRecords records = baseMapper.selectById(auditDto.getId());
        Assert.isTrue(records != null, "该订单不存在，请重新选择");
        if (!records.getStatus().equals("0") && !records.getStatus().equals("-2") && !records.getStatus().equals("-4"))
            throw new RuntimeException("审核失败：该订单已审核");

        if (records.getStatus().equals("-4")) {
            if (auditDto.getStatus().equals("1")) {
                auditDto.setStatus("-1");
            } else if (auditDto.getStatus().equals("-3")) {
                auditDto.setStatus("1");
            }
        }

        records = BeanCopyUtils.copyBean(auditDto, DmsRepairRecords.class);

        records.setAuditors(SecurityUtils.getUsername());

        baseMapper.updateById(records);
        DmsRepairStatus status = new DmsRepairStatus();
        switch (records.getStatus()) {
            case "1":
                status.setStatus("已分配师傅上门维修");
                break;
            case "-3":
                status.setStatus("审核不通过");
                break;
            case "-1":
                status.setStatus("已取消");
                break;
        }
        status.setRepairRecordId(records.getId());
        boolean save = statusService.save(status);
        if (!save) throw new RuntimeException("操作失败,请稍后再试");
        return AjaxResult.success();
    }


    @Override
    @Transactional
    public AjaxResult repair(RepairDto dto) {

        DmsRepairRecords records = baseMapper.selectById(dto.getId());
        if (records == null || !records.getTechName().equals(SecurityUtils.getUsername()) || !records.getStatus().equals("1"))
            return AjaxResult.error();

        records = BeanCopyUtils.copyBean(dto, DmsRepairRecords.class);

        if (!dto.getStatus().equals("-2")) records.setFixTime(LocalDateTime.now());
        boolean isAppraise = redisCache.getCacheObject("isAppraise");
        if (isAppraise && dto.getStatus().equals("2")) records.setStatus("3");
        boolean update = updateById(records);

        if (!update) throw new RuntimeException("操作失败,请稍后再试");

        DmsRepairStatus status = new DmsRepairStatus();
        status.setRepairRecordId(records.getId());

        switch (records.getStatus()) {
            case "3":
                status.setStatus("维修成功，等待评价");
                break;
            case "2":
                status.setStatus("维修成功");
                break;
            case "-2":
                status.setStatus("维修师傅申请转单");
                break;
        }
        boolean save = statusService.save(status);
        if (!save) throw new RuntimeException("操作失败,请稍后再试");
        return AjaxResult.success(status.getStatus());
    }

    @Override
    @Transactional
    public AjaxResult assess(AssessDto dto) {
        DmsRepairRecords records = getById(dto.getId());
        if (!records.getStuNo().equals(SecurityUtils.getUsername()) || !records.getStatus().equals("3"))
            return AjaxResult.error();
        records = BeanCopyUtils.copyBean(dto, DmsRepairRecords.class);
        records.setStatus("4");
        boolean update = updateById(records);
        if (!update) throw new RuntimeException("评价失败，请稍后再试");
        DmsRepairStatus status = new DmsRepairStatus();
        status.setRepairRecordId(records.getId());
        status.setStatus("已评价");
        boolean save = statusService.save(status);
        if (!save) throw new RuntimeException("评价失败，请稍后再试");
        return AjaxResult.success(status.getStatus());
    }

    @Override
    @Transactional
    public AjaxResult appraise(boolean isAppraise) {
        redisCache.setCacheObject("isAppraise", isAppraise);
        boolean appraise = redisCache.getCacheObject("isAppraise");
        boolean update;
        boolean update1;
        List<DmsRepairRecords> list = list();
        boolean hasStatus2 = list.stream().anyMatch(record -> "2".equals(record.getStatus()));
        boolean hasStatus3 = list.stream().anyMatch(record -> "3".equals(record.getStatus()));
        if (appraise) {

            if (hasStatus2) {
                update = lambdaUpdate()
                        .eq(DmsRepairRecords::getStatus, "2")
                        .set(DmsRepairRecords::getStatus, "3")
                        .update();
                update1 = statusService.lambdaUpdate()
                        .eq(DmsRepairStatus::getStatus, "维修成功")
                        .set(DmsRepairStatus::getStatus, "维修成功，等待评价")
                        .update();
                if (!update || !update1) throw new RuntimeException("开启评价失败");
            }

        } else {
            if (hasStatus3) {
                update = lambdaUpdate()
                        .eq(DmsRepairRecords::getStatus, "3")
                        .set(DmsRepairRecords::getStatus, "2")
                        .update();
                update1 = statusService.lambdaUpdate()
                        .eq(DmsRepairStatus::getStatus, "维修成功，等待评价")
                        .set(DmsRepairStatus::getStatus, "维修成功")
                        .update();
                if (!update || !update1) throw new RuntimeException("关闭评价失败");
            }
        }
        return AjaxResult.success(appraise);
    }

    @Override
    @Transactional
    public AjaxResult cancel(Long id, String reason) {
        DmsRepairRecords records = getById(id);
        DmsRepairStatus status = new DmsRepairStatus();

        if (!records.getStuNo().equals(SecurityUtils.getUsername()))
            return AjaxResult.error();
        if (records.getStatus().equals("0")) {
            records.setStatus("-1");
            records.setReason(reason);
            status.setRepairRecordId(id);
            status.setStatus("已取消");
        } else if (records.getStatus().equals("1")) {
            if (reason == null || reason.equals("")) throw new RuntimeException("通过申请的订单必须填写取消理由");
            records.setStatus("-4");
            records.setReason(reason);
            status.setStatus("等待管理员审核取消订单");
            status.setRepairRecordId(id);
        } else {
            throw new RuntimeException("该订单不可取消");
        }
        boolean update = updateById(records);
        boolean save = statusService.save(status);
        if (!update || !save) throw new RuntimeException("操作失败，请稍后再试");
        return AjaxResult.success(status.getStatus());
    }

    @Override
    public List<RepairListVo> repairList(RepairListVo dto) {
        Object appraise = redisCache.getCacheObject("isAppraise");
        if (appraise == null) {
            redisCache.setCacheObject("isAppraise", false);
        }

        Set<String> permissions = SecurityUtils.getLoginUser().getPermissions();
        boolean contains = permissions.contains("dormitory:records:audit");
        boolean contains1 = permissions.contains("*:*:*");

        QueryWrapper<RepairListVo> wrapper = new QueryWrapper<>();
        if (!contains && !contains1) {
            SrsStudent student = studentService.selectSrsStudentByStuNo(SecurityUtils.getUsername());
            if (student != null) {
                wrapper.eq("rep.stu_no", SecurityUtils.getUsername());
            } else {
                wrapper.eq("rep.tech_name", SecurityUtils.getUsername());
            }
        } else {
            if (dto.getId() != null) wrapper.eq("id", dto.getId());
            if (dto.getRepairNumber() != null) wrapper.eq("repair_number", dto.getRepairNumber());
            if (dto.getStuNo() != null) wrapper.eq("stu.stu_no", dto.getStuNo());
            if (dto.getStuName() != null) wrapper.eq("stu.`name`", dto.getStuName());
        }
        if (dto.getDescription() != null) wrapper.like("description", dto.getDescription());
        if (dto.getStatus() != null) wrapper.eq("rep.`status`", dto.getStatus());
        startPage();
        return baseMapper.selectRepairList(wrapper);
    }

    @Override
    public AjaxResult repairInfo(Long id) {
        DmsRepairRecords records = getById(id);
        if (records == null) {
            return AjaxResult.error();
        }

        RepairInfoVo vo = BeanCopyUtils.copyBean(records, RepairInfoVo.class);
        DmsDormitory dormitory = dormitoryService.getById(vo.getDormId());
        //TODO
//        DmsDormitoryUnit unit = unitService.getById(dormitory.getUnitId());
        DmsDormitoryUnit unit = null;
        DmsDormitoryBuilding building = buildingService.getById(unit.getBuildingId());
        vo.setRoomNo(String.format("%s-%s-%s", building.getName(), unit.getName(), dormitory.getRoomNo()));

        SrsStudent student = studentService.selectSrsStudentByStuNo(vo.getStuNo());
        vo.setStuName(student.getName());

        if (vo.getTechName() != null && !vo.getTechName().equals("")) {
            SysUser user = userService.selectUserByUserName(vo.getTechName());
            vo.setTechName(user.getNickName());
        }

        if (vo.getAuditors() != null && !vo.getAuditors().equals("")) {
            SysUser auditor = userService.selectUserByUserName(vo.getAuditors());
            vo.setAuditors(auditor.getNickName());
        }

        List<DmsPhotos> photos = photosService.lambdaQuery()
                .eq(DmsPhotos::getRepairRecordId, records.getId())
                .list();
        List<PhotoVO> vos = BeanCopyUtils.copyBeanList(photos, PhotoVO.class);
        vo.setPhotos(vos);
        return AjaxResult.success(vo);
    }

    @Override
    @Transactional
    public AjaxResult delete(List<Long> ids) {

        statusService.deleteStatus(ids);
        boolean b = removeBatchByIds(ids);
        if (!b) throw new RuntimeException("删除失败");
        return AjaxResult.success("删除成功");
    }

    @Override
    @Transactional
    public AjaxResult deleteById(Long id) {
        boolean remove = statusService
                .remove(new LambdaQueryWrapper<DmsRepairStatus>()
                        .eq(DmsRepairStatus::getRepairRecordId, id));
        if (!remove) throw new RuntimeException("删除失败");
        boolean b = removeById(id);
        if (!b) throw new RuntimeException("删除失败");
        return AjaxResult.success("删除成功");
    }

    @Override
    public List<Map<String, Object>> getRepairName() {

        return null;
    }
}
