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

import com.qqchen.deploy.backend.deploy.entity.ExternalSystem;
import com.qqchen.deploy.backend.deploy.integration.IGitServiceIntegration;
import com.qqchen.deploy.backend.deploy.integration.response.GitBranchResponse;
import com.qqchen.deploy.backend.deploy.integration.response.GitGroupResponse;
import com.qqchen.deploy.backend.deploy.integration.response.GitProjectResponse;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.core.ParameterizedTypeReference;
import org.springframework.http.*;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.util.UriComponentsBuilder;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;

/**
 * Git服务集成实现
 * 主要负责与外部Git系统(如GitLab)的API交互
 */
@Slf4j
@Service
public class GitServiceIntegrationImpl extends BaseExternalSystemIntegration implements IGitServiceIntegration {

    private final RestTemplate restTemplate = new RestTemplate();
    
    // Git系统解密缓存 - 线程安全
    private static final Map<Long, GitSystemCache> SYSTEM_CACHE = new ConcurrentHashMap<>();
    private static final long CACHE_EXPIRE_TIME = 30 * 60 * 1000; // 30分钟过期
    
    // GitLab API 分页配置
    private static final int PER_PAGE = 100; // GitLab API 最大值
    private static final int MAX_PAGES = 100; // 防止无限循环，最多获取 10000 条
    
    /**
     * Git系统缓存内部类
     */
    private static class GitSystemCache {
        final ExternalSystem decryptedSystem;
        final long expireTime;
        
        GitSystemCache(ExternalSystem system) {
            this.decryptedSystem = system;
            this.expireTime = System.currentTimeMillis() + CACHE_EXPIRE_TIME;
        }
        
        boolean isExpired() {
            return System.currentTimeMillis() > expireTime;
        }
    }
    
    /**
     * 线程安全地获取Git系统缓存
     * 如果缓存不存在或已过期，会重新解密
     */
    private synchronized GitSystemCache getSystemCache(ExternalSystem system) {
        Long systemId = system.getId();
        GitSystemCache cache = SYSTEM_CACHE.get(systemId);
        
        if (cache == null || cache.isExpired()) {
            log.debug("Git系统缓存失效，重新解密: systemId={}", systemId);
            
            // 解密系统信息（只在这里解密一次）
            ExternalSystem decryptedSystem = decryptSystem(system);
            
            // 创建新缓存
            cache = new GitSystemCache(decryptedSystem);
            SYSTEM_CACHE.put(systemId, cache);
            
            log.debug("Git系统缓存已更新: systemId={}, expireTime={}", systemId, cache.expireTime);
        }
        
        return cache;
    }

    @Override
    public boolean testConnection(ExternalSystem system) {
        try {
            // 直接使用原始系统信息构建URL（URL不需要解密）
            String url = system.getUrl() + "/api/v4/version";
            // 创建请求头（内部自动处理解密）
            HttpHeaders headers = createHeaders(system);
            HttpEntity<String> entity = new HttpEntity<>(headers);

            ResponseEntity<String> response = restTemplate.exchange(
                url,
                HttpMethod.GET,
                entity,
                String.class
            );

            return response.getStatusCode() == HttpStatus.OK;
        } catch (Exception e) {
            log.error("Git connection test failed for system: {}", system.getName(), e);
            return false;
        }
    }

    @Override
    public List<GitGroupResponse> groups(ExternalSystem system) {
        List<GitGroupResponse> allGroups = new ArrayList<>();
        HttpHeaders headers = createHeaders(system);
        HttpEntity<String> entity = new HttpEntity<>(headers);
        
        try {
            int page = 1;
            while (page <= MAX_PAGES) {
                String url = String.format("%s/api/v4/groups?per_page=%d&page=%d", 
                        system.getUrl(), PER_PAGE, page);
                
                ResponseEntity<List<GitGroupResponse>> response = restTemplate.exchange(
                    url,
                    HttpMethod.GET,
                    entity,
                    new ParameterizedTypeReference<>() {}
                );

                List<GitGroupResponse> groups = response.getBody();
                if (groups == null || groups.isEmpty()) {
                    break;
                }
                
                allGroups.addAll(groups);
                log.debug("Fetched {} groups from page {}", groups.size(), page);
                
                // 如果返回数量小于 per_page，说明已经是最后一页
                if (groups.size() < PER_PAGE) {
                    break;
                }
                page++;
            }
            
            log.info("Total fetched {} groups for system: {}", allGroups.size(), system.getName());
            return allGroups;
        } catch (Exception e) {
            log.error("Failed to fetch git groups for system: {}", system.getName(), e);
            return allGroups.isEmpty() ? Collections.emptyList() : allGroups;
        }
    }

