package com.usky.issue.service.impl;

import com.baomidou.dynamic.datasource.annotation.DS;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.usky.common.core.exception.BusinessException;
import com.usky.issue.domain.IssueSyncDownQueue;
import com.usky.issue.domain.SysUser;
import com.usky.issue.mapper.IssueSyncDownQueueMapper;
import com.usky.issue.mapper.SysUserMapper;
import com.usky.issue.service.CloudSyncPublishService;
import com.usky.issue.service.enums.SyncTypeEnum;
import com.usky.issue.service.support.CloudEntitySupport;
import com.usky.issue.service.sync.SyncPayloadSupport;
import com.usky.issue.service.util.SyncJsonMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.util.List;

/**
 * 云端下发队列发布实现
 *
 * @author fyc
 * @date 2026-06-29
 */
@Slf4j
@DS("usky-cloud")
@Service
public class CloudSyncPublishServiceImpl implements CloudSyncPublishService {

    private static final com.fasterxml.jackson.databind.ObjectMapper OBJECT_MAPPER = SyncJsonMapper.INSTANCE;

    @Autowired
    private IssueSyncDownQueueMapper downQueueMapper;
    @Autowired
    private SysUserMapper sysUserMapper;
    @Lazy
    @Autowired
    private CloudSyncPublishService self;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void enqueueUser(SysUser user, String operation) {
        if (user == null || user.getUserId() == null) {
            throw new BusinessException("用户信息不完整，无法入队");
        }
        if (user.getTenantId() == null) {
            throw new BusinessException("用户缺少租户ID，无法入队 userId=" + user.getUserId());
        }
        String op = StringUtils.hasText(operation) ? operation : "UPDATE";
        String tableName = SyncTypeEnum.USER.getCode();
        String dataKey = SyncPayloadSupport.buildUserDataKey(user.getUserId());
        long syncVersion = System.currentTimeMillis();

        Integer pending = downQueueMapper.selectCount(new LambdaQueryWrapper<IssueSyncDownQueue>()
                .eq(IssueSyncDownQueue::getTenantId, user.getTenantId())
                .eq(IssueSyncDownQueue::getTableName, tableName)
                .eq(IssueSyncDownQueue::getStatus, 0)
                .eq(IssueSyncDownQueue::getIsDeleted, 0)
                .like(IssueSyncDownQueue::getPayload, "\"dataKey\":\"" + dataKey + "\""));
        if (pending != null && pending > 0) {
            log.debug("用户下发队列已存在待同步记录 dataKey={}", dataKey);
            return;
        }

        try {
            String businessPayload = OBJECT_MAPPER.writeValueAsString(user);
            String wrappedPayload = SyncPayloadSupport.wrapBusinessPayload(
                    user.getTenantId(), tableName, dataKey, businessPayload, syncVersion);

            IssueSyncDownQueue queue = new IssueSyncDownQueue();
            queue.setTenantId(user.getTenantId());
            queue.setTableName(tableName);
            queue.setOperation(op);
            queue.setPayload(wrappedPayload);
            queue.setSyncVersion(syncVersion);
            queue.setStatus(0);
            CloudEntitySupport.fillOnInsert(queue);
            downQueueMapper.insert(queue);
            log.info("用户已从 sys_user 入下发队列 userId={}, tenantId={}, operation={}",
                    user.getUserId(), user.getTenantId(), op);
        } catch (Exception e) {
            log.error("用户入下发队列失败 userId={}, tenantId={}", user.getUserId(), user.getTenantId(), e);
            throw new BusinessException("用户入下发队列失败: " + e.getMessage());
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public int backfillUsersIfNeeded(Integer tenantId, Long lastVersion, boolean force) {
        if (tenantId == null) {
            return 0;
        }
        if (!force && lastVersion != null && lastVersion > 0) {
            return 0;
        }
        String tableName = SyncTypeEnum.USER.getCode();
        if (!force) {
            Integer pending = downQueueMapper.selectCount(new LambdaQueryWrapper<IssueSyncDownQueue>()
                    .eq(IssueSyncDownQueue::getTenantId, tenantId)
                    .eq(IssueSyncDownQueue::getTableName, tableName)
                    .eq(IssueSyncDownQueue::getStatus, 0)
                    .eq(IssueSyncDownQueue::getIsDeleted, 0));
            if (pending != null && pending > 0) {
                log.info("租户{}下发队列已有{}条待同步，跳过 sys_user 回填", tenantId, pending);
                return 0;
            }
        }

        List<SysUser> users = sysUserMapper.selectList(new LambdaQueryWrapper<SysUser>()
                .eq(SysUser::getTenantId, tenantId)
                .and(w -> w.eq(SysUser::getDelFlag, "0").or().isNull(SysUser::getDelFlag)));
        if (users.isEmpty()) {
            log.warn("租户{}在 sys_user 无有效用户（tenant_id={} 且 del_flag=0）", tenantId, tenantId);
            return 0;
        }
        log.info("从 sys_user 回填下发队列 tenantId={}, userCount={}, force={}", tenantId, users.size(), force);
        int enqueued = 0;
        for (SysUser user : users) {
            self.enqueueUser(user, "INSERT");
            enqueued++;
        }
        return enqueued;
    }

    @Override
    public int countSysUsers(Integer tenantId) {
        if (tenantId == null) {
            return 0;
        }
        Integer count = sysUserMapper.selectCount(new LambdaQueryWrapper<SysUser>()
                .eq(SysUser::getTenantId, tenantId)
                .and(w -> w.eq(SysUser::getDelFlag, "0").or().isNull(SysUser::getDelFlag)));
        return count == null ? 0 : count;
    }
}
