package com.njcn.rdms.module.project.service.member;

import com.njcn.rdms.module.project.constant.ObjectRoleConstants;
import com.njcn.rdms.module.project.constant.ProductObjectConstants;
import com.njcn.rdms.module.project.constant.ProjectObjectConstants;
import com.njcn.rdms.module.project.dal.dataobject.member.UserObjectRoleDO;
import com.njcn.rdms.module.project.dal.mysql.member.UserObjectRoleMapper;
import com.njcn.rdms.module.project.enums.ErrorCodeConstants;
import com.njcn.rdms.module.system.api.permission.ObjectPermissionApi;
import com.njcn.rdms.module.system.api.permission.dto.ObjectRoleRespDTO;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.List;
import java.util.Objects;

import static com.njcn.rdms.framework.common.exception.util.ServiceExceptionUtil.exception;

/**
 * ObjectRoleAutoAssignService 实现。
 *
 * 写入分支（参 spec 7.1 / 7.2 节）：
 * - (user, object, role) 三元组不存在 → INSERT
 * - 存在 ACTIVE → 跳过（防御性，正常流程不会走到）
 * - 存在 INACTIVE → 复活（status=ACTIVE, leftTime=null, joinedTime=now）
 *
 * 用 selectByObjectUserAndRole（不带 status 过滤）查老行，避免 INACTIVE 占索引位导致 INSERT 冲突。
 */
@Service
@Slf4j
public class ObjectRoleAutoAssignServiceImpl implements ObjectRoleAutoAssignService {

    @Resource
    private UserObjectRoleMapper userObjectRoleMapper;
    @Resource
    private ObjectPermissionApi objectPermissionApi;

    @Override
    public void assignCreatorAndManager(String objectType, Long objectId,
                                        Long creatorUserId, Long managerUserId,
                                        String creatorRoleCode, String managerRoleCode) {
        Long creatorRoleId = resolveRoleId(creatorRoleCode, objectType);
        Long managerRoleId = resolveRoleId(managerRoleCode, objectType);

        insertOrReactivate(objectType, objectId, managerUserId, managerRoleId);
        insertOrReactivate(objectType, objectId, creatorUserId, creatorRoleId);
    }

    @Override
    public void assignCreator(String objectType, Long objectId, Long creatorUserId, String creatorRoleCode) {
        Long creatorRoleId = resolveRoleId(creatorRoleCode, objectType);
        insertOrReactivate(objectType, objectId, creatorUserId, creatorRoleId);
    }

    @Override
    public void assignWatchers(String objectType, Long objectId,
                               List<Long> watcherUserIds, String watcherRoleCode) {
        if (watcherUserIds == null || watcherUserIds.isEmpty()) {
            return;
        }
        Long watcherRoleId = resolveRoleId(watcherRoleCode, objectType);
        watcherUserIds.stream()
                .filter(Objects::nonNull)
                .distinct()
                .forEach(uid -> insertOrReactivate(objectType, objectId, uid, watcherRoleId));
    }

    private Long resolveRoleId(String roleCode, String objectType) {
        ObjectRoleRespDTO role = objectPermissionApi
                .getObjectRoleByCode(roleCode, ObjectRoleConstants.ROLE_SCOPE_OBJECT, objectType)
                .getCheckedData();
        if (role == null || role.getId() == null) {
            // 按 objectType 派发到对应业务错误码，避免 IllegalStateException 透出 500
            if (ProductObjectConstants.OBJECT_TYPE.equals(objectType)) {
                throw exception(ErrorCodeConstants.PRODUCT_INTERNAL_ROLE_NOT_CONFIGURED, roleCode);
            }
            if (ProjectObjectConstants.OBJECT_TYPE.equals(objectType)) {
                throw exception(ErrorCodeConstants.PROJECT_INTERNAL_ROLE_NOT_CONFIGURED, roleCode);
            }
            // 未知 objectType 兜底（理论不会走到——调用方都用 ProductObjectConstants / ProjectObjectConstants）
            throw new IllegalStateException(
                    "内置对象角色未在 system_role 找到: code=" + roleCode + ", object_type=" + objectType);
        }
        return role.getId();
    }

    private void insertOrReactivate(String objectType, Long objectId, Long userId, Long roleId) {
        UserObjectRoleDO existing = userObjectRoleMapper
                .selectByObjectUserAndRole(objectType, objectId, userId, roleId);
        if (existing != null && Objects.equals(existing.getStatus(), ObjectRoleConstants.MEMBER_STATUS_ACTIVE)) {
            return;
        }
        LocalDateTime now = LocalDateTime.now();
        if (existing == null) {
            UserObjectRoleDO row = new UserObjectRoleDO();
            row.setUserId(userId);
            row.setObjectType(objectType);
            row.setObjectId(objectId);
            row.setRoleId(roleId);
            row.setStatus(ObjectRoleConstants.MEMBER_STATUS_ACTIVE);
            row.setJoinedTime(now);
            row.setLeftTime(null);
            // 系统自动落的角色行不写备注，避免内部标记泄漏到团队成员列表的备注列
            row.setRemark(null);
            userObjectRoleMapper.insert(row);
        } else {
            existing.setStatus(ObjectRoleConstants.MEMBER_STATUS_ACTIVE);
            existing.setLeftTime(null);
            existing.setJoinedTime(now);
            // 复活时一并清掉历史脏备注（旧版本写过 "auto: xxx"）
            existing.setRemark(null);
            userObjectRoleMapper.updateById(existing);
        }
    }

}
