package com.qqchen.deploy.backend.deploy.service.impl;

import com.qqchen.deploy.backend.deploy.entity.ExternalSystem;
import com.qqchen.deploy.backend.system.enums.ExternalSystemAuthTypeEnum;
import com.qqchen.deploy.backend.system.enums.ExternalSystemSyncStatusEnum;
import com.qqchen.deploy.backend.system.enums.ExternalSystemTypeEnum;
import com.qqchen.deploy.backend.framework.annotation.ServiceType;
import com.qqchen.deploy.backend.framework.enums.ResponseCode;
import com.qqchen.deploy.backend.framework.exception.BusinessException;
import com.qqchen.deploy.backend.framework.exception.UniqueConstraintException;
import com.qqchen.deploy.backend.framework.service.impl.BaseServiceImpl;
import com.qqchen.deploy.backend.deploy.integration.IExternalSystemIntegration;
import com.qqchen.deploy.backend.system.model.ExternalSystemDTO;
import com.qqchen.deploy.backend.deploy.repository.IExternalSystemRepository;
import com.qqchen.deploy.backend.deploy.service.IExternalSystemService;
import com.qqchen.deploy.backend.system.model.query.ExternalSystemQuery;
import jakarta.annotation.PostConstruct;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import static com.qqchen.deploy.backend.framework.annotation.ServiceType.Type.DATABASE;

/**
 * 外部系统服务实现类
 * 主要功能：
 * 1. 外部系统的CRUD操作
 * 2. 系统连接测试
 * 3. 系统数据同步
 * 4. 系统状态管理
 *
 * @author QQChen
 * @version 1.0.0
 */
@Slf4j
@Service
@ServiceType(DATABASE)
public class ExternalSystemServiceImpl extends BaseServiceImpl<ExternalSystem, ExternalSystemDTO, ExternalSystemQuery, Long> implements IExternalSystemService {

    @Resource
    private IExternalSystemRepository externalSystemRepository;

    @Resource
    private List<IExternalSystemIntegration> systemIntegrations;
    
    private Map<ExternalSystemTypeEnum, IExternalSystemIntegration> integrationMap;
    
    @PostConstruct
    public void init() {
        integrationMap = systemIntegrations.stream()
            .collect(Collectors.toMap(
                IExternalSystemIntegration::getSystemType,
                integration -> integration
            ));
    }

    @Override
    public void validateUniqueConstraints(ExternalSystemDTO dto) {
        // 检查名称唯一性
        if (externalSystemRepository.existsByNameAndDeletedFalse(dto.getName())) {
            throw new UniqueConstraintException(ResponseCode.EXTERNAL_SYSTEM_NAME_EXISTS, "name", dto.getName());
        }
        
        // 检查类型+URL组合唯一性
        if (externalSystemRepository.existsByTypeAndUrlAndDeletedFalse(dto.getType(), dto.getUrl())) {
            throw new UniqueConstraintException(ResponseCode.EXTERNAL_SYSTEM_TYPE_URL_EXISTS, 
                "type and url", dto.getType() + ":" + dto.getUrl());
        }

        validateGitAuth(dto);
    }

    @Override
    public ExternalSystemDTO update(Long id, ExternalSystemDTO dto) {
        // 先验证Git认证
        validateGitAuth(dto);
        return super.update(id, dto);
    }

    /**
     * 验证Git系统的认证方式
     *
     * @param dto 外部系统DTO
     */
    private void validateGitAuth(ExternalSystemDTO dto) {
        if (dto.getType() == ExternalSystemTypeEnum.GIT) {
            if (dto.getAuthType() != ExternalSystemAuthTypeEnum.TOKEN) {
                throw new BusinessException(ResponseCode.EXTERNAL_SYSTEM_GIT_AUTH_TYPE_ERROR);
            }
            if (StringUtils.isBlank(dto.getToken())) {
                throw new BusinessException(ResponseCode.EXTERNAL_SYSTEM_GIT_TOKEN_REQUIRED);
            }
        }
    }

    @Override
    @Transactional
    public boolean testConnection(Long id) {
        ExternalSystem system = findEntityById(id);
        if (!system.getEnabled()) {
            throw new BusinessException(ResponseCode.EXTERNAL_SYSTEM_DISABLED);
        }
        
        IExternalSystemIntegration integration = integrationMap.get(system.getType());
        if (integration == null) {
            throw new BusinessException(ResponseCode.EXTERNAL_SYSTEM_TYPE_NOT_SUPPORTED);
        }
        
        boolean success = integration.testConnection(system);
        if (success) {
            system.setLastConnectTime(LocalDateTime.now());
            externalSystemRepository.save(system);
        }
        return success;
    }

    @Override
    @Transactional
    public void updateStatus(Long id, boolean enabled) {
        ExternalSystem system = findEntityById(id);
        system.setEnabled(enabled);
        externalSystemRepository.save(system);
    }

}