    @Override
    public List<GitProjectResponse> projects(ExternalSystem system) {
        try {
            // 直接使用原始系统信息构建URL（URL不需要解密）
            String url = String.format("%s/api/v4/projects", system.getUrl());
            // 创建请求头（内部自动处理解密）
            HttpHeaders headers = createHeaders(system);
            HttpEntity<String> entity = new HttpEntity<>(headers);

            ResponseEntity<List<GitProjectResponse>> response = restTemplate.exchange(
                url,
                HttpMethod.GET,
                entity,
                new ParameterizedTypeReference<>() {
                }
            );

            return response.getBody() != null ? response.getBody() : Collections.emptyList();
        } catch (Exception e) {
            log.error("Failed to fetch git projects for system: {}", system.getName(), e);
            return Collections.emptyList();
        }
    }

    @Override
    public List<GitProjectResponse> projectsByGroup(ExternalSystem system, Long groupId) {
        List<GitProjectResponse> allProjects = new ArrayList<>();
        HttpHeaders headers = createHeaders(system);
        HttpEntity<String> entity = new HttpEntity<>(headers);
        
        try {
            int page = 1;
            while (page <= MAX_PAGES) {
                String url = String.format("%s/api/v4/groups/%d/projects?per_page=%d&page=%d", 
                        system.getUrl(), groupId, PER_PAGE, page);
                
                ResponseEntity<List<GitProjectResponse>> response = restTemplate.exchange(
                    url,
                    HttpMethod.GET,
                    entity,
                    new ParameterizedTypeReference<>() {}
                );

                List<GitProjectResponse> projects = response.getBody();
                if (projects == null || projects.isEmpty()) {
                    break;
                }
                
                allProjects.addAll(projects);
                log.debug("Fetched {} projects from page {} for group {}", projects.size(), page, groupId);
                
                // 如果返回数量小于 per_page，说明已经是最后一页
                if (projects.size() < PER_PAGE) {
                    break;
                }
                page++;
            }
            
            log.info("Total fetched {} projects for system: {} and group: {}", allProjects.size(), system.getName(), groupId);
            return allProjects;
        } catch (Exception e) {
            log.error("Failed to fetch git projects for system: {} and group: {}", system.getName(), groupId, e);
            return allProjects.isEmpty() ? Collections.emptyList() : allProjects;
        }
    }

    @Override
    public List<GitBranchResponse> branches(ExternalSystem system, Long projectId) {
        List<GitBranchResponse> allBranches = new ArrayList<>();
        HttpHeaders headers = createHeaders(system);
        HttpEntity<String> entity = new HttpEntity<>(headers);
        
        try {
            int page = 1;
            while (page <= MAX_PAGES) {
                String url = String.format("%s/api/v4/projects/%d/repository/branches?per_page=%d&page=%d", 
                        system.getUrl(), projectId, PER_PAGE, page);
                
                ResponseEntity<List<GitBranchResponse>> response = restTemplate.exchange(
                    url,
                    HttpMethod.GET,
                    entity,
                    new ParameterizedTypeReference<>() {}
                );

                List<GitBranchResponse> branches = response.getBody();
                if (branches == null || branches.isEmpty()) {
                    break;
                }
                
                allBranches.addAll(branches);
                log.debug("Fetched {} branches from page {} for project {}", branches.size(), page, projectId);
                
                // 如果返回数量小于 per_page，说明已经是最后一页
                if (branches.size() < PER_PAGE) {
                    break;
                }
                page++;
            }
            
            if (!allBranches.isEmpty()) {
                log.debug("Total fetched {} branches for project: {}, first branch: {}", 
                        allBranches.size(), projectId, allBranches.getFirst().getName());
            } else {
                log.warn("No branches found for project: {}", projectId);
            }
            
            return allBranches;
        } catch (Exception e) {
            log.error("Failed to fetch git branches for system: {} and project: {}", system.getName(), projectId, e);
            return allBranches.isEmpty() ? Collections.emptyList() : allBranches;
        }
    }

