package org.jeecg.modules.toolBorrowingRecord.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DateUtil;
import com.alibaba.druid.support.json.JSONUtils;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import kong.unirest.HttpResponse;
import kong.unirest.Unirest;
import lombok.RequiredArgsConstructor;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.util.StringUtil;
import org.apache.shiro.SecurityUtils;
import org.jeecg.common.system.api.ISysBaseAPI;
import org.jeecg.common.system.vo.LoginUser;
import org.jeecg.common.util.DateUtils;
import org.jeecg.modules.api.model.CabinetStocks;
import org.jeecg.modules.apply.entity.ApplyDetails;
import org.jeecg.modules.apply.entity.ApplyRecord;
import org.jeecg.modules.apply.mapper.ApplyDetailsMapper;
import org.jeecg.modules.apply.mapper.ApplyRecordMapper;
import org.jeecg.modules.cabinet.entity.Cabinet;
import org.jeecg.modules.cabinet.mapper.CabinetMapper;
import org.jeecg.modules.message.websocket.WebSocket;
import org.jeecg.modules.regular.entity.RegularDetail;
import org.jeecg.modules.stock.entity.StockLog;
import org.jeecg.modules.stock.mapper.StockLogMapper;
import org.jeecg.modules.system.entity.SysUser;
import org.jeecg.modules.system.mapper.SysUserMapper;
import org.jeecg.modules.system.service.ISysUserService;
import org.jeecg.modules.tool.entity.Tool;
import org.jeecg.modules.tool.mapper.ToolMapper;
import org.jeecg.modules.toolBorrowingRecord.entity.ToolBorrowingRecord;
import org.jeecg.modules.toolBorrowingRecord.entity.ToolIoRecord;
import org.jeecg.modules.toolBorrowingRecord.mapper.ToolBorrowingRecordMapper;
import org.jeecg.modules.toolBorrowingRecord.service.IToolBorrowingRecordService;
import org.jeecg.modules.toolSheet.entity.ToolSheet;
import org.jeecg.modules.toolSheet.mapper.ToolSheetMapper;
import org.jeecg.modules.workOrder.entity.WorkOrder;
import org.jeecg.modules.workOrder.mapper.WorkOrderMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.transaction.annotation.Transactional;

import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

import static org.jeewx.api.core.util.DateUtils.datetimeFormat;

/**
 * @Description: 工器具借用记录
 * @Author: jeecg-boot
 * @Date:   2025-01-15
 * @Version: V1.0
 */
@Service
@RequiredArgsConstructor
public class ToolBorrowingRecordServiceImpl extends ServiceImpl<ToolBorrowingRecordMapper, ToolBorrowingRecord> implements IToolBorrowingRecordService {
    private final ToolMapper toolMapper;
    private final ToolSheetMapper toolSheetMapper;
    private final SysUserMapper sysUserMapper;
    private final CabinetMapper cabinetMapper;
    private final StockLogMapper stockLogMapper;
    @Override
    public <E extends IPage<ToolBorrowingRecord>> E page(E page, Wrapper<ToolBorrowingRecord> queryWrapper) {
        E data = super.page(page, queryWrapper);
        data.getRecords().forEach(item -> {
            ToolSheet toolSheet = toolSheetMapper.selectById(item.getToolId());
            if(toolSheet!=null){
                Tool tool = toolMapper.selectById(toolSheet.getToolId());
                if(tool!=null){
                    item.setToolName(tool.getName() + "(" + tool.getModel() + ")");
                }
            }
        });
        return data;
    }

    @Override
    @Transactional(rollbackFor = RuntimeException.class)
    public boolean save(ToolBorrowingRecord entity) {
        ToolSheet toolSheet = toolSheetMapper.selectById(entity.getToolId());
        if(toolSheet.getNum() < entity.getCount()){
            return false;
        }
//        LoginUser user= (LoginUser) SecurityUtils.getSubject().getPrincipal();
//        entity.setBorrower(user.getRealname());
        entity.setStatus(0);
        entity.setBorrowTime(DateUtil.date());
        if(super.save(entity)){
            toolSheet.setNum(toolSheet.getNum() - entity.getCount());
            if(toolSheetMapper.updateById(toolSheet) > 0){
                StockLog stockLog = new StockLog();
                stockLog.setItem(entity.getToolId());
                stockLog.setQuantity(Double.valueOf(entity.getCount()));
                stockLog.setWorkOrder(entity.getWorkOrder());
                stockLog.setIoType(entity.getStatus());
                stockLog.setType(1);
                return stockLogMapper.insert(stockLog) > 0;
            }
            return false;
        }else{
            throw new RuntimeException();
        }
    }

