package com.brilliance.isc.common.lock.impl;

import org.slf4j.LoggerFactory;
import org.slf4j.Logger;
import com.brilliance.isc.bo.Lck;
import com.brilliance.isc.bo.Stb;
import com.brilliance.isc.common.lock.LockInfo;
import com.brilliance.isc.mda.dao.StbMapper;
import com.brilliance.isc.vo.manager.StbVo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Primary;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;


@Service
@Primary
public class DBLckBizLocker extends AbstractBizLocker {
    private final Logger logger = LoggerFactory.getLogger(DBLckBizLocker.class);

    @Autowired
    private LckComponent lckComponent;

    @Autowired
    private StbMapper stbMapper;

    private boolean switchFlag = false;

    private final String DBLOCKER = "DBLOCK";

    private boolean getSwitchFlag(){
        StbVo stbVo = new StbVo();
        stbVo.setTbl(DBLOCKER);
        List<Stb> stbs = stbMapper.queryByPage(stbVo);
        if(stbs == null || stbs.size() == 0){
            return false;
        }
        return "Y".equals(stbs.get(0).getCod()) ? true : false;
    }

    /**
     * @param key 为业务主键，使用LockInfo的方法生成key
     * @param value 为业务锁定信息，一般为交易码+操作人，使用LockInfo的方法生成value
     * @param seconds 锁定时间,db模式下无效
     * @return
     */
    @Transactional(propagation = Propagation.REQUIRES_NEW,rollbackFor = Exception.class)
    public boolean lock(String key,String value, long seconds) {
        if(!getSwitchFlag()){
            logger.info("锁定函数暂时关闭");
            return true;
        }
        LockInfo lockInfo = new LockInfo(key,value);
        boolean  isSuccess = lckComponent.tryInsert(lockInfo);

        // 插入成功，新增
        if (isSuccess) {
            logger.info("锁key:{},value:{}，结果:成功",key,value);
            return true;
        }
        lockInfo = getLock(lockInfo);
        String oldValue = lockInfo.genLockValue();
        // 相同时，刷新时间
        if (oldValue.equals(value)) {
            if(value.endsWith("#true")) {
                logger.info("锁已重入key:{},value:{}",key,value);
                isSuccess = true;
            }else{
                logger.info("锁无法重入key:{},value:{}",key,value);
            }
        }
        return isSuccess;
    }



    @Override
    public LockInfo getLock(LockInfo lockInfo) {
        if(!getSwitchFlag()){
            logger.info("锁定函数暂时关闭");
            return null;
        }
        String key = lockInfo.genLockKey();
        LockInfo dbLockInfo = lckComponent.getLck(lockInfo);
        if(dbLockInfo != null){
            String value = dbLockInfo.genLockValue();
            logger.info("返回锁信息key:{},value:{}",key,value);
            return dbLockInfo;
        }
        return null;
    }


    @Override
    public boolean unlock(LockInfo lockInfo) {
        if(!getSwitchFlag()){
            logger.info("锁定函数暂时关闭");
            return true;
        }
        String key = lockInfo.genLockKey();
        LockInfo oldLockInfo = getLock(lockInfo);
        if(oldLockInfo != null){
            logger.info("返回锁信息key:{},value:{}",key,oldLockInfo.genLockValue());
            if(oldLockInfo.getUsrId().equals(lockInfo.getUsrId())){
                logger.info("删除锁{}",key);
                int cnt = lckComponent.deleteLck(oldLockInfo);
                logger.info("删除锁成功{}，影响行数{}",key,cnt);
                return true;
            }else{
                logger.info("{}锁定人不一致，不允许删除,oldUserId:{},curUserId{},",key,oldLockInfo.getUsrId(),lockInfo.getUsrId());
            }
        }
        return false;
    }

    @Transactional(propagation = Propagation.REQUIRES_NEW,rollbackFor = Exception.class)
    public boolean lockForce(String key,String value, long seconds) {
        logger.info("强制占用锁{}:{}",key,value);
        LockInfo lockInfo = new LockInfo(key,value);
        lckComponent.updateLockInfo(lockInfo);
        logger.info("强制占用锁{}:{}成功",key,value);
        return true;
    }



    /**
     * 强制解锁
     *
     * @param lockInfo
     * @return
     */
    @Override
    public boolean unlockForce(LockInfo lockInfo) {
        String key = lockInfo.genLockKey();
        logger.info("强制删除锁{}",key);
        int cnt = lckComponent.deleteLck(lockInfo);
        logger.info("强制删除锁成功{}，影响行数{}",key,cnt);
        return true;
    }

    /**
     * 删除当前交易相关锁信息
     *
     * @param transName
     * @param userId
     */
    @Override
    public boolean unlockAllOfTrans(String transName, String userId) {
        Lck lck = new Lck();
        lck.setLcktrn(transName);
        lck.setLckusr(userId);
        int cnt = lckComponent.deleteLckByUserAndTrn(lck);
        logger.info("解除{}用户在{}交易的所有锁定，影响行数{}",userId,transName,cnt);
        return true;
    }

    /**
     * 刪除用戶所有的锁
     *
     * @param userId
     * @return
     */
    @Override
    public boolean unlockAllOfUser(String userId) {
        logger.info("退出锁定{}",userId);
        Lck lck = new Lck();
        lck.setLcktrn(null);
        lck.setLckusr(userId);
        int cnt = lckComponent.deleteLckByUserAndTrn(lck);
        logger.info("退出锁定成功{}，影响行数{}",userId,cnt);
        return false;
    }
}
