"""
Enhanced Project Generator Tool for creating complete projects with multiple files.
Generates entire project structures from natural language descriptions.
"""

import os
import json
import datetime
from pathlib import Path
from typing import Dict, List, Any, Optional
from .base import BaseTool


class EnhancedProjectGeneratorTool(BaseTool):
    """Tool for generating complete projects with multiple files and proper structure."""
    
    def __init__(self):
        self.name = "Enhanced Project Generator"
        self.description = "Generate complete projects with multiple files, directories, and configurations from descriptions"
        
        # Project templates with file structures
        self.templates = {
            "python-api": {
                "description": "FastAPI Python API with database integration",
                "files": {
                    "main.py": "FastAPI application entry point",
                    "models/__init__.py": "Models package init",
                    "models/base.py": "Base database model",
                    "routes/__init__.py": "Routes package init", 
                    "routes/api.py": "API route definitions",
                    "config.py": "Application configuration",
                    "database.py": "Database connection setup",
                    "requirements.txt": "Python dependencies",
                    "README.md": "Project documentation",
                    ".env.example": "Environment variables template",
                    "tests/__init__.py": "Tests package init",
                    "tests/test_api.py": "API endpoint tests"
                }
            },
            "react-app": {
                "description": "React frontend application with components",
                "files": {
                    "package.json": "Node.js dependencies and scripts",
                    "src/index.js": "React application entry point",
                    "src/App.js": "Main React component",
                    "src/components/Header.js": "Header component",
                    "src/components/Footer.js": "Footer component",
                    "src/services/api.js": "API service functions",
                    "src/styles/App.css": "Application styles",
                    "public/index.html": "HTML template",
                    "README.md": "Project documentation",
                    ".gitignore": "Git ignore rules",
                    "src/tests/App.test.js": "Component tests"
                }
            },
            "fullstack": {
                "description": "Full-stack application with frontend and backend",
                "files": {
                    "backend/main.py": "FastAPI backend entry point",
                    "backend/models/__init__.py": "Backend models init",
                    "backend/routes/__init__.py": "Backend routes init",
                    "backend/requirements.txt": "Python dependencies",
                    "frontend/package.json": "Frontend dependencies",
                    "frontend/src/App.js": "React frontend app",
                    "frontend/src/services/api.js": "API client",
                    "docker-compose.yml": "Container orchestration",
                    "README.md": "Project documentation",
                    ".gitignore": "Git ignore rules",
                    "docs/API.md": "API documentation"
                }
            }
        }
    
    def can_handle(self, query: str) -> bool:
        """Check if this tool can handle the query."""
        keywords = [
            "generate project", "create project", "new project", "project structure",
            "scaffold project", "initialize project", "build application",
            "full-stack", "api project", "react app", "web app"
        ]
        return any(keyword in query.lower() for keyword in keywords)
    
    def execute(self, task: str) -> Dict[str, Any]:
        """Execute project generation based on the task."""
        try:
            # Parse the task to determine project type and requirements
            project_info = self._parse_project_query(task)
            
            if not project_info:
                return {
                    "success": False,
                    "error": "Could not understand project requirements from query",
                    "suggestions": [
                        "Try: 'generate project fastapi backend with database'",
                        "Try: 'create react frontend application'", 
                        "Try: 'build full-stack e-commerce platform'"
                    ]
                }
            
            # Generate the project structure
            result = self._generate_project_structure(project_info)
            
            # Create tasks.md and requirements.md files
            self._create_documentation_files(project_info, result)
            
            return result
            
        except Exception as e:
            return {
                "success": False,
                "error": f"Error generating project: {str(e)}",
                "details": "Check project path permissions and requirements"
            }
    
    def _parse_project_query(self, query: str) -> Optional[Dict[str, Any]]:
        """Parse natural language query to extract project requirements."""
        query_lower = query.lower()
        
        # Determine project type
        project_type = "python-api"  # default
        if any(word in query_lower for word in ["react", "frontend", "ui", "web app"]):
            project_type = "react-app"
        elif any(word in query_lower for word in ["full-stack", "fullstack", "full stack"]):
            project_type = "fullstack"
        elif any(word in query_lower for word in ["api", "backend", "fastapi", "flask"]):
            project_type = "python-api"
        
        # Extract project name (look for quotes or last word)
        project_name = "my-project"
        words = query.split()
        if len(words) > 2:
            project_name = words[-1].replace('"', '').replace("'", "")
            if not project_name.replace("-", "").replace("_", "").isalnum():
                project_name = "my-project"
        
        # Extract features/requirements
        features = []
        if "database" in query_lower or "db" in query_lower:
            features.append("database")
        if "auth" in query_lower or "login" in query_lower:
            features.append("authentication") 
        if "payment" in query_lower or "stripe" in query_lower:
            features.append("payments")
        if "test" in query_lower:
            features.append("testing")
        
        return {
            "name": project_name,
            "type": project_type,
            "features": features,
            "description": query
        }
    
    def _generate_project_structure(self, project_info: Dict[str, Any]) -> Dict[str, Any]:
        """Generate the actual project files and structure."""
        project_name = project_info["name"]
        project_type = project_info["type"]
        features = project_info.get("features", [])
        
        if project_type not in self.templates:
            return {
                "success": False,
                "error": f"Unknown project type: {project_type}",
                "available_types": list(self.templates.keys())
            }
        
        template = self.templates[project_type]
        created_files = []
        created_dirs = set()
        
        # Create project directory
        project_path = Path.cwd() / project_name
        if project_path.exists():
            return {
                "success": False,
                "error": f"Directory '{project_name}' already exists",
                "suggestion": f"Choose a different name or remove existing directory"
            }
        
        try:
            project_path.mkdir(parents=True, exist_ok=True)
            created_dirs.add(str(project_path))
            
            # Generate files from template
            for file_path, description in template["files"].items():
                full_path = project_path / file_path
                
                # Create parent directories if needed
                full_path.parent.mkdir(parents=True, exist_ok=True)
                created_dirs.add(str(full_path.parent))
                
                # Generate file content based on type and features
                content = self._generate_file_content(file_path, description, project_info)
                
                # Write file
                with open(full_path, 'w', encoding='utf-8') as f:
                    f.write(content)
                
                created_files.append({
                    "path": str(full_path.relative_to(Path.cwd())),
                    "description": description,
                    "size": len(content)
                })
            
            return {
                "success": True,
                "project_name": project_name,
                "project_type": project_type,
                "project_path": str(project_path),
                "files_created": len(created_files),
                "directories_created": len(created_dirs),
                "files": created_files,
                "features": features,
                "next_steps": [
                    f"cd {project_name}",
                    "Review generated files and customize as needed",
                    "Install dependencies (check requirements.txt or package.json)",
                    "Run the application and start development"
                ]
            }
            
        except Exception as e:
            # Cleanup on error
            if project_path.exists():
                import shutil
                shutil.rmtree(project_path, ignore_errors=True)
            
            raise e
    
    def _generate_file_content(self, file_path: str, description: str, project_info: Dict[str, Any]) -> str:
        """Generate content for a specific file based on its type and project requirements."""
        project_name = project_info["name"]
        features = project_info.get("features", [])
        
        # File templates based on file type
        if file_path == "main.py":
            return self._generate_fastapi_main(project_name, features)
        elif file_path == "requirements.txt":
            return self._generate_python_requirements(features)
        elif file_path == "package.json":
            return self._generate_package_json(project_name, features)
        elif file_path.endswith("App.js"):
            return self._generate_react_app(project_name, features)
        elif file_path == "README.md":
            return self._generate_readme(project_name, project_info)
        elif file_path == ".gitignore":
            return self._generate_gitignore(project_info["type"])
        elif file_path.endswith(".py") and "test" in file_path:
            return self._generate_python_test(file_path)
        elif file_path.endswith("__init__.py"):
            return f'"""{description}"""\n'
        elif file_path.endswith(".js") and "component" in file_path.lower():
            component_name = Path(file_path).stem
            return self._generate_react_component(component_name)
        elif file_path.endswith(".css"):
            return self._generate_basic_css()
        elif file_path == "docker-compose.yml":
            return self._generate_docker_compose(project_name, features)
        else:
            return f"# {description}\n# TODO: Implement {Path(file_path).name}\n"
    
    def _generate_fastapi_main(self, project_name: str, features: List[str]) -> str:
        """Generate FastAPI main.py content."""
        return f'''"""
{project_name.replace('-', ' ').title()} - FastAPI Application
Generated by Metis Enhanced Project Generator
"""

from fastapi import FastAPI, HTTPException
from fastapi.middleware.cors import CORSMiddleware
{"from models.base import Base" if "database" in features else ""}
{"from database import engine" if "database" in features else ""}

app = FastAPI(
    title="{project_name.replace('-', ' ').title()}",
    description="API for {project_name}",
    version="1.0.0"
)

# CORS middleware
app.add_middleware(
    CORSMiddleware,
    allow_origins=["*"],  # Configure for production
    allow_credentials=True,
    allow_methods=["*"],
    allow_headers=["*"],
)

{"# Create database tables" if "database" in features else ""}
{"Base.metadata.create_all(bind=engine)" if "database" in features else ""}

@app.get("/")
async def root():
    return {{"message": "Welcome to {project_name.replace('-', ' ').title()} API"}}

@app.get("/health")
async def health_check():
    return {{"status": "healthy", "service": "{project_name}"}}

if __name__ == "__main__":
    import uvicorn
    uvicorn.run(app, host="0.0.0.0", port=8000)
'''

    def _generate_python_requirements(self, features: List[str]) -> str:
        """Generate requirements.txt content."""
        requirements = ["fastapi>=0.100.0", "uvicorn[standard]>=0.22.0"]
        
        if "database" in features:
            requirements.extend(["sqlalchemy>=2.0.0", "alembic>=1.11.0"])
        if "authentication" in features:
            requirements.extend(["python-jose[cryptography]", "passlib[bcrypt]"])
        if "payments" in features:
            requirements.append("stripe>=5.5.0")
        if "testing" in features:
            requirements.extend(["pytest>=7.4.0", "httpx>=0.24.0"])
        
        return "\n".join(requirements) + "\n"
    
    def _generate_package_json(self, project_name: str, features: List[str]) -> str:
        """Generate package.json content."""
        dependencies = {
            "react": "^18.2.0",
            "react-dom": "^18.2.0",
            "react-scripts": "5.0.1"
        }
        
        if "authentication" in features:
            dependencies["axios"] = "^1.4.0"
        if "testing" in features:
            dependencies["@testing-library/react"] = "^13.4.0"
        
        package_json = {
            "name": project_name,
            "version": "0.1.0",
            "private": True,
            "dependencies": dependencies,
            "scripts": {
                "start": "react-scripts start",
                "build": "react-scripts build", 
                "test": "react-scripts test",
                "eject": "react-scripts eject"
            },
            "browserslist": {
                "production": [
                    ">0.2%",
                    "not dead",
                    "not op_mini all"
                ],
                "development": [
                    "last 1 chrome version",
                    "last 1 firefox version",
                    "last 1 safari version"
                ]
            }
        }
        
        return json.dumps(package_json, indent=2)
    
    def _generate_react_app(self, project_name: str, features: List[str]) -> str:
        """Generate React App.js content."""
        return f'''import React from 'react';
import './styles/App.css';

function App() {{
  return (
    <div className="App">
      <header className="App-header">
        <h1>{project_name.replace('-', ' ').title()}</h1>
        <p>Welcome to your React application!</p>
        {"<p>Features: " + ", ".join(features) + "</p>" if features else ""}
      </header>
      
      <main className="App-main">
        <p>Start building your application here.</p>
        <p>Edit <code>src/App.js</code> to get started.</p>
      </main>
    </div>
  );
}}

export default App;
'''

    def _generate_readme(self, project_name: str, project_info: Dict[str, Any]) -> str:
        """Generate README.md content."""
        return f'''# {project_name.replace('-', ' ').title()}

{project_info["description"]}

## Project Structure

Generated by Metis Enhanced Project Generator

### Features
{chr(10).join(f"- {feature.title()}" for feature in project_info.get("features", []))}

## Getting Started

1. Install dependencies:
   ```bash
   {"pip install -r requirements.txt" if project_info["type"] == "python-api" else "npm install"}
   ```

2. Run the application:
   ```bash
   {"python main.py" if project_info["type"] == "python-api" else "npm start"}
   ```

## Development

This project was generated with Metis CLI. To continue development:

1. Review the generated files and customize as needed
2. Add your business logic and features
3. Update tests and documentation
4. Configure environment variables

## Project Type: {project_info["type"]}

Generated on: {datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")}
'''

    def _generate_gitignore(self, project_type: str) -> str:
        """Generate .gitignore content based on project type."""
        if "react" in project_type:
            return '''# React
node_modules/
build/
.env.local
.env.development.local
.env.test.local
.env.production.local
npm-debug.log*
yarn-debug.log*
yarn-error.log*
'''
        else:
            return '''# Python
__pycache__/
*.pyc
*.pyo
*.pyd
.Python
env/
venv/
.env
.venv
pip-log.txt
pip-delete-this-directory.txt
.coverage
.pytest_cache/
htmlcov/
'''

    def _generate_python_test(self, file_path: str) -> str:
        """Generate Python test file content."""
        return '''"""
Test module for API endpoints
"""

import pytest
from fastapi.testclient import TestClient
from main import app

client = TestClient(app)

def test_root_endpoint():
    """Test the root endpoint."""
    response = client.get("/")
    assert response.status_code == 200
    assert "message" in response.json()

def test_health_check():
    """Test the health check endpoint."""
    response = client.get("/health")
    assert response.status_code == 200
    assert response.json()["status"] == "healthy"
'''

    def _generate_react_component(self, component_name: str) -> str:
        """Generate React component content."""
        return f'''import React from 'react';

const {component_name} = () => {{
  return (
    <div className="{component_name.lower()}">
      <h2>{component_name}</h2>
      <p>{component_name} component - customize as needed</p>
    </div>
  );
}};

export default {component_name};
'''

    def _generate_basic_css(self) -> str:
        """Generate basic CSS content."""
        return '''.App {
  text-align: center;
}

.App-header {
  background-color: #282c34;
  padding: 20px;
  color: white;
}

.App-main {
  padding: 20px;
}

.App h1 {
  font-size: 2.5rem;
  margin-bottom: 1rem;
}
'''

    def _generate_docker_compose(self, project_name: str, features: List[str]) -> str:
        """Generate docker-compose.yml content."""
        return f'''version: '3.8'

services:
  backend:
    build: ./backend
    ports:
      - "8000:8000"
    environment:
      - DATABASE_URL=postgresql://user:password@db:5432/{project_name}
    depends_on:
      - db

  frontend:
    build: ./frontend
    ports:
      - "3000:3000"
    depends_on:
      - backend

{"  db:" if "database" in features else ""}
{"    image: postgres:15" if "database" in features else ""}
{"    environment:" if "database" in features else ""}
{"      POSTGRES_DB: " + project_name if "database" in features else ""}
{"      POSTGRES_USER: user" if "database" in features else ""}
{"      POSTGRES_PASSWORD: password" if "database" in features else ""}
{"    volumes:" if "database" in features else ""}
{"      - postgres_data:/var/lib/postgresql/data" if "database" in features else ""}

{"volumes:" if "database" in features else ""}
{"  postgres_data:" if "database" in features else ""}
'''

    def _create_documentation_files(self, project_info: Dict[str, Any], result: Dict[str, Any]) -> None:
        """Create tasks.md and requirements.md files for the project."""
        if not result.get("success"):
            return
        
        project_path = Path(result["project_path"])
        
        # Create tasks.md
        tasks_content = f'''# {project_info["name"].replace("-", " ").title()} - Development Tasks

## Project Overview
- **Type**: {project_info["type"]}
- **Features**: {", ".join(project_info.get("features", []))}
- **Generated**: {datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")}

## Current Tasks

### Setup Tasks
- [x] Generate project structure ({len(result["files"])} files created)
- [ ] Install dependencies
- [ ] Configure environment variables  
- [ ] Set up development environment

### Development Tasks  
- [ ] Implement core business logic
- [ ] Add error handling and validation
- [ ] Write comprehensive tests
- [ ] Add API documentation
- [ ] Implement security measures

### Deployment Tasks
- [ ] Configure production environment
- [ ] Set up CI/CD pipeline
- [ ] Deploy to production
- [ ] Monitor and maintain

## Completed Tasks
- ✓ Project structure generated by Metis CLI

## Notes
Generated by Metis Enhanced Project Generator
Use `metis docs task add "<task>"` to add new tasks
Use `metis docs task complete "<task>"` to mark tasks as done
'''

        # Create requirements.md
        requirements_content = f'''# {project_info["name"].replace("-", " ").title()} - Requirements

## Project Requirements

### Functional Requirements
1. **Core Functionality**
   - Primary application features as specified
   - User interface and user experience
   - Data processing and storage

2. **API Requirements** (if applicable)
   - RESTful API endpoints
   - Request/response handling
   - Authentication and authorization

3. **Database Requirements** (if applicable)
   - Data models and relationships
   - Data validation and integrity
   - Performance optimization

### Non-Functional Requirements
1. **Performance**
   - Response time < 2 seconds for API calls
   - Support for concurrent users
   - Scalable architecture

2. **Security** 
   - Input validation and sanitization
   - Authentication and session management
   - Data protection and privacy

3. **Reliability**
   - Error handling and recovery
   - Logging and monitoring
   - Backup and disaster recovery

### Technical Requirements
- **Framework**: {project_info["type"]}
- **Features**: {", ".join(project_info.get("features", []))}
- **Environment**: Development, Testing, Production
- **Dependencies**: See requirements.txt or package.json

### Acceptance Criteria
- [ ] All functional requirements implemented
- [ ] All tests passing
- [ ] Code review completed
- [ ] Documentation updated
- [ ] Performance benchmarks met

## Implementation Status
- **Generated**: {datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")}
- **Status**: Initial project structure created
- **Next Steps**: Implement core functionality

Generated by Metis Enhanced Project Generator
'''

        # Write documentation files
        try:
            with open(project_path / "tasks.md", "w", encoding="utf-8") as f:
                f.write(tasks_content)
            
            with open(project_path / "requirements.md", "w", encoding="utf-8") as f:
                f.write(requirements_content)
            
            # Update result to include documentation files
            result["files"].extend([
                {
                    "path": str((project_path / "tasks.md").relative_to(Path.cwd())),
                    "description": "Project tasks and progress tracking",
                    "size": len(tasks_content)
                },
                {
                    "path": str((project_path / "requirements.md").relative_to(Path.cwd())),
                    "description": "Project requirements and specifications", 
                    "size": len(requirements_content)
                }
            ])
            result["files_created"] += 2
            
        except Exception as e:
            print(f"Warning: Could not create documentation files: {e}")
