package com.shzg.project.unique.service.impl;

import java.util.List;

import com.shzg.common.exception.ServiceException;
import com.shzg.common.utils.DateUtils;
import com.shzg.common.utils.DeptScopeUtils;
import com.shzg.common.utils.SecurityUtils;
import com.shzg.common.utils.StringUtils;
import com.shzg.framework.aspectj.lang.annotation.DataScope;
import com.shzg.project.unique.domain.WornUniqueCodeEvent;
import com.shzg.project.unique.domain.WornUniqueCodeMaterial;
import com.shzg.project.unique.mapper.WornUniqueCodeEventMapper;
import com.shzg.project.unique.mapper.WornUniqueCodeMaterialMapper;
import com.shzg.project.unique.unit.QrCodeUtils;
import com.shzg.project.worn.domain.dto.WornInboundItemDTO;
import com.shzg.project.worn.mapper.WornInboundItemMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.shzg.project.unique.mapper.WornUniqueCodeMapper;
import com.shzg.project.unique.domain.WornUniqueCode;
import com.shzg.project.unique.service.IWornUniqueCodeService;
import org.springframework.transaction.annotation.Transactional;

/**
 * 唯一码管理Service业务层处理
 * 
 * @author shzg
 * @date 2026-03-17
 */
@Service
public class WornUniqueCodeServiceImpl implements IWornUniqueCodeService 
{
    @Autowired
    private WornUniqueCodeMapper wornUniqueCodeMapper;

    @Autowired
    private WornUniqueCodeMaterialMapper materialMapper;

    @Autowired
    private WornUniqueCodeEventMapper eventMapper;
    @Autowired
    private WornInboundItemMapper wornInboundItemMapper;
    /**
     * 查询唯一码管理
     * 
     * @param id 唯一码管理主键
     * @return 唯一码管理
     */
    @Override
    public WornUniqueCode selectWornUniqueCodeById(Long id)
    {
        /* 主表 */
        WornUniqueCode code = wornUniqueCodeMapper.selectWornUniqueCodeById(id);

        if (code == null)
        {
            throw new ServiceException("唯一码不存在");
        }

        /* 数据隔离校验 */
        Long deptId = SecurityUtils.getDeptId();
        if (!SecurityUtils.isAdmin() && !deptId.equals(code.getProjectId()))
        {
            throw new ServiceException("无权限查看该数据");
        }

        /* ================== 查询物料================== */
        WornUniqueCodeMaterial material =
                materialMapper.selectWithMaterialByUniqueCodeId(id);

        code.setMaterial(material);

        /* ================== 查询事件 ================== */
        List<WornUniqueCodeEvent> eventList =
                eventMapper.selectByUniqueCodeId(id);

        code.setEventList(eventList);

        /* ================== 生成二维码 ================== */
        String qrBase64 = QrCodeUtils.generateBase64(String.valueOf(code.getCode()));
        code.setQrCode(qrBase64);

        return code;
    }

    /**
     * 查询唯一码管理列表
     * 
     * @param wornUniqueCode 唯一码管理
     * @return 唯一码管理
     */
    @Override
    public List<WornUniqueCode> selectWornUniqueCodeList(WornUniqueCode wornUniqueCode)
    {
        if (!SecurityUtils.isAdmin())
        {
            wornUniqueCode.setDataScopeDeptIds(DeptScopeUtils.getDeptScope());
        }
        return wornUniqueCodeMapper.selectWornUniqueCodeList(wornUniqueCode);
    }

    /**
     * 新增唯一码管理
     * 
     * @param wornUniqueCode 唯一码管理
     * @return 结果
     */
    /**
     * 新增唯一码管理
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int insertWornUniqueCode(WornUniqueCode wornUniqueCode)
    {
        /* ================== 0️⃣ 参数校验 ================== */
        WornUniqueCodeMaterial material = wornUniqueCode.getMaterial();
        if (material == null)
        {
            throw new RuntimeException("物料信息不能为空");
        }

        /* ================== 1️⃣ 获取当前用户 ================== */
        Long userId = SecurityUtils.getLoginUser().getUser().getUserId();
        Long deptId = SecurityUtils.getLoginUser().getUser().getDeptId();

        wornUniqueCode.setProjectId(deptId);

        /* ================== 2️⃣ 主表 ================== */
        wornUniqueCode.setCreateTime(DateUtils.getNowDate());
        wornUniqueCode.setCreateBy(String.valueOf(userId));
        wornUniqueCode.setIsDelete("0");

        // 🔥 关键修改：根据 billNo 判断状态
        if (wornUniqueCode.getBillNo() != null && !wornUniqueCode.getBillNo().trim().isEmpty())
        {
            wornUniqueCode.setStatus("1"); // 已生成入库单号
            wornUniqueCode.setBillNo(wornUniqueCode.getBillNo());
        }
        else
        {
            wornUniqueCode.setStatus("0"); // 初始化
        }

        // 先占位
        wornUniqueCode.setCode(0);

        wornUniqueCodeMapper.insertWornUniqueCode(wornUniqueCode);

        Long id = wornUniqueCode.getId();
        if (id == null)
        {
            throw new RuntimeException("新增唯一码失败，主键ID未回填");
        }

        /* ================== 3️⃣ 生成 code ================== */
        Integer code = 600000 + id.intValue();

