package com.ruoyi.asset.service.impl;

import java.util.Arrays;
import java.util.List;
import com.ruoyi.asset.constant.RfidBindStatus;
import com.ruoyi.asset.constant.RfidTagStatus;
import com.ruoyi.asset.domain.RfidBindingContext;
import com.ruoyi.asset.service.IAssetLifecycleService;
import com.ruoyi.asset.service.IRfidBindingService;
import com.ruoyi.common.constant.UserConstants;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import com.ruoyi.asset.mapper.AmsRfidTagMapper;
import com.ruoyi.asset.domain.AmsRfidTag;
import com.ruoyi.asset.service.IAmsRfidTagService;
import com.ruoyi.common.core.text.Convert;

/**
 * RFID标签Service业务层处理
 * 
 * @author Yangk
 * @date 2026-06-05
 */
@Service
public class AmsRfidTagServiceImpl implements IAmsRfidTagService 
{
    private static final String DEL_FLAG_NORMAL = "0";

    @Autowired
    private AmsRfidTagMapper amsRfidTagMapper;

    @Autowired
    private IAssetLifecycleService assetLifecycleService;

    @Autowired
    private IRfidBindingService rfidBindingService;

    /**
     * 查询RFID标签
     * 
     * @param tagId RFID标签主键
     * @return RFID标签
     */
    @Override
    public AmsRfidTag selectAmsRfidTagByTagId(Long tagId)
    {
        return amsRfidTagMapper.selectAmsRfidTagByTagId(tagId);
    }

    /**
     * 查询RFID标签列表
     * 
     * @param amsRfidTag RFID标签
     * @return RFID标签
     */
    @Override
    public List<AmsRfidTag> selectAmsRfidTagList(AmsRfidTag amsRfidTag)
    {
        return amsRfidTagMapper.selectAmsRfidTagList(amsRfidTag);
    }

    /**
     * 校验标签编码是否唯一
     *
     * @param amsRfidTag RFID标签
     * @return 结果
     */
    @Override
    public boolean checkTagCodeUnique(AmsRfidTag amsRfidTag)
    {
        if (StringUtils.isNull(amsRfidTag) || StringUtils.isEmpty(amsRfidTag.getTagCode()))
        {
            return UserConstants.UNIQUE;
        }
        Long tagId = StringUtils.isNull(amsRfidTag.getTagId()) ? -1L : amsRfidTag.getTagId();
        AmsRfidTag info = amsRfidTagMapper.checkTagCodeUnique(StringUtils.trim(amsRfidTag.getTagCode()));
        if (StringUtils.isNotNull(info) && info.getTagId().longValue() != tagId.longValue())
        {
            return UserConstants.NOT_UNIQUE;
        }
        return UserConstants.UNIQUE;
    }

    /**
     * 校验EPC编码是否唯一
     *
     * @param amsRfidTag RFID标签
     * @return 结果
     */
    @Override
    public boolean checkEpcCodeUnique(AmsRfidTag amsRfidTag)
    {
        if (StringUtils.isNull(amsRfidTag) || StringUtils.isEmpty(amsRfidTag.getEpcCode()))
        {
            return UserConstants.UNIQUE;
        }
        Long tagId = StringUtils.isNull(amsRfidTag.getTagId()) ? -1L : amsRfidTag.getTagId();
        AmsRfidTag info = amsRfidTagMapper.checkEpcCodeUnique(StringUtils.trim(amsRfidTag.getEpcCode()));
        if (StringUtils.isNotNull(info) && info.getTagId().longValue() != tagId.longValue())
        {
            return UserConstants.NOT_UNIQUE;
        }
        return UserConstants.UNIQUE;
    }

