package com.repair.controller;


import com.alibaba.fastjson.JSON;
import com.repair.api.RepairConsumablesControllerAPI;
import com.repair.common.utils.*;
import com.repair.model.enumModel.eIsSuper;
import com.repair.model.enumModel.eRecordStatu;
import com.repair.model.enumModel.eSchool;
import com.repair.model.pojo.*;
import com.repair.model.request.MaintenanceConsumeablesRequest;
import com.repair.model.request.insertConsumablesRequest;
import com.repair.model.result.CommonResult;
import com.repair.model.result.PageUtils;
import com.repair.model.vo.ChangeConsumesVo;
import com.repair.model.vo.ChangePriceConsumeVo;
import com.repair.model.vo.ConsumableExcelVo;
import com.repair.model.vo.ConsumablePageVo;
import com.repair.services.*;
import org.apache.poi.ss.usermodel.Workbook;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletResponse;
import java.lang.reflect.InvocationTargetException;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * <p>
 * 前端控制器
 * </p>
 *
 * @author ceshi
 * @since 2023-07-20
 */
@RestController
public class RepairConsumablesController implements RepairConsumablesControllerAPI {

    @Autowired
    private RepairUserService repairUserService;
    @Autowired
    private RepairAdminService repairAdminService;
    @Autowired
    private RepairRecordService repairRecordService;
    @Autowired
    private RepairConsumablesService repairConsumablesService;
    @Autowired
    private RepairTrackRecordService repairTrackRecordService;
    @Autowired
    private RepairSystemMessagesService repairSystemMessagesService;

    /**
     * 新增耗材记录
     *
     * @param rc            耗材记录
     * @param bindingResult 是否为空判断
     * @return
     */
    @Override
    public CommonResult InsertRepairConsumables(RepairConsumables rc, BindingResult bindingResult) {
        if (bindingResult.hasErrors()) {
            String st = paramUtils.getParamError(bindingResult);
            return CommonResult.fail(st);
        }

        int result = repairConsumablesService.insertRepairConsumables(rc);

        return result > 0 ? CommonResult.ok("添加成功") : CommonResult.fail("添加失败");
    }

    /**
     * 根据数据ID更新耗材记录
     *
     * @param rc            耗材记录
     * @param bindingResult 是否为空判断
     * @return
     */
    @Override
    public CommonResult updateRepairConsumablesById(RepairConsumables rc, BindingResult bindingResult) {
        if (bindingResult.hasErrors()) {
            String st = paramUtils.getParamError(bindingResult);
            return CommonResult.fail(st);
        }

        int result = repairConsumablesService.updateRepairConsumables(rc);

        return result > 0 ? CommonResult.ok("修改成功") : CommonResult.fail("修改失败");
    }

    /**
     * 耗材记录分页数据查询
     *
     * @param currentPage 当前页
     * @param pageCount   一页数据条数
     * @param name        查询名称
     * @return
     */
    @Override
    public CommonResult queryPageRepairConsumabless(int currentPage, int pageCount, String name) {
        PageUtils<RepairConsumables> result = repairConsumablesService.queryPageRepairConsumabless(currentPage, pageCount, name);

        return CommonResult.ok(result);
    }

    /**
     * 根据数据ID删除耗材记录
     *
     * @param id 数据ID
     * @return
     */
    @Override
    public CommonResult deleteRepairConsumablesById(int id) {
        RepairConsumables data = repairConsumablesService.getRepairById(id);
        if (data == null) {
            return CommonResult.fail("当前数据不存在，删除失败！");
        }

        int result = repairConsumablesService.deleteRepairConsumablesById(id);

        return result > 0 ? CommonResult.ok("删除成功") : CommonResult.fail("删除失败");
    }

    /**
     * 耗材记录分页数据查询
     *
     * @param currentPage 当前页
     * @param pageCount   一页数据条数
     * @param keyWord     关键字查询
     * @param startTime   起始时间
     * @param endTime     结束时间
     * @return
     */
    @Override
    public CommonResult queryRepairConsumablePageList(int currentPage, int pageCount, String keyWord, String startTime, String endTime) {

        if (startTime != null && endTime != null) {
            try {
                startTime = TimeExchange.getStartOfDayStr(TimeExchange.StringToDate(startTime, "yyyy-MM-dd"));
                endTime = TimeExchange.getEndOfDayStr(TimeExchange.StringToDate(endTime, "yyyy-MM-dd"));
            } catch (Exception e) {
            }
        }

        PageUtils<ConsumablePageVo> result = repairConsumablesService.queryConsumablePageList(currentPage, pageCount, keyWord, startTime, endTime);

        for (ConsumablePageVo data : result.getList()) {
            //校区名称
            data.setSchoolName(eSchool.stringOf(data.getSchoolId()));
            //当返回值小于0时，表示BigDecimal对象小于指定的数值；
            //当返回值等于0时，表示BigDecimal对象等于指定的数值；
            //当返回值大于0时，表示BigDecimal对象大于指定的数值。
            data.setStatu(data.getTotalPrice().compareTo(BigDecimal.ZERO) > 0 ? "有偿" : "无偿");
        }

        return CommonResult.ok(result);
    }