        WornUniqueCode update = new WornUniqueCode();
        update.setId(id);
        update.setCode(code);
        update.setUpdateTime(DateUtils.getNowDate());
        update.setUpdateBy(String.valueOf(userId));

        wornUniqueCodeMapper.updateWornUniqueCode(update);

        /* ================== 4️⃣ 插入物料 ================== */
        material.setUniqueCodeId(id);
        material.setCreateTime(DateUtils.getNowDate());
        material.setCreateBy(String.valueOf(userId));
        material.setIsDelete("0");

        materialMapper.insertWornUniqueCodeMaterial(material);

        /* ================== 5️⃣ 插入事件 ================== */
        WornUniqueCodeEvent event = new WornUniqueCodeEvent();
        event.setUniqueCodeId(id);
        event.setOperatorId(userId);
        event.setCreateTime(DateUtils.getNowDate());
        event.setCreateBy(String.valueOf(userId));
        event.setIsDelete("0");

        // 🔥 关键修改：根据 billNo 判断事件类型
        if (wornUniqueCode.getBillNo() != null && !wornUniqueCode.getBillNo().trim().isEmpty())
        {
            event.setEventType("1");     // 生成入库单号
            event.setEventStatus("1");
            event.setEventDesc("生成入库单号");
            //更新明细表中
            if (material.getMaterialId() == null)
            {
                throw new RuntimeException("物料ID不能为空，无法同步更新明细表唯一码");
            }

            int itemRows = wornInboundItemMapper.updateUniqueCodeByBillNoAndMaterialId(
                    wornUniqueCode.getBillNo(),
                    material.getMaterialId(),
                    code
            );

        }
        else
        {
            event.setEventType("0");     // 唯一码生成
            event.setEventStatus("0");
            event.setEventDesc("唯一码生成");
        }

        eventMapper.insertWornUniqueCodeEvent(event);

        return 1;
    }

    /**
     * 修改唯一码管理
     * 
     * @param wornUniqueCode 唯一码管理
     * @return 结果
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int updateWornUniqueCode(WornUniqueCode wornUniqueCode)
    {
        Long userId = SecurityUtils.getLoginUser().getUser().getUserId();

        wornUniqueCode.setUpdateTime(DateUtils.getNowDate());
        wornUniqueCode.setUpdateBy(String.valueOf(userId));

        // 1️⃣ 更新主表
        wornUniqueCodeMapper.updateWornUniqueCode(wornUniqueCode);

        // 2️⃣ 更新物料
        if (wornUniqueCode.getMaterial() != null)
        {
            WornUniqueCodeMaterial material = wornUniqueCode.getMaterial();
            material.setUpdateTime(DateUtils.getNowDate());
            material.setUpdateBy(String.valueOf(userId));

            materialMapper.updateWornUniqueCodeMaterial(material);
        }

        return 1;
    }
    /**
     * 批量删除唯一码管理
     * 
     * @param ids 需要删除的唯一码管理主键
     * @return 结果
     */
    @Override
    public int deleteWornUniqueCodeByIds(Long[] ids)
    {
        return wornUniqueCodeMapper.deleteWornUniqueCodeByIds(ids);
    }

    @Override
    public List<WornInboundItemDTO> selectMaterialInfoByCode(Integer code)
    {
        if (code == null)
        {
            throw new RuntimeException("唯一码编号不能为空");
        }
        List<WornInboundItemDTO> dto = wornUniqueCodeMapper.selectMaterialInfoByCode(code);

        if (dto != null && dto.size() >= 0){
            for (WornInboundItemDTO item : dto){
                if (StringUtils.isNotEmpty(item.getStatus()) && !"0".equals(item.getStatus())){
                    throw new RuntimeException("唯一码编号已经被使用");
                }
            }

        }
        return dto;
    }

    @Override
    public List<WornInboundItemDTO> selectMaterialInfoForOutbound(Integer code, List<Integer> existList)
    {
        /* ================== 1. 参数校验 ================== */
        if (code == null)
        {
            throw new RuntimeException("唯一码不能为空");
        }
        if (existList != null && existList.contains(code))
        {
            throw new RuntimeException("该唯一码已扫描，请勿重复添加");
        }
        /* ================== 2. 查询物料信息 ================== */
        List<WornInboundItemDTO> dto = wornUniqueCodeMapper.selectMaterialInfoByCode(code);

        if (dto == null || dto.isEmpty())
        {
            throw new RuntimeException("未查询到对应物料信息");
        }

        /* ================== 3. 状态校验 ================== */
        for (WornInboundItemDTO item : dto)
        {
            String status = item.getStatus();

            if (StringUtils.isEmpty(status))
            {
                throw new RuntimeException("唯一码状态异常");
            }

            // ❗只允许已入库（2）出库
            if (!"2".equals(status)){
                if ("0".equals(status)){
                    throw new RuntimeException("唯一码未入库，不能出库");
                }else if ("1".equals(status)){
                    throw new RuntimeException("唯一码仅生成入库单，尚未入库");
                }else if ("3".equals(status)){
                    throw new RuntimeException("唯一码已生成出库单，请勿重复操作");
                }else if ("4".equals(status)){
                    throw new RuntimeException("唯一码已完成出库");
                }else if ("9".equals(status)){
                    throw new RuntimeException("唯一码已作废");
                }else{
                    throw new RuntimeException("唯一码状态异常：" + status);
                }
            }
        }

        return dto;
    }
}