    /**
     * 新增RFID标签
     * 
     * @param amsRfidTag RFID标签
     * @return 结果
     */
    @Override
    public int insertAmsRfidTag(AmsRfidTag amsRfidTag)
    {
        validateBasicFields(amsRfidTag);
        if (!checkTagCodeUnique(amsRfidTag))
        {
            throw new ServiceException("标签编码已存在");
        }
        if (!checkEpcCodeUnique(amsRfidTag))
        {
            throw new ServiceException("EPC编码已存在");
        }
        // 后台建档只允许创建未绑定的正常标签，绑定关系必须经 RfidBindingService 受控维护
        amsRfidTag.setTagStatus(RfidTagStatus.NORMAL);
        amsRfidTag.setBindStatus(RfidBindStatus.UNBOUND);
        clearBindingFields(amsRfidTag);
        amsRfidTag.setDelFlag(DEL_FLAG_NORMAL);
        amsRfidTag.setCreateTime(DateUtils.getNowDate());
        return amsRfidTagMapper.insertAmsRfidTag(amsRfidTag);
    }

    /**
     * 修改RFID标签
     * 
     * @param amsRfidTag RFID标签
     * @return 结果
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int updateAmsRfidTag(AmsRfidTag amsRfidTag)
    {
        validateBasicFields(amsRfidTag);
        AmsRfidTag current = selectExistingTagForUpdate(amsRfidTag.getTagId());
        validateIdentityChange(current, amsRfidTag);
        if (!checkTagCodeUnique(amsRfidTag))
        {
            throw new ServiceException("标签编码已存在");
        }
        if (!checkEpcCodeUnique(amsRfidTag))
        {
            throw new ServiceException("EPC编码已存在");
        }
        // 页面只维护标签基础信息，状态/绑定字段由 RfidBindingService 统一维护，避免绕过受控服务
        keepCurrentStateFields(amsRfidTag, current);
        amsRfidTag.setUpdateTime(DateUtils.getNowDate());
        return amsRfidTagMapper.updateAmsRfidTag(amsRfidTag);
    }

    /**
     * 作废RFID标签
     *
     * @param tagId RFID标签主键
     * @param operName 操作用户
     * @return 结果
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int voidAmsRfidTagByTagId(Long tagId, String operName)
    {
        AmsRfidTag tag = selectExistingTagForUpdate(tagId);
        if (StringUtils.equals(RfidTagStatus.VOID, tag.getTagStatus()))
        {
            throw new ServiceException("RFID标签已作废");
        }
        if (isBound(tag))
        {
            throw new ServiceException("已绑定RFID标签不能直接作废，请先解绑");
        }
        int rows = amsRfidTagMapper.voidAmsRfidTagByTagId(tagId, operName, DateUtils.getNowDate());
        if (rows != 1)
        {
            throw new ServiceException("RFID标签当前状态已变化，作废失败");
        }
        return rows;
    }

    /**
     * 解绑RFID标签
     *
     * @param tagId RFID标签主键
     * @param operUserId 操作用户ID
     * @param operUserName 操作用户名称
     * @param operName 操作登录账号
     * @return 结果
     */
    @Override
    public int unbindAmsRfidTagByTagId(Long tagId, Long operUserId, String operUserName, String operName)
    {
        // 解绑逻辑已统一委托给 RfidBindingService，事务由被委托方管理
        RfidBindingContext context = new RfidBindingContext();
        context.setOperateUserId(operUserId);
        context.setOperateUserName(operUserName);
        context.setOperateLoginName(operName);
        rfidBindingService.unbind(tagId, context);
        return 1;
    }