    /**
     * 耗材记录导出
     *
     * @param keyWord   关键字查询
     * @param startTime 起始时间
     * @param endTime   结束时间
     * @param response  文件响应流
     * @throws NoSuchMethodException
     * @throws InstantiationException
     * @throws IllegalAccessException
     * @throws InvocationTargetException
     */
    @Override
    public void downloadRepairConsumableExcel(String keyWord, String startTime, String endTime, HttpServletResponse response) throws NoSuchMethodException, InstantiationException, IllegalAccessException, InvocationTargetException {
        Map<String, String> map = new HashMap<>();
        //表头与键值对的映射关系
        map.put("id", "数据ID");
        map.put("consumeName", "耗材名称");
        map.put("price", "单价(元)");
        map.put("number", "数量");
        map.put("totalPrice", "金额(元)");
        map.put("articleName", "工单");
        map.put("reportTimeStr", "报修时间");
        map.put("updateTimeStr", "维修时间");

        if (startTime != null && endTime != null) {
            try {
                startTime = TimeExchange.getStartOfDayStr(TimeExchange.StringToDate(startTime, "yyyy-MM-dd"));
                endTime = TimeExchange.getEndOfDayStr(TimeExchange.StringToDate(endTime, "yyyy-MM-dd"));
            } catch (Exception e) {
            }
        }
        List<ConsumableExcelVo> datas = repairConsumablesService.queryConsumablePageList(keyWord, startTime, endTime);

        List<String> orderList = new ArrayList<>();
        orderList.add("id");
        orderList.add("consumeName");
        orderList.add("price");
        orderList.add("number");
        orderList.add("totalPrice");
        orderList.add("articleName");
        orderList.add("reportTimeStr");
        orderList.add("updateTimeStr");

        //导出逻辑 这里的list是从导入里面哪来的 map1与map不一样 orderList这里为空
        Workbook workbook = ExcelExportUtil.createWorkbook(datas, map, 1, "耗材记录表", orderList);

        ExcelUtils.excelDownload(workbook, "耗材记录.xlsx", response);
    }