    @Override
    public List<ToolSheet> queryToolByOrder(String workOrder) throws Exception{
        List<ToolBorrowingRecord> records = baseMapper.selectList(new LambdaQueryWrapper<ToolBorrowingRecord>().eq(ToolBorrowingRecord::getWorkOrder, workOrder));
        if(CollectionUtil.isEmpty(records)){
            return null;
        }
        // 查询工单借用的工具列表，排除没有mac地址的非智能工具
        return toolSheetMapper.selectList(new LambdaQueryWrapper<ToolSheet>()
                .in(ToolSheet::getId,records.stream().map(ToolBorrowingRecord::getToolId).collect(Collectors.toSet())).isNotNull(ToolSheet::getMac));
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public boolean returnTool(String id) throws Exception {
        ToolBorrowingRecord record = baseMapper.selectById(id);
        if(record==null || record.getStatus()!=0){
            throw new Exception("借用状态错误");
        }
        record.setStatus(1);
        record.setReturnTime(DateUtil.date());
        if(baseMapper.updateById(record) > 0){
            ToolSheet toolSheet = toolSheetMapper.selectById(record.getToolId());
            if(toolSheet!=null){
                toolSheet.setNum(toolSheet.getNum() + record.getCount());
                if(toolSheetMapper.updateById(toolSheet) > 0){
                    StockLog stockLog = new StockLog();
                    stockLog.setItem(record.getToolId());
                    stockLog.setQuantity(Double.valueOf(record.getCount()));
                    stockLog.setWorkOrder(record.getWorkOrder());
                    stockLog.setIoType(1);
                    stockLog.setType(1);
                    stockLogMapper.insert(stockLog);
                    return true;
                }else{
                    throw new Exception("工器具台账修改失败");
                }
            }else{
                throw new Exception("未查询到工具台账记录");
            }
        }else{
            throw new Exception("记录修改失败");
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean inOutRecordSync(List<CabinetStocks> records) {
        int count = 0;
        for (CabinetStocks record : records) {
            switch (record.getOpType()) {
                case 0:// 出库操作
                    count += processOutRecord(record);
                    break;
                case 1://若是一条入库记录则需要找到对应的出库记录并更新
                    count += processInRecord(record);
                    break;
                default:
                    // 处理未知操作类型
                    log.error("未知出入库操作类型："+record.getOpType());
                    break;
            }
        }
        return count == records.size();
    }

    @Override
    public List<ToolIoRecord> loadToolRecord(String toolId) throws Exception {
        try{
            Cabinet cabinet = cabinetMapper.selectOne(new LambdaQueryWrapper<Cabinet>());
            HttpResponse<String> response = Unirest.get("http://" + cabinet.getIpAddress() +":" + cabinet.getPort() + "/api/Cabinet/getIoRecord")
                    .queryString("toolId", toolId)
                    .asString();
            String data = response.getBody();
            JSONObject jsonObject = JSONObject.parseObject(data);
            if(jsonObject.getInteger("code") == 200)
            {
                List<ToolIoRecord> records = jsonObject.getJSONArray("data").toJavaList(ToolIoRecord.class);
                records.forEach(record -> {
                    record.setHasOrder(StringUtils.isNotBlank(record.getWorkOrder()));
                });
                return records;
            }else{
                throw new Exception("数据查询失败");
            }
        }catch (Exception e){
            throw e;
        }

    }

    @Autowired
    private ISysBaseAPI baseAPI;
    @Autowired
    private WebSocket webSocket;
    @Autowired
    private ISysUserService userService;
    /**
     * 处理出库操作
     */
    private int processOutRecord(CabinetStocks record) {
        // 查询基础台账信息
        ToolSheet toolSheet = toolSheetMapper.selectById(record.getToolId());
        if (toolSheet == null || toolSheet.getNum() < 1) {
            return 0;// 台账不存在或库存不足
        }
        //查询工具信息
        Tool tool = toolMapper.selectById(toolSheet.getToolId());
        if(tool.getCheckRequire().equals("1") &&
                (toolSheet.getLastCheckDate() == null ||
                        DateUtil.betweenDay(toolSheet.getLastCheckDate(), new Date(), true) > 0)) {
            JSONObject msg = new JSONObject();
            msg.put("cmd", "tool");
            msg.put("code", 500);
            msg.put("type", "cabinet");
            msg.put("msg", "非法取用工具:工具未检定！");
            webSocket.pushMessage(JSONUtils.toJSONString(msg));
        }
        //判断是否为工单操作
        if(StringUtils.isEmpty(record.getOrderId())){
            String msgStr = "非法取用工具:";
            //查询用户信息
            SysUser user = userService.getById(record.getUserId());
            if(user != null){
                msgStr = "[" + user.getRealname() + "]" + msgStr;
            }
            msgStr += (tool.getName());
            JSONObject msg = new JSONObject();
            msg.put("cmd", "tool");
            msg.put("code", 500);
            msg.put("type", "cabinet");
            msg.put("msg", msgStr);
            webSocket.pushMessage(JSONUtils.toJSONString(msg));
        }
        // 创建借用记录
        ToolBorrowingRecord borrowingRecord = convertToToolBorrowingRecord(record);
//        borrowingRecord.setBorrower(record.getUserId());
        // 保存借用记录并更新台账
        if (super.save(borrowingRecord)) {
            toolSheet.setNum(toolSheet.getNum() - 1);
            if (toolSheetMapper.updateById(toolSheet) > 0) {
                StockLog stockLog = new StockLog();
                stockLog.setItem(record.getToolId());
                stockLog.setQuantity(1.0);
                stockLog.setWorkOrder(record.getOrderId());
                stockLog.setIoType(0);
                stockLog.setType(1);
                stockLog.setOperator(record.getUserId());
                stockLog.setCreateTime(new Date());
                stockLogMapper.insert(stockLog);
                return 1;
            }
        }
        return 0;
    }

    /**
     * 处理入库操作
     */
    private int processInRecord(CabinetStocks record) {
        //根据toolId的唯一性和业务特性，可以找到唯一一条处于“借用中”状态借用记录
        ToolBorrowingRecord borrowingRecord = baseMapper.selectOne(new LambdaQueryWrapper<ToolBorrowingRecord>()
                .eq(ToolBorrowingRecord::getToolId, record.getToolId())
                .eq(ToolBorrowingRecord::getStatus, 0) // 状态为“借用中”
                .last("LIMIT 1"));
        // 如果没有找到借用记录，则创建一条新的借用记录
        if (borrowingRecord == null) {
            borrowingRecord = convertToToolBorrowingRecord(record);
            if (!super.save(borrowingRecord)) {
                return 0; // 保存失败
            }
        } else {
            // 更新借用记录为“归还”状态
            borrowingRecord.setStatus(1); // 归还
            borrowingRecord.setReturnTime(DateUtils.str2Date(record.getOpTime(), datetimeFormat));
            if (baseMapper.updateById(borrowingRecord) <= 0) {
                return 0; // 更新失败
            }
        }

        // 更新台账
        if(updateToolSheet(record.getToolId())){
            StockLog stockLog = new StockLog();
            stockLog.setItem(record.getToolId());
            stockLog.setQuantity(1.0);
            stockLog.setWorkOrder(record.getOrderId());
            stockLog.setIoType(1);
            stockLog.setType(1);
            stockLog.setOperator(record.getUserId());
            stockLog.setCreateTime(new Date());
            stockLogMapper.insert(stockLog);
            return 1;
        };
        return 0;
    }
    /**
     * 更新台账
     *
     * @param toolId 工具ID
     * @return 是否更新成功
     */
    private boolean updateToolSheet(String toolId) {
        ToolSheet toolSheet = toolSheetMapper.selectById(toolId);
        if (toolSheet == null) {
            return false; // 台账不存在
        }
        toolSheet.setNum(toolSheet.getNum() + 1);
        return toolSheetMapper.updateById(toolSheet) > 0;
    }
    private ToolBorrowingRecord convertToToolBorrowingRecord(CabinetStocks record) {
        // 创建借用记录
        ToolBorrowingRecord borrowingRecord = new ToolBorrowingRecord();
        borrowingRecord.setToolId(record.getToolId());
        borrowingRecord.setCount(1); // 数量默认为1
        borrowingRecord.setStatus(record.getOpType()==0?0:1); // 0借出1入库
        borrowingRecord.setWorkOrder(record.getOrderId());
        // 查询用户信息
        SysUser user = sysUserMapper.selectById(record.getUserId());
        if (user == null) {
            log.error("同步工具出入库记录失败，未找到对应的用户："+ JSON.toJSONString(record));
            throw new RuntimeException();
        }
        borrowingRecord.setBorrower(record.getUserId());
        borrowingRecord.setBorrowTime(DateUtils.str2Date(record.getOpTime(), datetimeFormat));
        return borrowingRecord;
    }

}
