"""Analysis service - AI-powered issue analysis."""
import httpx
import json
from datetime import datetime
from typing import Optional, Dict, Any, List
from app.core.config import settings

class AnalysisService:
    OPENROUTER_API = "https://openrouter.ai/api/v1/chat/completions"
    MODEL = "meta-llama/llama-3.3-70b-instruct:free"
    
    @classmethod
    async def fetch_repository_files(cls, repo: str, path: str = "") -> List[Dict[str, str]]:
        """Fetch files from Gitea repository."""
        files = []
        async with httpx.AsyncClient() as client:
            try:
                url = f"{settings.GITEA_URL}/api/v1/repos/{repo}/contents/{path}"
                headers = {}
                if settings.GITEA_TOKEN:
                    headers["Authorization"] = f"token {settings.GITEA_TOKEN}"
                
                response = await client.get(url, headers=headers)
                if response.status_code != 200:
                    return files
                
                items = response.json()
                for item in items:
                    if item["type"] == "file" and item["name"].endswith((".cbl", ".cob", ".py", ".java", ".js", ".ts")):
                        content_resp = await client.get(item["download_url"], headers=headers)
                        if content_resp.status_code == 200:
                            files.append({
                                "path": item["path"],
                                "content": content_resp.text[:10000]  # Limit size
                            })
                    elif item["type"] == "dir":
                        sub_files = await cls.fetch_repository_files(repo, item["path"])
                        files.extend(sub_files)
            except Exception as e:
                print(f"Error fetching repo: {e}")
        
        return files[:20]  # Limit to 20 files
    
    @classmethod
    def build_prompt(cls, issue: Dict[str, Any], files: List[Dict[str, str]]) -> str:
        """Build analysis prompt for LLM."""
        files_context = "\n\n".join([
            f"### {f['path']}\n```\n{f['content']}\n```"
            for f in files
        ])
        
        return f"""You are an expert software engineer analyzing a support issue.

## Issue Details
**Title:** {issue.get('title', 'N/A')}
**Description:** {issue.get('description', 'N/A')}
**Priority:** {issue.get('priority', 'N/A')}

## Source Code Files
{files_context}

## Your Task
Analyze the issue and identify:
1. Root cause of the problem
2. Which files are affected
3. Suggested code fix

## Response Format (JSON)
{{
    "root_cause": "Detailed explanation of what's causing the issue",
    "affected_files": ["file1.py", "file2.py"],
    "suggested_fix": "Code changes needed to fix the issue",
    "confidence": 0.85,
    "explanation": "Step-by-step explanation of the fix"
}}

Respond ONLY with valid JSON."""
    
    @classmethod
    async def analyze(cls, issue: Dict[str, Any], repo: Optional[str] = None) -> Dict[str, Any]:
        """Run AI analysis on an issue."""
        # Fetch code context
        files = []
        if repo:
            files = await cls.fetch_repository_files(repo)
        
        # Build prompt
        prompt = cls.build_prompt(issue, files)
        
        # Call LLM
        if not settings.OPENROUTER_API_KEY:
            # Mock response for testing
            return {
                "root_cause": "Mock analysis - configure OPENROUTER_API_KEY for real analysis",
                "affected_files": ["example.py"],
                "suggested_fix": "# Mock fix",
                "confidence": 0.5,
                "explanation": "This is a mock response"
            }
        
        async with httpx.AsyncClient() as client:
            try:
                response = await client.post(
                    cls.OPENROUTER_API,
                    headers={
                        "Authorization": f"Bearer {settings.OPENROUTER_API_KEY}",
                        "Content-Type": "application/json"
                    },
                    json={
                        "model": cls.MODEL,
                        "messages": [{"role": "user", "content": prompt}],
                        "temperature": 0.2,
                        "max_tokens": 2000
                    },
                    timeout=120
                )
                
                if response.status_code == 200:
                    data = response.json()
                    content = data["choices"][0]["message"]["content"]
                    
                    # Parse JSON from response
                    try:
                        # Handle markdown code blocks
                        if "```json" in content:
                            content = content.split("```json")[1].split("```")[0]
                        elif "```" in content:
                            content = content.split("```")[1].split("```")[0]
                        
                        return json.loads(content.strip())
                    except json.JSONDecodeError:
                        return {
                            "root_cause": content[:500],
                            "affected_files": [],
                            "suggested_fix": "",
                            "confidence": 0.3,
                            "explanation": "Could not parse structured response"
                        }
                else:
                    return {
                        "root_cause": f"API error: {response.status_code}",
                        "affected_files": [],
                        "suggested_fix": "",
                        "confidence": 0,
                        "explanation": response.text[:500]
                    }
            except Exception as e:
                return {
                    "root_cause": f"Analysis error: {str(e)}",
                    "affected_files": [],
                    "suggested_fix": "",
                    "confidence": 0,
                    "explanation": str(e)
                }
    
    @classmethod
    async def create_pull_request(
        cls, 
        repo: str, 
        branch: str, 
        title: str, 
        description: str,
        file_changes: List[Dict[str, str]]
    ) -> Optional[str]:
        """Create a pull request with suggested fix."""
        if not settings.GITEA_TOKEN:
            return None
        
        async with httpx.AsyncClient() as client:
            headers = {"Authorization": f"token {settings.GITEA_TOKEN}"}
            
            try:
                # 1. Get default branch
                repo_resp = await client.get(
                    f"{settings.GITEA_URL}/api/v1/repos/{repo}",
                    headers=headers
                )
                if repo_resp.status_code != 200:
                    return None
                default_branch = repo_resp.json().get("default_branch", "main")
                
                # 2. Get latest commit SHA
                ref_resp = await client.get(
                    f"{settings.GITEA_URL}/api/v1/repos/{repo}/git/refs/heads/{default_branch}",
                    headers=headers
                )
                if ref_resp.status_code != 200:
                    return None
                sha = ref_resp.json()["object"]["sha"]
                
                # 3. Create branch
                await client.post(
                    f"{settings.GITEA_URL}/api/v1/repos/{repo}/git/refs",
                    headers=headers,
                    json={"ref": f"refs/heads/{branch}", "sha": sha}
                )
                
                # 4. Commit changes (simplified - just description for now)
                # Full implementation would update actual files
                
                # 5. Create PR
                pr_resp = await client.post(
                    f"{settings.GITEA_URL}/api/v1/repos/{repo}/pulls",
                    headers=headers,
                    json={
                        "title": title,
                        "body": description,
                        "head": branch,
                        "base": default_branch
                    }
                )
                
                if pr_resp.status_code in (200, 201):
                    pr_data = pr_resp.json()
                    return pr_data.get("html_url")
                
            except Exception as e:
                print(f"PR creation error: {e}")
        
        return None