    /**
     * 报价-确认提交
     *
     * @param data          报价耗材数据
     * @param userhead      userhead请求头数据
     * @param bindingResult 是否为空判断
     * @return
     * @throws Exception
     */
    @Override
    @Transactional(rollbackFor = {Exception.class})
    public CommonResult InsertMaintenanceConsumables(MaintenanceConsumeablesRequest data, @RequestHeader("user_head") String userhead, BindingResult bindingResult) throws Exception {
        System.out.println("报价确认提交" + JSON.toJSON(data));

        try {
            if (bindingResult.hasErrors()) {
                String st = paramUtils.getParamError(bindingResult);
                return CommonResult.fail(st);
            }

            if (data.getConsumes().size() <= 0) {
                return CommonResult.fail("无耗材数据，报价失败");
            }

            List<RepairConsumables> rcDatas = new ArrayList<>();
            for (insertConsumablesRequest rc : data.getConsumes()) {
                if (rc.getConsumeId() == null) {
                    return CommonResult.fail("耗材ID不能为空");
                }
                if (rc.getConsumeName() == null) {
                    return CommonResult.fail("耗材名称不能为空");
                }
                if (rc.getNumber() == null || rc.getNumber() <= 0) {
                    return CommonResult.fail("耗材数量不能为空");
                }
                if (rc.getPrice() == null) {
                    return CommonResult.fail("耗材单价不能为空");
                }
                RepairConsumables rcData = new RepairConsumables();
                rcData.setRecordId(data.getRecordId());
                rcData.setArticleId(rc.getArticleId());
                rcData.setConsumeId(rc.getConsumeId());
                rcData.setConsumeName(rc.getConsumeName());
                rcData.setNumber(rc.getNumber());
                rcData.setPrice(rc.getPrice());
                rcData.setTotalPrice(new BigDecimal(rcData.getNumber()).multiply(rcData.getPrice()));
                rcDatas.add(rcData);
            }

            RepairRecord rr = repairRecordService.getRepairById(data.getRecordId());
            if (rr == null) {
                return CommonResult.fail("报修工单不存在，报价失败");
            }

            //判断是否已报价
            if (rr.getPrice() != null) {
                return CommonResult.fail("报修工单已报过价，请勿重复报价");
            }

            if (rr.getMaintenanceState() == eRecordStatu.Finished.getValue()
                    || rr.getMaintenanceState() == eRecordStatu.Canceled.getValue()
                    || rr.getMaintenanceState() == eRecordStatu.Closed.getValue()) {
                return CommonResult.fail("当前报修工单状态发生变化，报价失败");
            }

            boolean result = repairConsumablesService.insertConsumableBatch(rcDatas);

            if (!result) {
                throw new Exception("报价失败！");
            }

            //只有用户支付完了之后，维修师傅才能继续看到这个单子
            rr.setMaintenanceState(eRecordStatu.ToConfirmed.getValue());
            rr.setPrice(data.getTotalPrice());
            int updateRecord = repairRecordService.updateRepairRecord(rr);
            if (updateRecord <= 0) {
                throw new Exception("报价失败！");
            }

            RepairSystemMessages rsm = new RepairSystemMessages();
            rsm.setRecordId(data.getRecordId());
            rsm.setRecipientId(rr.getUserId());
            rsm.setIsRead(0);
            rsm.setContent("工单需要支付" + data.getTotalPrice() + "元，请尽快确认！");
            int insertRsm = repairSystemMessagesService.insertRepairSystemMessages(rsm);
            if (insertRsm <= 0) {
                throw new Exception("报价失败！");
            }

            String userID = AesUtils.decrypt(userhead);
            RepairAdmin operateData = repairAdminService.getRepairById(userID);
            if (operateData == null) {
                throw new Exception("操作人信息不合法，无法进行回复！");
            }

            //发送人
            Integer senderId = 0;//超级管理员用ID为0
            if (!operateData.getIsSuper().equals(eIsSuper.Super.getValue())) {
                RepairUser user = repairUserService.getRepairByCardNumber(operateData.getCardNumber());
                if (user == null) {
                    throw new Exception("管理端账号未与移动端账号绑定，无法进行审核！");
                }
                senderId = user.getId();
            }

            //添加跟踪记录
            RepairTrackRecord rtr = new RepairTrackRecord();
            rtr.setRecordId(data.getRecordId());
            rtr.setMaintenanceState(eRecordStatu.ToConfirmed.getValue());
            rtr.setContent("待确认");
            rtr.setUserId(senderId);
            rtr.setUserZzstr("维修师傅");
            int insertRtr = repairTrackRecordService.insertRepairTrackRecord(rtr);
            if (insertRtr <= 0) {
                throw new Exception("报价失败");
            }
        } catch (Exception e) {
            throw new Exception("报价失败！");
        }

        return CommonResult.ok("报价成功");
    }

    /**
     * 改价-获取耗材记录数据
     *
     * @param recordId 维修单记录ID
     * @return
     */
    @Override
    public CommonResult queryChangePriceConsumables(Integer recordId) {
        RepairRecord rr = repairRecordService.getRepairById(recordId);
        if (rr == null) {
            return CommonResult.fail("维修单已失效，改价失败");
        }

        if (rr.getMaintenanceState() != eRecordStatu.ToLogistics.getValue()) {
            return CommonResult.fail("维修单不是待处理状态，无法进行改价操作");
        }
        ChangePriceConsumeVo result = new ChangePriceConsumeVo();
        result.setRecordId(recordId);
        result.setTotalPrice(rr.getPrice());
        result.setMaintenancerName(rr.getMaintenancerName());
        result.setMaintenancerPhone(rr.getMaintenancerPhone());

        List<ChangeConsumesVo> consumables = repairConsumablesService.repairChangeConsumes(recordId);

        result.setConsumes(consumables);
        return CommonResult.ok(result);
    }

