import os
import yaml
import git
import subprocess
from pathlib import Path
from typing import Optional, List, Dict, Any
from backend.config import config


class GitService:
    """Git集成服务 - 使用oc-collab CLI"""
    
    def __init__(self, base_path: Optional[str] = None):
        self.base_path = Path(base_path) if base_path else Path("./data/repos")
        self.base_path.mkdir(parents=True, exist_ok=True)
        
        self.default_branch = config.get("git.default_branch", "main")
        self.user_name = config.get("git.user_name", "PM-Agent")
        self.user_email = config.get("git.user_email", "pm-agent@local")
    
    def clone(self, repo_url: str, local_path: Optional[str] = None) -> str:
        """克隆仓库"""
        if local_path is None:
            repo_name = repo_url.split('/')[-1].replace('.git', '')
            local_path = str(self.base_path / repo_name)
        
        if os.path.exists(local_path):
            return local_path
        
        git.Repo.clone_from(repo_url, local_path)
        
        repo = git.Repo(local_path)
        if repo.config_reader().has_section("user"):
            pass
        else:
            with repo.config_writer() as w:
                w.set_value("user", "name", self.user_name)
                w.set_value("user", "email", self.user_email)
        
        return local_path
    
    def pull(self, local_path: str) -> bool:
        """拉取更新"""
        try:
            repo = git.Repo(local_path)
            origin = repo.remotes.origin
            origin.pull()
            return True
        except Exception as e:
            print(f"Pull failed: {e}")
            return False
    
    def create_requirement(
        self, 
        project_path: str, 
        requirement: Dict[str, Any]
    ) -> str:
        """创建oc-collab需求"""
        req_path = Path(project_path) / "docs" / "01-requirements"
        req_path.mkdir(parents=True, exist_ok=True)
        
        filename = f"REQ-{requirement.get('id', '001')}.md"
        
        content = self._format_requirement(requirement)
        (req_path / filename).write_text(content, encoding='utf-8')
        
        return self._commit_and_push(project_path, str(req_path / filename), f"Add requirement: {filename}")
    
    def create_bug_report(
        self, 
        project_path: str, 
        bug_id: str, 
        content: str
    ) -> str:
        """创建BUG报告"""
        bug_path = Path(project_path) / "docs" / "00-memos"
        bug_path.mkdir(parents=True, exist_ok=True)
        
        filename = f"{bug_id}.md"
        (bug_path / filename).write_text(content, encoding='utf-8')
        
        return self._commit_and_push(project_path, str(bug_path / filename), f"Add bug report: {filename}")
    
    def create_proposal(
        self, 
        project_path: str, 
        proposal_id: str, 
        content: str
    ) -> str:
        """创建Proposal"""
        prop_path = Path(project_path) / "docs" / "04-proposals"
        prop_path.mkdir(parents=True, exist_ok=True)
        
        filename = f"{proposal_id}.md"
        (prop_path / filename).write_text(content, encoding='utf-8')
        
        return self._commit_and_push(project_path, str(prop_path / filename), f"Add proposal: {filename}")
    
    def create_todo(
        self, 
        project_path: str, 
        todo: Dict[str, Any]
    ) -> str:
        """创建oc-collab TODO"""
        todo_path = Path(project_path) / "state" / "agent_adhoc_todos.yaml"
        
        todos = []
        if todo_path.exists():
            content = todo_path.read_text(encoding='utf-8')
            if content.strip():
                try:
                    todos = yaml.safe_load(content) or []
                    if not isinstance(todos, list):
                        todos = []
                except:
                    todos = []
        
        todos.append({
            'id': todo.get('id'),
            'content': todo.get('content'),
            'priority': todo.get('priority', 'medium'),
            'status': 'pending',
            'agent_id': todo.get('agent_id', 2),
            'created_at': todo.get('created_at')
        })
        
        todo_path.parent.mkdir(parents=True, exist_ok=True)
        todo_path.write_text(yaml.dump(todos, allow_unicode=True), encoding='utf-8')
        
        return self._commit_and_push(project_path, str(todo_path), f"Add TODO: {todo.get('id')}")
    
    def fetch_development_docs(self, project_path: str) -> List[Dict[str, str]]:
        """拉取开发文档"""
        docs_path = Path(project_path)
        
        documents = []
        for pattern in ["**/*.md", "**/*.pdf"]:
            for p in docs_path.glob(pattern):
                if '.git' not in str(p):
                    documents.append({
                        "path": str(p),
                        "name": p.name,
                        "relative_path": str(p.relative_to(docs_path))
                    })
        
        return documents
    
    def get_recent_commits(self, local_path: str, count: int = 10) -> List[Any]:
        """获取最近提交"""
        try:
            repo = git.Repo(local_path)
            commits = list(repo.iter_commits(max_count=count))
            return commits
        except:
            return []
    
    def check_requirement_completed(self, project_path: str, req_id: str) -> bool:
        """检查需求是否已完成"""
        req_path = Path(project_path) / "docs" / "01-requirements" / f"{req_id}.md"
        
        if not req_path.exists():
            return False
        
        content = req_path.read_text(encoding='utf-8')
        return "状态: 已完成" in content or "status: completed" in content.lower()
    
    def _commit_and_push(self, project_path: str, file_path: str, message: str) -> str:
        """使用oc-collab CLI提交并推送"""
        try:
            repo = git.Repo(project_path)
            
            file_path_abs = file_path if os.path.isabs(file_path) else os.path.join(project_path, file_path)
            if not os.path.exists(file_path_abs):
                print(f"File not found: {file_path_abs}")
                return ""
            
            repo.index.add([file_path])
            
            if repo.index.diff("HEAD"):
                repo.index.commit(message)
                
                if config.get("git.auto_push", False):
                    result = subprocess.run(
                        ["oc-collab", "push", "-m", message],
                        cwd=project_path,
                        capture_output=True,
                        text=True
                    )
                    if result.returncode == 0:
                        return repo.head.commit.hexsha
                    else:
                        print(f"oc-collab push failed: {result.stderr}")
                        return repo.head.commit.hexsha
                
                return repo.head.commit.hexsha
            
            return ""
        except Exception as e:
            print(f"Git commit failed: {e}")
            return ""
    
    def _format_requirement(self, requirement: Dict[str, Any]) -> str:
        """格式化需求文档"""
        return f"""# 需求: {requirement.get('title', 'Untitled')}

**ID**: {requirement.get('id', 'N/A')}
**优先级**: {requirement.get('priority', 'P1')}
**状态**: DRAFT

---

## 1. 背景

{requirement.get('background', '无')}

---

## 2. 用户场景

{requirement.get('user_scenario', '无')}

---

## 3. 期望行为

{requirement.get('expected_behavior', '无')}

---

## 4. 验收标准

{requirement.get('acceptance_criteria', '- [ ] 验收项1')}

---

## 5. 估算工时

{requirement.get('estimated_hours', '待评估')} 小时
"""