    /**
     * 创建包含认证信息的完整请求头
     * 内部自动处理系统解密和缓存
     */
    private HttpHeaders createHeaders(ExternalSystem system) {
        // 获取缓存的解密系统信息
        GitSystemCache cache = getSystemCache(system);
        ExternalSystem decryptedSystem = cache.decryptedSystem;
        
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_JSON);

        // 根据认证类型设置认证信息（使用解密后的系统信息）
        switch (decryptedSystem.getAuthType()) {
            case BASIC -> {
                // Basic认证
                String auth = decryptedSystem.getUsername() + ":" + decryptedSystem.getPassword();
                byte[] encodedAuth = Base64.getEncoder().encode(auth.getBytes());
                String authHeader = "Basic " + new String(encodedAuth);
                headers.set("Authorization", authHeader);
            }
            case TOKEN -> {
                // Token认证 - GitLab使用Private Token
                headers.set("PRIVATE-TOKEN", decryptedSystem.getToken());
            }
            case OAUTH -> {
                // OAuth认证
                headers.set("Authorization", "Bearer " + decryptedSystem.getToken());
            }
            default -> throw new RuntimeException("Unsupported authentication type: " + decryptedSystem.getAuthType());
        }

        return headers;
    }

    @Override
    public GitBranchResponse getBranch(ExternalSystem system, Long projectId, String branchName) {
        try {
            // GitLab API: GET /projects/:id/repository/branches/:branch
            String url = String.format("%s/api/v4/projects/%d/repository/branches/%s", 
                    system.getUrl(), projectId, branchName);
            
            HttpHeaders headers = createHeaders(system);
            HttpEntity<String> entity = new HttpEntity<>(headers);
            
            ResponseEntity<GitBranchResponse> response = restTemplate.exchange(
                url,
                HttpMethod.GET,
                entity,
                GitBranchResponse.class
            );
            
            return response.getBody();
        } catch (Exception e) {
            log.warn("Failed to get branch {} for project {}: {}", branchName, projectId, e.getMessage());
            return null;
        }
    }

    @Override
    public List<com.qqchen.deploy.backend.deploy.integration.response.GitCommitResponse> getCommits(
            ExternalSystem system, 
            Long projectId, 
            String branchName, 
            int limit) {
        
        try {
            // GitLab API: GET /projects/:id/repository/commits?ref_name=:branch&per_page=:limit
            String url = String.format("%s/api/v4/projects/%d/repository/commits?ref_name=%s&per_page=%d", 
                    system.getUrl(), projectId, branchName, limit);
            
            HttpHeaders headers = createHeaders(system);
            HttpEntity<String> entity = new HttpEntity<>(headers);
            
            ResponseEntity<List<com.qqchen.deploy.backend.deploy.integration.response.GitCommitResponse>> response = 
                    restTemplate.exchange(
                        url,
                        HttpMethod.GET,
                        entity,
                        new ParameterizedTypeReference<>() {}
                    );
            
            List<com.qqchen.deploy.backend.deploy.integration.response.GitCommitResponse> commits = response.getBody();
            log.info("获取到{}个提交记录 - 项目: {}, 分支: {}", 
                    commits != null ? commits.size() : 0, projectId, branchName);
            
            return commits != null ? commits : Collections.emptyList();
            
        } catch (Exception e) {
            log.error("获取提交记录失败 - 项目: {}, 分支: {}", projectId, branchName, e);
            return Collections.emptyList();
        }
    }
}