    /**
     * 改价-确认提交
     *
     * @param data          改价耗材数据
     * @param userhead      userhead请求头
     * @param bindingResult 是否为空判断
     * @return
     * @throws Exception
     */
    @Override
    @Transactional(rollbackFor = {Exception.class})
    public CommonResult changeMaintenanceConsumables(MaintenanceConsumeablesRequest data, @RequestHeader("user_head") String userhead, BindingResult bindingResult) throws Exception {
        System.out.println("改价确认提交" + JSON.toJSON(data));

        try {
            if (bindingResult.hasErrors()) {
                String st = paramUtils.getParamError(bindingResult);
                return CommonResult.fail(st);
            }

            if (data.getConsumes().size() <= 0) {
                return CommonResult.fail("无耗材数据，改价失败");
            }

            String userID = AesUtils.decrypt(userhead);
            RepairAdmin operateData = repairAdminService.getRepairById(userID);
            if (operateData == null) {
                //return CommonResult.fail("操作人信息不合法，无法进行回复！");
                throw new Exception("操作人信息不合法，无法进行改价！");
            }

            List<RepairConsumables> rcDatas = new ArrayList<>();
            for (insertConsumablesRequest rc : data.getConsumes()) {
                if (rc.getArticleId() == null) {
                    return CommonResult.fail("报修物品ID不能为空");
                }
                if (rc.getConsumeId() == null) {
                    return CommonResult.fail("耗材ID不能为空");
                }
                if (rc.getConsumeName() == null) {
                    return CommonResult.fail("耗材名称不能为空");
                }
                if (rc.getNumber() == null || rc.getNumber() <= 0) {
                    return CommonResult.fail("耗材数量不能为空");
                }
                if (rc.getPrice() == null) {
                    return CommonResult.fail("耗材单价不能为空");
                }
                RepairConsumables rcData = new RepairConsumables();
                if (rc.getId() != null && rc.getId() > 0) {
                    rcData.setId(rc.getId());
                }
                rcData.setChangeUser(operateData.getUsername());
                rcData.setRecordId(data.getRecordId());
                rcData.setArticleId(rc.getArticleId());
                rcData.setConsumeId(rc.getConsumeId());
                rcData.setConsumeName(rc.getConsumeName());
                rcData.setNumber(rc.getNumber());
                rcData.setPrice(rc.getPrice());
                rcData.setTotalPrice(new BigDecimal(rcData.getNumber()).multiply(rcData.getPrice()));
                rcDatas.add(rcData);
            }
            //获取原有的耗材记录数据
            List<ChangeConsumesVo> oldConsumables = repairConsumablesService.repairChangeConsumes(data.getRecordId());

            RepairRecord rr = repairRecordService.getRepairById(data.getRecordId());
            if (rr == null) {
                return CommonResult.fail("报修工单不存在，改价失败");
            }

            if (rr.getMaintenanceState() == eRecordStatu.Finished.getValue()
                    || rr.getMaintenanceState() == eRecordStatu.Canceled.getValue()
                    || rr.getMaintenanceState() == eRecordStatu.Closed.getValue()) {
                return CommonResult.fail("当前报修工单状态发生变化，改价失败");
            }

            boolean result = repairConsumablesService.saveorUpdateConsumableBatch(rcDatas);

            if (!result) {
                throw new Exception("改价失败！");
            }

            //只有用户支付完了之后，维修师傅才能继续看到这个单子
            rr.setMaintenanceState(eRecordStatu.ToConfirmed.getValue());
            rr.setPrice(data.getTotalPrice());
            int updateRecord = repairRecordService.updateRepairRecord(rr);
            if (updateRecord <= 0) {
                throw new Exception("改价失败！");
            }

            List<Integer> newDatas = rcDatas.stream().map(RepairConsumables::getId).collect(Collectors.toList());
            List<Integer> oldDatas = oldConsumables.stream().map(ChangeConsumesVo::getId).collect(Collectors.toList());
            //oldData集合不在newDatas集合中的内容
            List<Integer> ids = oldDatas.stream().filter(item -> !newDatas.contains(item)).collect(Collectors.toList());

            if (ids.size() > 0) {
                int deleted = repairConsumablesService.deletedConsumableByIds(ids);
                if (deleted <= 0) {
                    throw new Exception("改价失败！");
                }
            }

            //发送人
            Integer senderId = 0;//超级管理员用ID为0
            if (!operateData.getIsSuper().equals(eIsSuper.Super.getValue())) {
                RepairUser user = repairUserService.getRepairByCardNumber(operateData.getCardNumber());
                if (user == null) {
                    //return CommonResult.fail("管理端账号未与移动端账号绑定，无法进行审核！");
                    throw new Exception("管理端账号未与移动端账号绑定，无法进行改价！");
                }
                senderId = user.getId();
            }

            //追踪记录表
            RepairTrackRecord repairTrackRecord = new RepairTrackRecord();
            repairTrackRecord.setRecordId(data.getRecordId());
            repairTrackRecord.setMaintenanceState(eRecordStatu.ToConfirmed.getValue());
            repairTrackRecord.setContent("改价");
            repairTrackRecord.setUserId(senderId);
            repairTrackRecord.setUserZzstr("维修师傅");
            int save = repairTrackRecordService.insertRepairTrackRecord(repairTrackRecord);

            if (save <= 0) {
                throw new Exception("改价失败！");
            }

        } catch (Exception e) {
            throw new Exception("改价失败！");
        }

        return CommonResult.ok("改价成功");
    }
}