    /**
     * 批量删除RFID标签
     * 
     * @param tagIds 需要删除的RFID标签主键
     * @return 结果
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int deleteAmsRfidTagByTagIds(String tagIds)
    {
        String[] ids = Convert.toStrArray(tagIds);
        // 按ID升序逐行加锁删除，代替批量 IN(...) 避免间隙锁和锁序不确定的死锁风险
        Long[] sortedIds = Arrays.stream(ids).map(Long::valueOf).sorted().toArray(Long[]::new);
        for (Long tagId : sortedIds)
        {
            AmsRfidTag tag = selectExistingTagForUpdate(tagId);
            checkDeleteAllowed(tag);
            if (amsRfidTagMapper.deleteAmsRfidTagByTagId(tagId) != 1)
            {
                throw new ServiceException("RFID标签当前状态已变化，删除失败");
            }
        }
        return sortedIds.length;
    }

    /**
     * 删除RFID标签信息
     * 
     * @param tagId RFID标签主键
     * @return 结果
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int deleteAmsRfidTagByTagId(Long tagId)
    {
        AmsRfidTag tag = selectExistingTagForUpdate(tagId);
        checkDeleteAllowed(tag);
        int rows = amsRfidTagMapper.deleteAmsRfidTagByTagId(tagId);
        if (rows != 1)
        {
            throw new ServiceException("RFID标签当前状态已变化，删除失败");
        }
        return rows;
    }

    private AmsRfidTag selectExistingTagForUpdate(Long tagId)
    {
        if (StringUtils.isNull(tagId))
        {
            throw new ServiceException("RFID标签ID不能为空");
        }
        AmsRfidTag tag = amsRfidTagMapper.selectAmsRfidTagByTagIdForUpdate(tagId);
        if (StringUtils.isNull(tag))
        {
            throw new ServiceException("RFID标签不存在或已删除");
        }
        return tag;
    }

    private void validateBasicFields(AmsRfidTag amsRfidTag)
    {
        if (StringUtils.isNull(amsRfidTag))
        {
            throw new ServiceException("RFID标签不能为空");
        }
        amsRfidTag.setTagCode(StringUtils.trim(amsRfidTag.getTagCode()));
        amsRfidTag.setEpcCode(StringUtils.trim(amsRfidTag.getEpcCode()));
        if (StringUtils.isEmpty(amsRfidTag.getTagCode()))
        {
            throw new ServiceException("标签编码不能为空");
        }
        if (StringUtils.isEmpty(amsRfidTag.getEpcCode()))
        {
            throw new ServiceException("EPC编码不能为空");
        }
    }

    private void validateIdentityChange(AmsRfidTag current, AmsRfidTag incoming)
    {
        if (StringUtils.equals(RfidTagStatus.VOID, current.getTagStatus())
                && (!StringUtils.equals(current.getTagCode(), incoming.getTagCode())
                || !StringUtils.equals(current.getEpcCode(), incoming.getEpcCode())))
        {
            throw new ServiceException("已作废RFID标签不允许修改标签编码或EPC编码");
        }
        if (isBound(current)
                && (!StringUtils.equals(current.getTagCode(), incoming.getTagCode())
                || !StringUtils.equals(current.getEpcCode(), incoming.getEpcCode())))
        {
            throw new ServiceException("已绑定RFID标签不允许修改标签编码或EPC编码，请先解绑");
        }
    }

    private void keepCurrentStateFields(AmsRfidTag incoming, AmsRfidTag current)
    {
        incoming.setTagStatus(current.getTagStatus());
        incoming.setBindStatus(current.getBindStatus());
        incoming.setAssetId(current.getAssetId());
        incoming.setAssetCode(current.getAssetCode());
        incoming.setAssetName(current.getAssetName());
        incoming.setBindTime(current.getBindTime());
        incoming.setBindUserId(current.getBindUserId());
        incoming.setBindUserName(current.getBindUserName());
        incoming.setDelFlag(current.getDelFlag());
    }

    private void clearBindingFields(AmsRfidTag amsRfidTag)
    {
        amsRfidTag.setAssetId(null);
        amsRfidTag.setAssetCode(null);
        amsRfidTag.setAssetName(null);
        amsRfidTag.setBindTime(null);
        amsRfidTag.setBindUserId(null);
        amsRfidTag.setBindUserName(null);
    }

    private void checkDeleteAllowed(AmsRfidTag tag)
    {
        if (isBound(tag))
        {
            throw new ServiceException(String.format("RFID标签【%1$s】已绑定资产，不允许删除", tag.getTagCode()));
        }
        // 以履历记录代替 bindTime 判断，避免解绑后 bindTime 被清空导致有历史的标签被误删
        if (assetLifecycleService.hasRfidLifecycle(tag.getTagId()))
        {
            throw new ServiceException(String.format("RFID标签【%1$s】已有绑定履历，不允许删除，可作废保留", tag.getTagCode()));
        }
    }

    private boolean isBound(AmsRfidTag tag)
    {
        return StringUtils.equals(RfidBindStatus.BOUND, tag.getBindStatus()) || StringUtils.isNotNull(tag.getAssetId());
    }
}
