"""Gitea服务，处理与Gitea相关的业务逻辑"""

import os
import subprocess
import logging
import base64
from typing import Optional, Dict, Any, List
import uuid

from app.gitea.client import GiteaClient
from app.config.settings import settings
from app.models.database import SessionLocal
from app.models.models import GiteaConfig

logger = logging.getLogger(__name__)


class GiteaService:
    """Gitea服务类"""
    
    def __init__(self):
        """初始化Gitea服务"""
        self.config = self._load_config()
        self.client = None
        if self.config:
            self.client = GiteaClient(
                self.config['server_url'],
                self.config['access_token']
            )
    
    def _load_config(self) -> Optional[Dict[str, Any]]:
        """加载Gitea配置
        
        Returns:
            Gitea配置信息
        """
        try:
            db = SessionLocal()
            # 从数据库中获取配置（只取第一个配置）
            config = db.query(GiteaConfig).filter_by(status="active").first()
            db.close()
            
            if config:
                return {
                    'id': config.id,
                    'server_url': config.server_url,
                    'access_token': config.access_token,
                    'default_owner': config.default_owner,
                    'repo_prefix': config.repo_prefix,
                    'status': config.status
                }
            
            # 配置不存在时返回默认值
            return {
                'server_url': getattr(settings, 'GITEA_SERVER_URL', ''),
                'access_token': getattr(settings, 'GITEA_ACCESS_TOKEN', ''),
                'default_owner': getattr(settings, 'GITEA_DEFAULT_OWNER', ''),
                'repo_prefix': getattr(settings, 'GITEA_REPO_PREFIX', '')
            }
        except Exception as e:
            logger.error(f"Failed to load Gitea config from database: {str(e)}")
            # 出错时返回默认配置
            return {
                'server_url': getattr(settings, 'GITEA_SERVER_URL', ''),
                'access_token': getattr(settings, 'GITEA_ACCESS_TOKEN', ''),
                'default_owner': getattr(settings, 'GITEA_DEFAULT_OWNER', ''),
                'repo_prefix': getattr(settings, 'GITEA_REPO_PREFIX', '')
            }
    
    def save_config(self, config: Dict[str, Any]) -> bool:
        """保存Gitea配置
        
        Args:
            config: Gitea配置信息
            
        Returns:
            是否保存成功
        """
        try:
            db = SessionLocal()
            
            # 将所有现有配置设置为非活动状态
            db.query(GiteaConfig).update({GiteaConfig.status: "inactive"})
            
            # 检查是否已有配置
            existing_config = db.query(GiteaConfig).first()
            
            if existing_config:
                # 更新现有配置
                existing_config.server_url = config['server_url']
                existing_config.access_token = config['access_token']
                existing_config.default_owner = config['default_owner']
                existing_config.repo_prefix = config.get('repo_prefix', '')
                existing_config.status = "active"
            else:
                # 创建新配置
                new_config = GiteaConfig(
                    id=f"gitea-config-{uuid.uuid4()}",
                    server_url=config['server_url'],
                    access_token=config['access_token'],
                    default_owner=config['default_owner'],
                    repo_prefix=config.get('repo_prefix', ''),
                    status="active"
                )
                db.add(new_config)
            
            db.commit()
            db.close()
            
            # 更新内存中的配置
            self.config = config
            self.client = GiteaClient(
                config['server_url'],
                config['access_token']
            )
            
            logger.info("Gitea config saved to database successfully")
            return True
        except Exception as e:
            logger.error(f"Failed to save Gitea config to database: {str(e)}")
            return False
    
    def get_config(self) -> Optional[Dict[str, Any]]:
        """获取Gitea配置
        
        Returns:
            Gitea配置信息
        """
        return self.config
    
    def test_connection(self) -> bool:
        """测试Gitea连接
        
        Returns:
            是否连接成功
        """
        if not self.client:
            return False
        return self.client.check_connection()
    
    def create_repository(self, algorithm_id: str, algorithm_name: str, description: str = "") -> Optional[Dict[str, Any]]:
        """为算法创建Gitea仓库
        
        Args:
            algorithm_id: 算法ID
            algorithm_name: 算法名称
            description: 仓库描述
            
        Returns:
            创建的仓库信息
        """
        try:
            if not self.client:
                logger.error("Gitea client not initialized. Please check your Gitea configuration.")
                return None
            
            if not self.config.get('default_owner'):
                logger.error("Default owner not set in Gitea configuration.")
                return None
            
            # 记录传入的algorithm_id
            logger.info(f"Received algorithm_id: {algorithm_id}")
            
            # 检查是否已经包含前缀
            repo_prefix = self.config.get('repo_prefix', '')
            if repo_prefix and algorithm_id.startswith(repo_prefix):
                logger.info(f"Algorithm ID already contains prefix: {repo_prefix}")
                repo_name = algorithm_id
            else:
                # 生成仓库名称，添加前缀
                repo_name = f"{repo_prefix}{algorithm_id}" if repo_prefix else algorithm_id
                logger.info(f"Generated repository name: {repo_name}")
            
            logger.info(f"Creating repository: {repo_name} for owner: {self.config['default_owner']}")
            
            # 创建仓库
            repo = self.client.create_repository(
                self.config['default_owner'],
                repo_name,
                description or f"Algorithm repository for {algorithm_name}",
                False
            )
            
            if repo:
                logger.info(f"Repository created successfully: {repo}")
                # 验证仓库是否真的存在
                verify_repo = self.client.get_repository(self.config['default_owner'], repo_name)
                if not verify_repo:
                    logger.error(f"Repository creation verified failed: {repo_name}")
                    return None
            else:
                logger.error(f"Failed to create repository: {repo_name}")
            
            return repo
        except Exception as e:
            logger.error(f"Failed to create repository: {str(e)}")
            return None
    
    def clone_repository(self, repo_url: str, algorithm_id: str, branch: str = "main") -> bool:
        """克隆Gitea仓库
        
        Args:
            repo_url: 仓库URL
            algorithm_id: 算法ID
            branch: 分支名称
            
        Returns:
            是否克隆成功
        """
        try:
            # 创建本地目录
            repo_dir = f"/tmp/algorithms/{algorithm_id}"
            
            logger.info(f"Cloning repository to: {repo_dir}")
            
            # 导入需要的模块
            import shutil
            import subprocess
            
            # 如果目录已存在，先清理它
            if os.path.exists(repo_dir):
                logger.info(f"Cleaning existing repository directory: {repo_dir}")
                try:
                    shutil.rmtree(repo_dir)
                    logger.info(f"Successfully cleaned directory: {repo_dir}")
                except Exception as e:
                    logger.error(f"Failed to clean directory: {str(e)}")
                    # 尝试使用sudo删除（如果有权限）
                    try:
                        subprocess.run(["sudo", "rm", "-rf", repo_dir], check=True)
                        logger.info(f"Successfully cleaned directory with sudo: {repo_dir}")
                    except Exception as e2:
                        logger.error(f"Failed to clean directory with sudo: {str(e2)}")
                        return False
            
            # 重新创建目录
            logger.info(f"Creating directory: {repo_dir}")
            os.makedirs(repo_dir, exist_ok=True)
            logger.info(f"Directory created successfully: {repo_dir}")
            
            # 克隆仓库
            cmd = ["git", "clone", "-b", branch, repo_url, repo_dir]
            logger.info(f"Running clone command: {' '.join(cmd)}")
            result = subprocess.run(cmd, capture_output=True, text=True)
            
            if result.returncode == 0:
                logger.info(f"Repository cloned successfully: {repo_url}")
                return True
            else:
                logger.error(f"Failed to clone repository: {result.stderr}")
                
                # 尝试初始化仓库
                logger.info(f"Trying to initialize repository in {repo_dir}")
                
                # 初始化git仓库
                init_result = subprocess.run(["git", "init"], cwd=repo_dir, capture_output=True, text=True)
                if init_result.returncode != 0:
                    logger.error(f"Failed to initialize git repository: {init_result.stderr}")
                    return False
                
                # 添加远程仓库
                remote_result = subprocess.run(["git", "remote", "add", "origin", repo_url], cwd=repo_dir, capture_output=True, text=True)
                if remote_result.returncode != 0:
                    logger.error(f"Failed to add remote repository: {remote_result.stderr}")
                    # 如果远程仓库已存在，尝试更新它
                    logger.info("Trying to update existing remote repository")
                    update_result = subprocess.run(["git", "remote", "set-url", "origin", repo_url], cwd=repo_dir, capture_output=True, text=True)
                    if update_result.returncode != 0:
                        logger.error(f"Failed to update remote repository: {update_result.stderr}")
                        return False
                    logger.info("Successfully updated remote repository")
                
                # 创建初始文件
                readme_path = os.path.join(repo_dir, "README.md")
                with open(readme_path, "w") as f:
                    f.write("# Algorithm Repository\n\nThis is an algorithm repository.\n")
                
                # 添加文件并提交
                add_result = subprocess.run(["git", "add", "README.md"], cwd=repo_dir, capture_output=True, text=True)
                if add_result.returncode != 0:
                    logger.error(f"Failed to add README.md: {add_result.stderr}")
                    return False
                
                commit_result = subprocess.run(["git", "commit", "-m", "Initial commit"], cwd=repo_dir, capture_output=True, text=True)
                if commit_result.returncode != 0:
                    logger.error(f"Failed to commit initial file: {commit_result.stderr}")
                    return False
                
                # 推送代码到远程仓库
                push_result = subprocess.run(["git", "push", "-u", "origin", branch], cwd=repo_dir, capture_output=True, text=True)
                if push_result.returncode != 0:
                    logger.error(f"Failed to push initial commit: {push_result.stderr}")
                    # 即使推送失败，初始化仓库也算成功
                    logger.info(f"Repository initialized successfully, but push failed: {push_result.stderr}")
                    return True
                
                logger.info(f"Repository initialized and pushed successfully: {repo_url}")
                return True
                
        except Exception as e:
            logger.error(f"Failed to clone repository: {str(e)}")
            return False
    
    def push_to_repository(self, algorithm_id: str, message: str = "Update code") -> bool:
        """推送代码到Gitea仓库
        
        Args:
            algorithm_id: 算法ID
            message: 提交消息
            
        Returns:
            是否推送成功
        """
        try:
            logger.info("=== 开始推送代码到Gitea仓库 ===")
            logger.info(f"Algorithm ID: {algorithm_id}")
            logger.info(f"Commit message: {message}")
            
            repo_dir = f"/tmp/algorithms/{algorithm_id}"
            logger.info(f"Repository directory: {repo_dir}")
            
            if not os.path.exists(repo_dir):
                logger.error(f"❌ Repository directory not found: {repo_dir}")
                return False
            
            # 首先尝试使用API上传（推荐方法，避免Git推送限制）
            logger.info("Attempting to upload files via Gitea API...")
            api_upload_success = self.upload_files_via_api(algorithm_id, message)
            
            if api_upload_success:
                logger.info(f"✅ Code uploaded successfully via API for algorithm: {algorithm_id}")
                return True
            else:
                logger.warning("❌ API upload failed, falling back to Git push...")
            
            # 如果API上传失败，回退到原来的Git推送方法
            import subprocess
            
            # 检查是否是git仓库
            git_dir = os.path.join(repo_dir, ".git")
            if not os.path.exists(git_dir):
                logger.info(f"⚠️  Git repository not initialized, initializing...")
                # 初始化git仓库
                logger.info(f"Executing: git init in {repo_dir}")
                init_result = subprocess.run(["git", "init"], cwd=repo_dir, capture_output=True, text=True)
                logger.info(f"Git init output: {init_result.stdout}")
                if init_result.stderr:
                    logger.warning(f"Git init stderr: {init_result.stderr}")
                if init_result.returncode != 0:
                    logger.error(f"❌ Failed to initialize git repository: {init_result.stderr}")
                    return False
                logger.info("✅ Git repository initialized successfully")
                
                # 添加远程仓库（从配置中获取，包含访问令牌以确保认证）
                if self.config.get('default_owner'):
                    # 使用访问令牌构建认证URL
                    auth_repo_url = f"https://{self.config['access_token']}@{self.config['server_url'].replace('https://', '').replace('http://', '')}/{self.config['default_owner']}/{algorithm_id}.git"
                    logger.info(f"Adding remote repository: {auth_repo_url}")
                    remote_result = subprocess.run(["git", "remote", "add", "origin", auth_repo_url], cwd=repo_dir, capture_output=True, text=True)
                    logger.info(f"Git remote add output: {remote_result.stdout}")
                    if remote_result.stderr:
                        logger.warning(f"Git remote add stderr: {remote_result.stderr}")
                    if remote_result.returncode != 0:
                        logger.error(f"❌ Failed to add remote repository: {remote_result.stderr}")
                        return False
                    logger.info("✅ Remote repository added successfully")
            else:
                logger.info("✅ Git repository already initialized")
            
            # 执行git命令 - 分批添加文件以处理大量文件
            logger.info("=== 执行Git操作 ===")
            
            # 获取所有需要添加的文件
            all_files = []
            for root, dirs, files in os.walk(repo_dir):
                if '.git' in root:
                    continue
                for file in files:
                    if not file.endswith('.git'):
                        file_path = os.path.relpath(os.path.join(root, file), repo_dir)
                        all_files.append(file_path)
            
            logger.info(f"Total files to add: {len(all_files)}")
            
            # 分批添加文件，避免命令行参数过长
            batch_size = 100  # 每次添加100个文件
            for i in range(0, len(all_files), batch_size):
                batch = all_files[i:i + batch_size]
                logger.info(f"Adding batch {i//batch_size + 1}: {len(batch)} files")
                
                add_result = subprocess.run(["git", "add"] + batch, cwd=repo_dir, capture_output=True, text=True)
                if add_result.stderr and add_result.returncode != 0:
                    logger.error(f"❌ Git add batch {i//batch_size + 1} failed: {add_result.stderr}")
                    return False
                elif add_result.stderr:
                    logger.warning(f"Git add batch {i//batch_size + 1} warning: {add_result.stderr}")
            
            logger.info("✅ Git add completed successfully")
            
            # 检查是否有更改需要提交
            logger.info("Executing: git status --porcelain")
            status_result = subprocess.run(["git", "status", "--porcelain"], cwd=repo_dir, capture_output=True, text=True)
            logger.info(f"Git status output: {status_result.stdout}")
            if status_result.stderr:
                logger.warning(f"Git status stderr: {status_result.stderr}")
            if status_result.returncode != 0:
                logger.error(f"❌ Git status failed: {status_result.stderr}")
                return False
            
            # 如果有更改，执行commit和push
            if status_result.stdout.strip():
                logger.info("✅ Changes detected, proceeding with commit and push")
                # 执行git commit
                logger.info(f"Executing: git commit -m '{message}'")
                commit_result = subprocess.run(["git", "commit", "-m", message], cwd=repo_dir, capture_output=True, text=True)
                logger.info(f"Git commit output: {commit_result.stdout}")
                if commit_result.stderr:
                    logger.warning(f"Git commit stderr: {commit_result.stderr}")
                if commit_result.returncode != 0:
                    logger.error(f"❌ Git commit failed: {commit_result.stderr}")
                    return False
                logger.info("✅ Git commit completed successfully")
                
                # 检查仓库大小
                logger.info("Checking repository size before push")
                total_size = 0
                for dirpath, dirnames, filenames in os.walk(repo_dir):
                    for filename in filenames:
                        filepath = os.path.join(dirpath, filename)
                        if not filepath.startswith(os.path.join(repo_dir, '.git')):
                            total_size += os.path.getsize(filepath)
                logger.info(f"Repository size (excluding .git): {total_size / (1024 * 1024):.2f} MB")
                
                if total_size > 100 * 1024 * 1024:  # 100MB
                    logger.warning(f"Repository is large: {total_size / (1024 * 1024):.2f} MB")
                    logger.warning("This may cause HTTP 413 errors on push")
                
                # 设置Git推送缓冲区大小（增加到1GB）
                logger.info("Setting Git http.postBuffer to 1GB")
                buffer_result = subprocess.run(["git", "config", "http.postBuffer", "1073741824"], cwd=repo_dir, capture_output=True, text=True)
                if buffer_result.returncode != 0:
                    logger.warning(f"Failed to set http.postBuffer: {buffer_result.stderr}")
                else:
                    logger.info("✅ Git http.postBuffer set successfully")
                
                # 禁用Git压缩
                logger.info("Disabling Git compression")
                compression_result = subprocess.run(["git", "config", "core.compression", "0"], cwd=repo_dir, capture_output=True, text=True)
                if compression_result.returncode != 0:
                    logger.warning(f"Failed to set core.compression: {compression_result.stderr}")
                else:
                    logger.info("✅ Git core.compression disabled successfully")
                
                # 针对大仓库优化的推送命令
                logger.info("Setting additional Git configs for large repositories...")
                subprocess.run(["git", "config", "http.postBuffer", "524288000"], cwd=repo_dir)  # 500MB buffer
                subprocess.run(["git", "config", "pack.windowMemory", "128m"], cwd=repo_dir)    # Limit memory usage
                subprocess.run(["git", "config", "pack.packSizeLimit", "128m"], cwd=repo_dir)   # Limit pack size
                
                # 执行git push，添加更多优化参数
                logger.info("Executing: git push with optimizations for large repositories")
                push_result = subprocess.run([
                    "git", "push", 
                    "--verbose", 
                    "-u", "origin", "main",
                    "--receive-pack='git receive-pack'",  # Ensure proper receive pack
                    "--progress"  # Show progress for large pushes
                ], cwd=repo_dir, capture_output=True, text=True, timeout=300)  # 5 minute timeout
                logger.info(f"Git push output: {push_result.stdout}")
                if push_result.stderr:
                    logger.warning(f"Git push stderr: {push_result.stderr}")
                if push_result.returncode != 0:
                    # 检查是否是常见的大文件错误
                    error_msg = push_result.stderr.lower()
                    is_large_file_error = (
                        "http 413" in error_msg or 
                        "payload too large" in error_msg or 
                        "unpack failed" in error_msg or 
                        "remote: fatal" in error_msg or
                        "cannot spawn" in error_msg or
                        "timeout" in error_msg
                    )
                    
                    if is_large_file_error:
                        logger.error(f"❌ Git push failed likely due to repository size: {total_size / (1024 * 1024):.2f} MB")
                        logger.error(f"Error details: {push_result.stderr}")
                        logger.error("\n📋 解决方案建议：")
                        logger.error("1. 检查Gitea服务器配置，增加MAX_UPLOAD_SIZE限制")
                        logger.error("2. 尝试使用SSH协议进行推送（如果服务器支持）")
                        logger.error("3. 优化仓库大小，移除不必要的大文件")
                        logger.error("4. 考虑使用Git LFS（Large File Storage）管理大文件")
                        
                        # 尝试使用SSH协议进行推送（如果URL是HTTPS格式）
                        logger.info("\n🔄 尝试使用SSH协议进行推送...")
                        try:
                            # 获取当前远程URL
                            remote_result = subprocess.run(["git", "remote", "get-url", "origin"], cwd=repo_dir, capture_output=True, text=True, timeout=30)
                            if remote_result.returncode == 0:
                                https_url = remote_result.stdout.strip()
                                # 将HTTPS URL转换为SSH URL
                                if https_url.startswith("https://"):
                                    ssh_url = https_url.replace("https://", "git@").replace(":", "/")
                                    logger.info(f"Converting HTTPS URL to SSH URL: {ssh_url}")
                                    # 更新远程URL
                                    set_url_result = subprocess.run(["git", "remote", "set-url", "origin", ssh_url], cwd=repo_dir, capture_output=True, text=True, timeout=30)
                                    if set_url_result.returncode == 0:
                                        logger.info("✅ Remote URL updated to SSH format")
                                        # 再次尝试推送，使用更保守的参数
                                        logger.info("Executing: git push with SSH and conservative parameters")
                                        ssh_push_result = subprocess.run([
                                            "git", "push", 
                                            "--verbose", 
                                            "-u", "origin", "main"
                                        ], cwd=repo_dir, capture_output=True, text=True, timeout=600)  # 10 minute timeout for SSH
                                        
                                        if ssh_push_result.returncode == 0:
                                            logger.info("✅ Git push completed successfully with SSH")
                                            # 改回HTTPS URL
                                            reset_url_result = subprocess.run(["git", "remote", "set-url", "origin", https_url], cwd=repo_dir, capture_output=True, text=True, timeout=30)
                                            if reset_url_result.returncode != 0:
                                                logger.warning(f"Failed to reset remote URL to HTTPS: {reset_url_result.stderr}")
                                            return True
                                        else:
                                            logger.warning(f"SSH push failed: {ssh_push_result.stderr}")
                                            # 改回HTTPS URL
                                            reset_url_result = subprocess.run(["git", "remote", "set-url", "origin", https_url], cwd=repo_dir, capture_output=True, text=True, timeout=30)
                                            if reset_url_result.returncode != 0:
                                                logger.warning(f"Failed to reset remote URL to HTTPS: {reset_url_result.stderr}")
                                            
                                            # 如果SSH也失败，尝试分阶段推送
                                            logger.info("\n🔄 尝试分阶段推送...")
                                            return self.push_repository_staged(repo_dir, https_url)
                            else:
                                logger.warning(f"Could not get remote URL: {remote_result.stderr}")
                        except subprocess.TimeoutExpired:
                            logger.warning("Remote URL command timed out")
                        except Exception as e:
                            logger.warning(f"Failed to try SSH push: {str(e)}")
                    else:
                        logger.error(f"❌ Git push failed: {push_result.stderr}")
                    return False
                logger.info("✅ Git push completed successfully")
            else:
                logger.info("ℹ️  No changes to commit")
            
            logger.info(f"✅ Code pushed successfully for algorithm: {algorithm_id}")
            return True
            
        except Exception as e:
            logger.error(f"=== 推送代码失败 ===")
            logger.error(f"Error: {str(e)}")
            import traceback
            logger.error(f"Traceback: {traceback.format_exc()}")
            return False
    
    def pull_from_repository(self, algorithm_id: str) -> bool:
        """从Gitea仓库拉取代码
        
        Args:
            algorithm_id: 算法ID
            
        Returns:
            是否拉取成功
        """
        try:
            repo_dir = f"/tmp/algorithms/{algorithm_id}"
            
            if not os.path.exists(repo_dir):
                logger.error(f"Repository directory not found: {repo_dir}")
                return False
            
            # 执行git pull命令
            result = subprocess.run(
                ["git", "pull"],
                cwd=repo_dir,
                capture_output=True,
                text=True
            )
            
            if result.returncode == 0:
                logger.info(f"Code pulled successfully for algorithm: {algorithm_id}")
                return True
            else:
                logger.error(f"Failed to pull code: {result.stderr}")
                return False
                
        except Exception as e:
            logger.error(f"Failed to pull code: {str(e)}")
            return False
    
    def push_repository_staged(self, repo_dir: str, origin_url: str) -> bool:
        """
        分阶段推送仓库，用于处理超大仓库
        """
        try:
            import subprocess
            import os
            
            logger.info("=== 开始分阶段推送仓库 ===")
            logger.info(f"Repository directory: {repo_dir}")
            
            # 获取所有文件并按类型分组
            all_files = []
            for root, dirs, files in os.walk(repo_dir):
                # 跳过 .git 目录
                if '.git' in root:
                    continue
                for file in files:
                    file_path = os.path.relpath(os.path.join(root, file), repo_dir)
                    if file_path.startswith('.git'):
                        continue
                    all_files.append(file_path)
            
            logger.info(f"Total files to stage: {len(all_files)}")
            
            # 按扩展名分类文件，优先推送小文件
            def get_file_size(file_path):
                try:
                    return os.path.getsize(os.path.join(repo_dir, file_path))
                except:
                    return 0
            
            # 按文件大小排序（从小到大）
            sorted_files = sorted(all_files, key=get_file_size)
            
            # 分批处理，每批最多50个文件或不超过50MB
            batch_size_limit = 50
            batch_size_bytes = 50 * 1024 * 1024  # 50MB
            
            current_batch = []
            current_batch_size = 0
            batch_number = 1
            
            for file_path in sorted_files:
                file_full_path = os.path.join(repo_dir, file_path)
                file_size = get_file_size(file_path)
                
                # 如果单个文件太大，单独处理
                if file_size > batch_size_bytes:
                    logger.info(f"Handling large file separately: {file_path} ({file_size / (1024*1024):.2f}MB)")
                    # 单独添加和推送这个大文件
                    add_result = subprocess.run(["git", "add", file_path], cwd=repo_dir, capture_output=True, text=True)
                    if add_result.returncode != 0:
                        logger.error(f"Failed to add large file {file_path}: {add_result.stderr}")
                        continue
                    
                    # 检查是否有暂存的更改
                    status_result = subprocess.run(["git", "status", "--porcelain"], cwd=repo_dir, capture_output=True, text=True)
                    if status_result.stdout.strip():
                        # 创建专门的提交
                        commit_msg = f"Add large file: {file_path}"
                        commit_result = subprocess.run(["git", "commit", "-m", commit_msg], cwd=repo_dir, capture_output=True, text=True)
                        if commit_result.returncode == 0:
                            logger.info(f"Committed large file: {file_path}")
                            
                            # 推送这个提交
                            push_result = subprocess.run([
                                "git", "push", "--verbose", "origin", "main"
                            ], cwd=repo_dir, capture_output=True, text=True, timeout=300)
                            
                            if push_result.returncode != 0:
                                logger.warning(f"Push failed for large file {file_path}: {push_result.stderr}")
                                # 如果推送失败，尝试重置这个文件的暂存状态
                                subprocess.run(["git", "reset", "HEAD", file_path], cwd=repo_dir, capture_output=True, text=True)
                            else:
                                logger.info(f"Successfully pushed large file: {file_path}")
                        else:
                            logger.error(f"Failed to commit large file {file_path}: {commit_result.stderr}")
                else:
                    # 尝试添加到当前批次
                    if (len(current_batch) >= batch_size_limit or 
                        current_batch_size + file_size > batch_size_bytes):
                        # 推送当前批次
                        if current_batch:
                            logger.info(f"Pushing batch {batch_number} with {len(current_batch)} files...")
                            success = self.push_batch(repo_dir, current_batch, batch_number, origin_url)
                            if not success:
                                logger.error(f"Failed to push batch {batch_number}")
                                return False
                            batch_number += 1
                            current_batch = []
                            current_batch_size = 0
                        
                    current_batch.append(file_path)
                    current_batch_size += file_size
            
            # 推送最后一批
            if current_batch:
                logger.info(f"Pushing final batch {batch_number} with {len(current_batch)} files...")
                success = self.push_batch(repo_dir, current_batch, batch_number, origin_url)
                if not success:
                    logger.error(f"Failed to push final batch {batch_number}")
                    return False
            
            logger.info("✅ 分阶段推送完成")
            return True
            
        except Exception as e:
            logger.error(f"❌ 分阶段推送失败: {str(e)}")
            import traceback
            logger.error(f"Traceback: {traceback.format_exc()}")
            return False
    
    def push_batch(self, repo_dir: str, file_batch: list, batch_num: int, origin_url: str) -> bool:
        """
        推送文件批次
        """
        try:
            import subprocess
            
            logger.info(f"Processing batch {batch_num}: {len(file_batch)} files")
            
            # 添加批次中的文件
            for file_path in file_batch:
                add_result = subprocess.run(["git", "add", file_path], cwd=repo_dir, capture_output=True, text=True)
                if add_result.returncode != 0:
                    logger.error(f"Failed to add file {file_path}: {add_result.stderr}")
                    return False
            
            # 检查是否有更改需要提交
            status_result = subprocess.run(["git", "status", "--porcelain"], cwd=repo_dir, capture_output=True, text=True)
            if not status_result.stdout.strip():
                logger.info(f"No changes in batch {batch_num}")
                return True
            
            # 提交批次
            commit_result = subprocess.run([
                "git", "commit", "-m", f"Batch {batch_num}: Add {len(file_batch)} files"
            ], cwd=repo_dir, capture_output=True, text=True)
            
            if commit_result.returncode != 0:
                logger.warning(f"Commit failed or no changes for batch {batch_num}: {commit_result.stderr}")
                # 即使没有更改，也可能正常（比如文件没变）
            
            # 推送批次
            push_result = subprocess.run([
                "git", "push", "--verbose", "origin", "main"
            ], cwd=repo_dir, capture_output=True, text=True, timeout=300)
            
            if push_result.returncode == 0:
                logger.info(f"✅ Batch {batch_num} pushed successfully")
                return True
            else:
                logger.error(f"❌ Batch {batch_num} push failed: {push_result.stderr}")
                return False
                
        except subprocess.TimeoutExpired:
            logger.error(f"❌ Batch {batch_num} push timed out")
            return False
        except Exception as e:
            logger.error(f"❌ Batch {batch_num} push failed with error: {str(e)}")
            return False
    
    def get_repository_info(self, repo_owner: str, repo_name: str) -> Optional[Dict[str, Any]]:
        """获取仓库信息
        
        Args:
            repo_owner: 仓库所有者
            repo_name: 仓库名称
            
        Returns:
            仓库信息
        """
        if not self.client:
            return None
        
        return self.client.get_repository(repo_owner, repo_name)
    
    def list_repositories(self, owner: Optional[str] = None) -> Optional[List[Dict[str, Any]]]:
        """列出仓库
        
        Args:
            owner: 所有者（用户或组织）
            
        Returns:
            仓库列表
        """
        if not self.client:
            return None
        
        target_owner = owner or self.config.get('default_owner')
        if not target_owner:
            return None
        
        return self.client.list_repositories(target_owner)
    
    def register_algorithm_from_repo(self, repo_owner: str, repo_name: str, algorithm_id: str) -> bool:
        """从仓库注册算法服务
        
        Args:
            repo_owner: 仓库所有者
            repo_name: 仓库名称
            algorithm_id: 算法ID
            
        Returns:
            是否注册成功
        """
        try:
            # 这里应该实现从仓库注册算法服务的逻辑
            # 1. 克隆仓库
            # 2. 扫描仓库中的算法代码
            # 3. 注册算法服务
            
            logger.info(f"Algorithm registered from repo: {repo_owner}/{repo_name}")
            return True
            
        except Exception as e:
            logger.error(f"Failed to register algorithm from repo: {str(e)}")
            return False


            
            # 递归遍历目录中的所有文件
            for root, dirs, files in os.walk(repo_dir):
                # 跳过 .git 目录
                if '.git' in root:
                    continue
                    
                for file in files:
                    file_path = os.path.relpath(os.path.join(root, file), repo_dir)
                    if file_path.startswith('.git'):
                        continue
                        
                    full_file_path = os.path.join(root, file)
                    
                    # 读取文件内容并进行base64编码
                    try:
                        with open(full_file_path, 'rb') as f:
                            file_content = f.read()
                        encoded_content = base64.b64encode(file_content).decode('utf-8')
                        
                        # 使用Gitea API创建或更新文件
                        if self.client:
                            # 移除开头的./，如果有的话
                            clean_path = file_path.lstrip('./\\')
                            result = self.client.create_file(
                                self.config["default_owner"], 
                                algorithm_id, 
                                clean_path, 
                                encoded_content, 
                                f"{message} - Upload {clean_path}"
                            )
                            
                            if result:
                                logger.info(f"✅ File uploaded via API: {clean_path}")
                            else:
                                logger.error(f"❌ Failed to upload file via API: {clean_path}")
                                return False
                        else:
                            logger.error("❌ Gitea client not initialized")
                            return False
                    except Exception as e:
                        logger.error(f"❌ Error processing file {file_path}: {str(e)}")
                        return False
            
            logger.info(f"✅ All files uploaded successfully via API for algorithm: {algorithm_id}")
            return True
            
        except Exception as e:
            logger.error(f"❌ Failed to upload files via API: {str(e)}")
            import traceback
            logger.error(f"Traceback: {traceback.format_exc()}")
            return False


# 全局Gitea服务实例
gitea_service = GiteaService()
