"""Analysis service - AI-powered issue analysis."""
import httpx
import json
import base64
from datetime import datetime
from typing import Optional, Dict, Any, List
from sqlalchemy.ext.asyncio import AsyncSession
from sqlalchemy import select
from app.core.config import settings
from app.models.organization import Organization

class AnalysisService:
    
    @classmethod
    def decrypt_key(cls, encrypted: str) -> str:
        """Simple deobfuscation."""
        try:
            return base64.b64decode(encrypted.encode()).decode()
        except:
            return ""
    
    @classmethod
    async def get_org_ai_config(cls, db: AsyncSession, org_id: int) -> Dict[str, Any]:
        """Get AI configuration from organization settings."""
        result = await db.execute(select(Organization).where(Organization.id == org_id))
        org = result.scalar_one_or_none()
        
        if org and org.ai_api_key_encrypted:
            return {
                "provider": org.ai_provider or "openrouter",
                "api_key": cls.decrypt_key(org.ai_api_key_encrypted),
                "model": org.ai_model or "meta-llama/llama-3.3-70b-instruct",
                "auto_analyze": org.ai_auto_analyze if org.ai_auto_analyze is not None else True,
                "auto_create_pr": org.ai_auto_create_pr if org.ai_auto_create_pr is not None else True,
                "confidence_threshold": org.ai_confidence_threshold or 70,
            }
        
        # Fallback to env config
        return {
            "provider": "openrouter",
            "api_key": settings.OPENROUTER_API_KEY or "",
            "model": "meta-llama/llama-3.3-70b-instruct",
            "auto_analyze": True,
            "auto_create_pr": True,
            "confidence_threshold": 70,
        }
    
    @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, timeout=30)
                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", ".tsx", ".jsx")):
                        content_resp = await client.get(item["download_url"], headers=headers, timeout=30)
                        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
        ]) if files else "No source code files available."
        
        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 call_llm(cls, prompt: str, ai_config: Dict[str, Any]) -> Dict[str, Any]:
        """Call the configured LLM provider."""
        provider = ai_config.get("provider", "openrouter")
        api_key = ai_config.get("api_key", "")
        model = ai_config.get("model", "meta-llama/llama-3.3-70b-instruct")
        
        if not api_key:
            return {
                "root_cause": "No API key configured. Go to Settings > AI Configuration.",
                "affected_files": [],
                "suggested_fix": "",
                "confidence": 0,
                "explanation": "Please configure an LLM API key in Settings."
            }
        
        async with httpx.AsyncClient() as client:
            try:
                if provider == "openrouter":
                    response = await client.post(
                        "https://openrouter.ai/api/v1/chat/completions",
                        headers={
                            "Authorization": f"Bearer {api_key}",
                            "Content-Type": "application/json",
                            "HTTP-Referer": "https://jira-fixer.startdata.com.br",
                            "X-Title": "JIRA AI Fixer"
                        },
                        json={
                            "model": model,
                            "messages": [{"role": "user", "content": prompt}],
                            "temperature": 0.2,
                            "max_tokens": 2000
                        },
                        timeout=120
                    )
                elif provider == "anthropic":
                    response = await client.post(
                        "https://api.anthropic.com/v1/messages",
                        headers={
                            "x-api-key": api_key,
                            "Content-Type": "application/json",
                            "anthropic-version": "2023-06-01"
                        },
                        json={
                            "model": model,
                            "max_tokens": 2000,
                            "messages": [{"role": "user", "content": prompt}]
                        },
                        timeout=120
                    )
                elif provider == "openai":
                    response = await client.post(
                        "https://api.openai.com/v1/chat/completions",
                        headers={
                            "Authorization": f"Bearer {api_key}",
                            "Content-Type": "application/json"
                        },
                        json={
                            "model": model,
                            "messages": [{"role": "user", "content": prompt}],
                            "temperature": 0.2,
                            "max_tokens": 2000
                        },
                        timeout=120
                    )
                elif provider == "groq":
                    response = await client.post(
                        "https://api.groq.com/openai/v1/chat/completions",
                        headers={
                            "Authorization": f"Bearer {api_key}",
                            "Content-Type": "application/json"
                        },
                        json={
                            "model": model,
                            "messages": [{"role": "user", "content": prompt}],
                            "temperature": 0.2,
                            "max_tokens": 2000
                        },
                        timeout=120
                    )
                else:
                    return {
                        "root_cause": f"Unsupported provider: {provider}",
                        "affected_files": [],
                        "suggested_fix": "",
                        "confidence": 0,
                        "explanation": "Please select a supported AI provider."
                    }
                
                if response.status_code == 200:
                    data = response.json()
                    
                    # Extract content based on provider
                    if provider == "anthropic":
                        content = data["content"][0]["text"]
                    else:
                        content = data["choices"][0]["message"]["content"]
                    
                    # Parse JSON from response
                    try:
                        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:
                    error_msg = response.text[:200]
                    try:
                        error_data = response.json()
                        error_msg = error_data.get("error", {}).get("message", error_msg)
                    except:
                        pass
                    return {
                        "root_cause": f"API error: {response.status_code}",
                        "affected_files": [],
                        "suggested_fix": "",
                        "confidence": 0,
                        "explanation": error_msg
                    }
                    
            except httpx.TimeoutException:
                return {
                    "root_cause": "Analysis timeout",
                    "affected_files": [],
                    "suggested_fix": "",
                    "confidence": 0,
                    "explanation": "The AI request timed out. Try again."
                }
            except Exception as e:
                return {
                    "root_cause": f"Analysis error: {str(e)}",
                    "affected_files": [],
                    "suggested_fix": "",
                    "confidence": 0,
                    "explanation": str(e)
                }
    
    @classmethod
    async def analyze(cls, issue: Dict[str, Any], repo: Optional[str] = None, ai_config: Optional[Dict[str, Any]] = None) -> Dict[str, Any]:
        """Run AI analysis on an issue."""
        # Use provided config or default
        if ai_config is None:
            ai_config = {
                "provider": "openrouter",
                "api_key": settings.OPENROUTER_API_KEY or "",
                "model": "meta-llama/llama-3.3-70b-instruct",
            }
        
        # Fetch code context
        files = []
        if repo:
            files = await cls.fetch_repository_files(repo)
        
        # Build prompt
        prompt = cls.build_prompt(issue, files)
        
        # Call LLM
        return await cls.call_llm(prompt, ai_config)
    
    @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,
                    timeout=30
                )
                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,
                    timeout=30
                )
                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},
                    timeout=30
                )
                
                # 4. 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
                    },
                    timeout=30
                )
                
                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
