import os
import base64
from pathlib import Path
from typing import Dict, Any, List, Optional
from github import Github, GithubException
from exponent.core.config import get_config

def create_github_repo(project_id: str, project_name: str = None) -> str:
    """Create a new GitHub repository for the ML project."""
    config = get_config()
    
    # Use project_id as repo name if no name provided
    if not project_name:
        project_name = f"ml-project-{project_id[:8]}"
    
    try:
        # Initialize GitHub client
        # Note: This would need GITHUB_TOKEN in config
        github_token = os.getenv("GITHUB_TOKEN")
        if not github_token:
            raise ValueError("GITHUB_TOKEN environment variable is required")
        
        g = Github(github_token)
        user = g.get_user()
        
        # Create repository
        repo = user.create_repo(
            name=project_name,
            description=f"ML project generated by Exponent-ML: {project_id}",
            private=False,
            auto_init=False
        )
        
        return repo.html_url
        
    except GithubException as e:
        print(f"❌ Error creating GitHub repository: {e}")
        raise

def upload_files_to_github(repo_url: str, project_path: Path, commit_message: str = "Initial commit") -> bool:
    """Upload project files to GitHub repository."""
    try:
        github_token = os.getenv("GITHUB_TOKEN")
        if not github_token:
            raise ValueError("GITHUB_TOKEN environment variable is required")
        
        g = Github(github_token)
        
        # Extract repo name from URL
        repo_name = repo_url.split("/")[-1]
        user_name = repo_url.split("/")[-2]
        
        # Get repository
        if user_name == g.get_user().login:
            repo = g.get_user().get_repo(repo_name)
        else:
            repo = g.get_repo(f"{user_name}/{repo_name}")
        
        # Upload files
        for file_path in project_path.rglob("*"):
            if file_path.is_file() and not file_path.name.startswith("."):
                # Get relative path
                relative_path = file_path.relative_to(project_path)
                
                # Read file content
                with open(file_path, 'rb') as f:
                    content = f.read()
                
                # Create file in repository
                try:
                    repo.create_file(
                        path=str(relative_path),
                        message=commit_message,
                        content=content,
                        branch="main"
                    )
                    print(f"✅ Uploaded: {relative_path}")
                except GithubException as e:
                    if e.status == 422:  # File already exists
                        print(f"⚠️  File already exists: {relative_path}")
                    else:
                        raise
        
        return True
        
    except Exception as e:
        print(f"❌ Error uploading files to GitHub: {e}")
        return False

def create_github_workflow(repo_url: str, project_id: str) -> bool:
    """Create GitHub Actions workflow for automated training."""
    try:
        github_token = os.getenv("GITHUB_TOKEN")
        if not github_token:
            raise ValueError("GITHUB_TOKEN environment variable is required")
        
        g = Github(github_token)
        
        # Extract repo name from URL
        repo_name = repo_url.split("/")[-1]
        user_name = repo_url.split("/")[-2]
        
        # Get repository
        if user_name == g.get_user().login:
            repo = g.get_user().get_repo(repo_name)
        else:
            repo = g.get_repo(f"{user_name}/{repo_name}")
        
        # Create workflow directory
        workflow_content = f"""name: Train ML Model

on:
  push:
    branches: [ main ]
  workflow_dispatch:

jobs:
  train:
    runs-on: ubuntu-latest
    
    steps:
    - uses: actions/checkout@v3
    
    - name: Set up Python
      uses: actions/setup-python@v4
      with:
        python-version: '3.9'
    
    - name: Install dependencies
      run: |
        python -m pip install --upgrade pip
        pip install -r requirements.txt
    
    - name: Train model
      run: |
        python train.py
      env:
        ANTHROPIC_API_KEY: ${{{{ secrets.ANTHROPIC_API_KEY }}}}
        AWS_ACCESS_KEY_ID: ${{{{ secrets.AWS_ACCESS_KEY_ID }}}}
        AWS_SECRET_ACCESS_KEY: ${{{{ secrets.AWS_SECRET_ACCESS_KEY }}}}
        S3_BUCKET: ${{{{ secrets.S3_BUCKET }}}}
    
    - name: Upload model artifacts
      uses: actions/upload-artifact@v3
      with:
        name: model-artifacts
        path: |
          *.joblib
          *.pkl
          *.h5
"""
        
        # Create workflow file
        repo.create_file(
            path=".github/workflows/train.yml",
            message="Add training workflow",
            content=workflow_content,
            branch="main"
        )
        
        print("✅ Created GitHub Actions workflow")
        return True
        
    except Exception as e:
        print(f"❌ Error creating GitHub workflow: {e}")
        return False

def deploy_to_github(project_id: str, project_path: Path, project_name: str = None) -> Dict[str, Any]:
    """Deploy ML project to GitHub."""
    try:
        # Create GitHub repository
        repo_url = create_github_repo(project_id, project_name)
        print(f"✅ Created GitHub repository: {repo_url}")
        
        # Upload project files
        success = upload_files_to_github(repo_url, project_path)
        if not success:
            raise Exception("Failed to upload files to GitHub")
        
        # Create GitHub Actions workflow
        create_github_workflow(repo_url, project_id)
        
        return {
            "project_id": project_id,
            "github_url": repo_url,
            "deployment_successful": True
        }
        
    except Exception as e:
        print(f"❌ Error deploying to GitHub: {e}")
        return {
            "project_id": project_id,
            "github_url": None,
            "deployment_successful": False,
            "error": str(e)
        }

def list_github_repos() -> List[Dict[str, Any]]:
    """List GitHub repositories created by Exponent-ML."""
    try:
        github_token = os.getenv("GITHUB_TOKEN")
        if not github_token:
            return []
        
        g = Github(github_token)
        user = g.get_user()
        
        repos = []
        for repo in user.get_repos():
            if repo.description and "Exponent-ML" in repo.description:
                repos.append({
                    "name": repo.name,
                    "url": repo.html_url,
                    "description": repo.description,
                    "created_at": repo.created_at.isoformat()
                })
        
        return repos
        
    except Exception as e:
        print(f"❌ Error listing GitHub repositories: {e}")
        return []
