package org.dromara.system.service.impl;

import cn.hutool.core.io.FileUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import lombok.RequiredArgsConstructor;
import org.dromara.common.core.domain.model.LoginUser;
import org.dromara.common.core.exception.ServiceException;
import org.dromara.common.core.utils.MapstructUtils;
import org.dromara.common.core.utils.StringUtils;
import org.dromara.common.core.utils.file.MimeTypeUtils;
import org.dromara.common.satoken.utils.LoginHelper;
import org.dromara.system.domain.SysUserElectronicSignature;
import org.dromara.system.domain.bo.SysUserElectronicSignatureBo;
import org.dromara.system.domain.vo.SysOssVo;
import org.dromara.system.domain.vo.SysUserElectronicSignatureVo;
import org.dromara.system.mapper.SysUserElectronicSignatureMapper;
import org.dromara.system.service.ISysOssService;
import org.dromara.system.service.ISysUserElectronicSignatureService;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

/**
 * 当前登录人员电子签名服务实现
 *
 * @author shihongwei
 */
@RequiredArgsConstructor
@Service
public class SysUserElectronicSignatureServiceImpl implements ISysUserElectronicSignatureService {

    private static final String STATUS_ENABLED = "1";
    private static final String STATUS_DISABLED = "0";

    private final SysUserElectronicSignatureMapper baseMapper;
    private final ISysOssService ossService;

    @Override
    public SysUserElectronicSignatureVo getCurrentUserSignature() {
        LoginUser loginUser = getRequiredLoginUser();
        String personKey = buildPersonKey(loginUser);
        SysUserElectronicSignature entity = baseMapper.selectOne(
            Wrappers.<SysUserElectronicSignature>lambdaQuery()
                .eq(SysUserElectronicSignature::getTenantId, loginUser.getTenantId())
                .eq(SysUserElectronicSignature::getPersonKey, personKey)
                .last("limit 1")
        );
        if (entity == null) {
            return buildEmptyVo(loginUser, personKey);
        }
        SysUserElectronicSignatureVo vo = MapstructUtils.convert(entity, SysUserElectronicSignatureVo.class);
        vo.setConfigured(isConfigured(entity));
        if (StringUtils.isBlank(vo.getSignName())) {
            vo.setSignName(resolveSignName(loginUser));
        }
        return vo;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public SysUserElectronicSignatureVo saveCurrentUserSignature(SysUserElectronicSignatureBo bo) {
        LoginUser loginUser = getRequiredLoginUser();
        validateSignatureOss(bo.getSignOssId());
        String personKey = buildPersonKey(loginUser);
        SysUserElectronicSignature entity = baseMapper.selectOne(
            Wrappers.<SysUserElectronicSignature>lambdaQuery()
                .eq(SysUserElectronicSignature::getTenantId, loginUser.getTenantId())
                .eq(SysUserElectronicSignature::getPersonKey, personKey)
                .last("limit 1")
        );
        if (entity == null) {
            entity = new SysUserElectronicSignature();
            entity.setTenantId(loginUser.getTenantId());
            entity.setPersonKey(personKey);
        }
        entity.setUserId(loginUser.getUserId());
        entity.setBusinessUserId(loginUser.getBusinessUserId());
        entity.setCompanyId(loginUser.getCompanyId());
        entity.setLoginPort(defaultLoginPort(loginUser));
        entity.setSignOssId(bo.getSignOssId());
        entity.setSignName(resolveSignName(loginUser));
        entity.setStatus(STATUS_ENABLED);
        if (entity.getId() == null) {
            baseMapper.insert(entity);
        } else {
            baseMapper.updateById(entity);
        }
        return getCurrentUserSignature();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean clearCurrentUserSignature() {
        LoginUser loginUser = getRequiredLoginUser();
        String personKey = buildPersonKey(loginUser);
        SysUserElectronicSignature entity = baseMapper.selectOne(
            Wrappers.<SysUserElectronicSignature>lambdaQuery()
                .eq(SysUserElectronicSignature::getTenantId, loginUser.getTenantId())
                .eq(SysUserElectronicSignature::getPersonKey, personKey)
                .last("limit 1")
        );
        if (entity == null) {
            return true;
        }
        entity.setUserId(loginUser.getUserId());
        entity.setBusinessUserId(loginUser.getBusinessUserId());
        entity.setCompanyId(loginUser.getCompanyId());
        entity.setLoginPort(defaultLoginPort(loginUser));
        entity.setSignOssId(null);
        entity.setSignName(resolveSignName(loginUser));
        entity.setStatus(STATUS_DISABLED);
        return baseMapper.updateById(entity) > 0;
    }

    private boolean isConfigured(SysUserElectronicSignature entity) {
        return entity != null
            && STATUS_ENABLED.equals(entity.getStatus())
            && entity.getSignOssId() != null;
    }

    private SysUserElectronicSignatureVo buildEmptyVo(LoginUser loginUser, String personKey) {
        SysUserElectronicSignatureVo vo = new SysUserElectronicSignatureVo();
        vo.setConfigured(false);
        vo.setPersonKey(personKey);
        vo.setUserId(loginUser.getUserId());
        vo.setBusinessUserId(loginUser.getBusinessUserId());
        vo.setCompanyId(loginUser.getCompanyId());
        vo.setLoginPort(defaultLoginPort(loginUser));
        vo.setSignName(resolveSignName(loginUser));
        vo.setStatus(STATUS_DISABLED);
        return vo;
    }

    private void validateSignatureOss(Long signOssId) {
        SysOssVo ossVo = ossService.getById(signOssId);
        if (ossVo == null) {
            throw new ServiceException("电子签名文件不存在，请重新上传后再试");
        }
        String fileName = StringUtils.defaultIfBlank(ossVo.getOriginalName(), ossVo.getFileName());
        String extension = FileUtil.extName(fileName);
        if (!StringUtils.equalsAnyIgnoreCase(extension, MimeTypeUtils.IMAGE_EXTENSION)) {
            throw new ServiceException("电子签名必须为图片格式");
        }
    }

    private LoginUser getRequiredLoginUser() {
        LoginUser loginUser = LoginHelper.getLoginUser();
        if (loginUser == null || loginUser.getUserId() == null) {
            throw new ServiceException("用户未登录");
        }
        return loginUser;
    }

    private String buildPersonKey(LoginUser loginUser) {
        String businessUserId = StringUtils.defaultIfBlank(loginUser.getBusinessUserId(), String.valueOf(loginUser.getUserId()));
        String companyId = loginUser.getCompanyId() == null ? "0" : String.valueOf(loginUser.getCompanyId());
        return defaultLoginPort(loginUser) + ":" + companyId + ":" + businessUserId;
    }

    private String defaultLoginPort(LoginUser loginUser) {
        return StringUtils.defaultIfBlank(loginUser.getLoginPort(), "default");
    }

    private String resolveSignName(LoginUser loginUser) {
        return StringUtils.defaultIfBlank(loginUser.getNickname(), loginUser.getUsername());
    }
}
