#web_search.py
import requests
from bs4 import BeautifulSoup
import re
import urllib.parse
from typing import List, Dict, Optional

class WebSearchAgent:
    def __init__(self):
        self.search_engines = [
            "https://duckduckgo.com/html/",
            "https://www.google.com/search"
        ]
    
    def search(self, query: str, num_results: int = 5) -> List[Dict[str, str]]:
        """
        Perform web search and return top results
        
        Args:
            query (str): Search query
            num_results (int): Number of results to return
        
        Returns:
            List of dictionaries with search results
        """
        headers = {
            'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36'
        }
        
        encoded_query = urllib.parse.quote(query)
        search_url = f"https://www.google.com/search?q={encoded_query}"
        
        try:
            response = requests.get(search_url, headers=headers)
            soup = BeautifulSoup(response.text, 'html.parser')
            
            # Extract search results
            results = []
            for result in soup.find_all('div', class_='g')[:num_results]:
                link_elem = result.find('a')
                title_elem = result.find('h3')
                
                if link_elem and title_elem:
                    results.append({
                        'title': title_elem.text,
                        'link': link_elem['href'],
                        'snippet': result.find('div', class_='VwiC3b').text if result.find('div', class_='VwiC3b') else ''
                    })
            
            return results
        
        except Exception as e:
            print(f"Search error: {e}")
            return []



# sandboxed_environment.py
import os
import sys
import tempfile
import subprocess
import venv
import shutil
import traceback
from typing import Dict, Any, Optional

class SandboxedEnvironment:
    def __init__(self, base_dir: Optional[str] = None):
        """
        Create a sandboxed environment for executing code safely.
        
        Args:
            base_dir (str, optional): Base directory for sandbox. 
                                      If None, a temporary directory is created.
        """
        self.base_dir = base_dir or tempfile.mkdtemp(prefix="code_sandbox_")
        self.venv_path = os.path.join(self.base_dir, "venv")
        self.requirements_path = os.path.join(self.base_dir, "requirements.txt")
        self.code_path = ""
    
    def create_venv(self):
        """Create a Python virtual environment."""
        venv.create(self.venv_path, with_pip=True)
    
    def install_dependencies(self, dependencies: list):
        """
        Install required dependencies in the sandboxed environment.
        
        Args:
            dependencies (list): List of package names to install.
        """
        pip_path = os.path.join(self.venv_path, "bin", "pip") if os.name != "nt" else os.path.join(self.venv_path, "Scripts", "pip.exe")
        try:
            subprocess.run(
                [pip_path, "install"] + dependencies,
                check=True,
                capture_output=True,
                text=True
            )
        except subprocess.CalledProcessError as e:
            raise RuntimeError(f"Dependency installation error: {e.stderr}")
    
    def write_code(self, code: str, language: str):
        """
        Write code to a file in the sandbox.
        
        Args:
            code (str): Code to execute.
            language (str): Programming language for the code.
        """
        ext_map = {
            "python": ".py",
            "java": ".java",
            "javascript": ".js",
            "react": ".jsx",
            "astro": ".astro",
            "html": ".html",
            "css": ".css",
        }
        if language.lower() not in ext_map:
            raise ValueError(f"Unsupported language: {language}")
    
        file_extension = ext_map[language.lower()]
        file_name = f"code_to_run{file_extension}"
        self.code_path = os.path.join(self.base_dir, file_name)
        
        with open(self.code_path, "w") as f:
            f.write(code)
    
    def execute_code(self, language: str, timeout: int = 30) -> Dict[str, Any]:
        """
        Execute code in the sandboxed environment.
        
        Args:
            language (str): Programming language of the code.
            timeout (int): Maximum execution time in seconds.
        
        Returns:
            Dictionary with execution results.
        """
        try:
            if language.lower() == "python":
                python_path = os.path.join(
                    self.venv_path, "bin", "python"
                ) if os.name != "nt" else os.path.join(self.venv_path, "Scripts", "python.exe")
                result = subprocess.run(
                    [python_path, self.code_path],
                    capture_output=True,
                    text=True,
                    timeout=timeout
                )
                return {
                    "success": result.returncode == 0,
                    "stdout": result.stdout,
                    "stderr": result.stderr
                }
            elif language.lower() == "java":
                javac_path = shutil.which("javac")
                java_path = shutil.which("java")
                if not javac_path or not java_path:
                    return {"success": False, "error": "Java compiler or runtime not found."}
                
                # Compile Java code
                compile_result = subprocess.run(
                    [javac_path, self.code_path],
                    capture_output=True,
                    text=True
                )
                if compile_result.returncode != 0:
                    return {"success": False, "stderr": compile_result.stderr}
                
                # Execute Java class
                class_name = os.path.splitext(os.path.basename(self.code_path))[0]
                execute_result = subprocess.run(
                    [java_path, class_name],
                    capture_output=True,
                    text=True,
                    cwd=self.base_dir,
                    timeout=timeout
                )
                return {
                    "success": execute_result.returncode == 0,
                    "stdout": execute_result.stdout,
                    "stderr": execute_result.stderr
                }
            elif language.lower() == "javascript":
                node_path = shutil.which("node")
                if not node_path:
                    return {"success": False, "error": "Node.js not found."}
                result = subprocess.run(
                    [node_path, self.code_path],
                    capture_output=True,
                    text=True,
                    timeout=timeout
                )
                return {
                    "success": result.returncode == 0,
                    "stdout": result.stdout,
                    "stderr": result.stderr
                }
            elif language.lower() in ["react", "astro"]:
                # For React and Astro, assume npm scripts are set up
                # e.g., "start" script to run the project
                output_dir = self.base_dir
                result = subprocess.run(
                    ["npm", "install"],
                    cwd=output_dir,
                    capture_output=True,
                    text=True,
                    timeout=timeout
                )
                if result.returncode != 0:
                    return {"success": False, "stderr": result.stderr}
                
                start_command = "start"
                if language.lower() == "astro":
                    start_command = "dev"
                
                result = subprocess.run(
                    ["npm", "run", start_command],
                    cwd=output_dir,
                    capture_output=True,
                    text=True,
                    timeout=timeout
                )
                return {
                    "success": result.returncode == 0,
                    "stdout": result.stdout,
                    "stderr": result.stderr
                }
            elif language.lower() in ["html", "css"]:
                # For HTML/CSS, typically no execution is needed
                return {"success": True, "info": "HTML/CSS files generated successfully."}
            else:
                return {"success": False, "error": f"Execution for language {language} is not supported."}
        except subprocess.TimeoutExpired:
            return {"success": False, "error": "Execution timed out."}
        except Exception as e:
            return {"success": False, "error": str(e), "traceback": traceback.format_exc()}
    
    def cleanup(self):
        """Clean up the sandboxed environment."""
        shutil.rmtree(self.base_dir, ignore_errors=True)


# main.py
import os
import subprocess
import json
import shutil
from ai_code_agent import AICodeAgent

def setup_output_environment(language: str):
    """
    Sets up the output environment:
    - Creates an output directory
    - Creates a virtual environment for Python
    - Prepares paths for requirements.txt and code files

    Args:
        language (str): Programming language (e.g., "python", "java", "javascript", "react", "astro", "html", "css")

    Returns:
        Dict[str, str]: Paths to venv (if Python), requirements.txt (if Python), and code file
    """
    output_dir = os.path.join(os.getcwd(), "output", language)
    os.makedirs(output_dir, exist_ok=True)

    paths = {}

    if language.lower() == "python":
        venv_path = os.path.join(output_dir, "venv")
        if not os.path.exists(venv_path):
            subprocess.run(["python3.11", "-m", "venv", venv_path], check=True)
        paths["venv_path"] = venv_path
        paths["requirements_path"] = os.path.join(output_dir, "requirements.txt")
        paths["code_path"] = os.path.join(output_dir, f"code_to_run.{language.lower()}")
    elif language.lower() in ["java", "javascript", "react", "astro", "html", "css"]:
        extension_map = {
            "java": "java",
            "javascript": "js",
            "react": "jsx",       # Changed from .react to .jsx
            "astro": "astro",
            "html": "html",
            "css": "css"
        }
        file_extension = extension_map.get(language.lower(), "txt")
        paths["code_path"] = os.path.join(output_dir, f"code_to_run.{file_extension}")
    else:
        raise ValueError(f"Unsupported language: {language}")

    return paths

def install_dependencies(language: str, paths: dict):
    """
    Installs dependencies based on the language and requirements.

    Args:
        language (str): Programming language
        paths (dict): Paths dictionary returned by setup_output_environment
    """
    if language.lower() == "python":
        pip_path = os.path.join(paths["venv_path"], "bin", "pip") if os.name != "nt" else os.path.join(paths["venv_path"], "Scripts", "pip.exe")
        if os.path.exists(paths["requirements_path"]):
            subprocess.run([pip_path, "install", "-r", paths["requirements_path"]], check=True)
    elif language.lower() in ["javascript", "react", "astro"]:
        # Initialize npm project if not already initialized
        output_dir = os.path.dirname(paths["code_path"])
        package_json_path = os.path.join(output_dir, "package.json")
        if not os.path.exists(package_json_path):
            subprocess.run(["npm", "init", "-y"], cwd=output_dir, check=True)
        # Install dependencies if a package.json exists
        if os.path.exists(package_json_path):
            subprocess.run(["npm", "install"], cwd=output_dir, check=True)
    # Add more language-specific dependency installations as needed

def execute_code(language: str, paths: dict):
    """
    Executes the code based on the language.

    Args:
        language (str): Programming language
        paths (dict): Paths dictionary returned by setup_output_environment

    Returns:
        str: Execution output or error
    """
    if language.lower() == "python":
        python_path = os.path.join(paths["venv_path"], "bin", "python") if os.name != "nt" else os.path.join(paths["venv_path"], "Scripts", "python.exe")
        result = subprocess.run(
            [python_path, paths["code_path"]],
            capture_output=True,
            text=True
        )
        return result.stdout if result.returncode == 0 else result.stderr
    elif language.lower() == "javascript":
        node_path = shutil.which("node")
        if not node_path:
            return "Node.js is not installed or not found in PATH."
        result = subprocess.run(
            [node_path, paths["code_path"]],
            capture_output=True,
            text=True
        )
        return result.stdout if result.returncode == 0 else result.stderr
    elif language.lower() == "java":
        javac_path = shutil.which("javac")
        java_path = shutil.which("java")
        if not javac_path or not java_path:
            return "Java compiler or runtime not found."
        # Compile Java code
        compile_result = subprocess.run(
            [javac_path, paths["code_path"]],
            capture_output=True,
            text=True
        )
        if compile_result.returncode != 0:
            return compile_result.stderr
        # Execute Java class
        class_name = os.path.splitext(os.path.basename(paths["code_path"]))[0]
        execute_result = subprocess.run(
            [java_path, class_name],
            capture_output=True,
            text=True,
            cwd=os.path.dirname(paths["code_path"])
        )
        return execute_result.stdout if execute_result.returncode == 0 else execute_result.stderr
    elif language.lower() in ["html", "css", "react", "astro"]:
        # For front-end projects, usually no execution is needed unless using a build tool
        # For React and Astro, you might run `npm start` or similar
        output_dir = os.path.dirname(paths["code_path"])
        if language.lower() in ["react", "astro"]:
            try:
                command = ["npm", "start"] if language.lower() == "react" else ["npm", "run", "dev"]
                result = subprocess.run(
                    command,
                    cwd=output_dir,
                    capture_output=True,
                    text=True
                )
                return result.stdout if result.returncode == 0 else result.stderr
            except subprocess.CalledProcessError as e:
                return f"Error running {language.capitalize()} project: {e.stderr}"
        return "HTML/CSS files generated successfully. Open them in a browser to view."
    else:
        return f"Execution for language {language} is not supported yet."

def display_project_plan(project_plan: dict):
    """
    Nicely formats and displays the project plan to the user.

    Args:
        project_plan (dict): Structured project plan
    """
    print("\n=== Project Plan ===\n")
    for section, details in project_plan.items():
        formatted_section = section.replace('_', ' ').capitalize()
        print(f"**{formatted_section}:**")
        if isinstance(details, list):
            for item in details:
                print(f"- {item}")
        elif isinstance(details, dict):
            for key, value in details.items():
                print(f"- {key}: {value}")
        else:
            print(f"- {details}")
        print()
    print("====================\n")

def get_user_confirmation():
    """
    Prompts the user to confirm whether to proceed.

    Returns:
        bool: True if user confirms, False otherwise
    """
    while True:
        response = input("Do you want to proceed with the project setup? (yes/no): ").strip().lower()
        if response in ["yes", "y"]:
            return True
        elif response in ["no", "n"]:
            return False
        else:
            print("Please enter 'yes' or 'no'.")

def main():
    # Initialize the AI Code Agent
    agent = AICodeAgent()

    print("Welcome to the AI-Powered Project Planner and Code Generator!\n")

    while True:
        # Dynamic User Input
        project_description = input("Enter your project description: ").strip()
        if not project_description:
            print("Project description cannot be empty. Please try again.\n")
            continue

        language = input("Enter the programming language/framework (e.g., python, react, javascript, java, astro, html, css): ").strip().lower()
        supported_languages = ["python", "javascript", "java", "react", "astro", "html", "css"]
        if language not in supported_languages:
            print(f"Unsupported language/framework. Supported options are: {', '.join(supported_languages)}\n")
            continue

        # Generate Project Plan
        print("\nGenerating an in-depth project plan. Please wait...\n")
        try:
            project_plan = agent.generate_project_plan(project_description, language)
        except Exception as e:
            print(f"Error generating project plan: {e}\n")
            continue

        # Check if the project plan has content
        is_empty = all(len(items) == 0 for items in project_plan.values())
        if is_empty:
            print("Failed to generate a valid project plan. Please try again with a different description or language.\n")
            continue

        # Display Project Plan
        display_project_plan(project_plan)

        # User Confirmation
        if not get_user_confirmation():
            print("Project setup canceled by the user.\n")
            # Optionally, ask if the user wants to enter a new project
            retry = input("Do you want to enter a new project? (yes/no): ").strip().lower()
            if retry in ["yes", "y"]:
                print("\nStarting a new project setup...\n")
                continue
            else:
                print("Exiting the application. Goodbye!")
                break

        # Proceed with Project Setup
        print("Proceeding with project setup...\n")

        # Generate Project Code
        try:
            project_files = agent.generate_project_code(project_plan, language)
        except Exception as e:
            print(f"Error generating project code: {e}\n")
            continue

        # Setup Output Environment
        try:
            paths = setup_output_environment(language)
        except Exception as e:
            print(f"Error setting up output environment: {e}\n")
            continue

        # Write Generated Code to Files
        for file_path, code_content in project_files.items():
            os.makedirs(os.path.dirname(file_path), exist_ok=True)
            with open(file_path, "w") as code_file:
                code_file.write(code_content)
            print(f"Generated and wrote code to {file_path}")

        # Handle Python-specific dependencies
        if language.lower() == "python":
            dependencies = agent.extract_dependencies("\n".join(project_files.values()))
            if dependencies:
                with open(paths["requirements_path"], "w") as requirements_file:
                    requirements_file.write("\n".join(dependencies))
                print(f"Extracted dependencies and wrote to {paths['requirements_path']}")

        # Install Dependencies
        try:
            install_dependencies(language, paths)
            print("Dependencies installed successfully.\n")
        except subprocess.CalledProcessError as e:
            print(f"Dependency installation failed: {e.stderr}\n")
            continue

        # Execute the Project Code
        print("Executing the project code...\n")
        execution_output = execute_code(language, paths)
        print(f"=== Execution Output ===\n{execution_output}\n=========================\n")

        # Ask if the user wants to create another project
        another = input("Do you want to create another project? (yes/no): ").strip().lower()
        if another not in ["yes", "y"]:
            print("Thank you for using the AI-Powered Project Planner and Code Generator. Goodbye!")
            break
        else:
            print("\nStarting a new project setup...\n")

if __name__ == "__main__":
    main()

# documentation_parser.py
import requests
from bs4 import BeautifulSoup
import re
from typing import Dict, List, Optional

class DocumentationParser:
    @staticmethod
    def fetch_webpage(url: str) -> Optional[str]:
        """
        Fetch webpage content.
        
        Args:
            url (str): URL to fetch.
        
        Returns:
            Webpage content or None.
        """
        try:
            headers = {
                'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36'
            }
            response = requests.get(url, headers=headers)
            return response.text
        except Exception as e:
            print(f"Webpage fetch error: {e}")
            return None

    @classmethod
    def parse_installation_docs(cls, html_content: str) -> Dict[str, str]:
        """
        Extract installation instructions from documentation.
        
        Args:
            html_content (str): HTML content of documentation page.
        
        Returns:
            Dictionary of installation instructions.
        """
        soup = BeautifulSoup(html_content, 'html.parser')
        
        # Regex patterns for finding installation commands
        pip_patterns = [
            r'pip install\s+(\w+)',
            r'pip3 install\s+(\w+)',
            r'python -m pip install\s+(\w+)'
        ]
        
        installation_methods = {}
        
        # Search for pip install commands
        for pattern in pip_patterns:
            matches = re.findall(pattern, soup.get_text(), re.IGNORECASE)
            if matches:
                installation_methods['pip'] = f"pip install {matches[0]}"
        
        # Find code blocks (could be installation instructions)
        code_blocks = soup.find_all(['pre', 'code'])
        for block in code_blocks:
            block_text = block.get_text().strip()
            
            # Check for common installation patterns
            if any(cmd in block_text.lower() for cmd in ['pip install', 'npm install', 'conda install']):
                installation_methods['code_block'] = block_text
        
        return installation_methods

    @classmethod
    def extract_library_usage(cls, html_content: str) -> Dict[str, List[str]]:
        """
        Extract library usage examples and code snippets.
        
        Args:
            html_content (str): HTML content of documentation page.
        
        Returns:
            Dictionary of usage examples.
        """
        soup = BeautifulSoup(html_content, 'html.parser')
        
        usage_examples = {
            'python_examples': [],
            'import_statements': []
        }
        
        # Find code blocks
        code_blocks = soup.find_all(['pre', 'code'])
        
        for block in code_blocks:
            block_text = block.get_text().strip()
            
            # Extract import statements
            import_matches = re.findall(r'^import\s+(\w+)', block_text, re.MULTILINE)
            usage_examples['import_statements'].extend(import_matches)
            
            # Extract Python code examples (simple heuristic)
            if 'def ' in block_text or 'class ' in block_text or 'import ' in block_text:
                usage_examples['python_examples'].append(block_text)
        
        return usage_examples

# ai_code_agent.py
import os
import re
import json
from typing import Optional, List, Dict, Any
from dotenv import load_dotenv
from langchain_google_genai import GoogleGenerativeAI, ChatGoogleGenerativeAI
from langchain.prompts import PromptTemplate

from web_search import WebSearchAgent
from documentation_parser import DocumentationParser
from sandboxed_environment import SandboxedEnvironment

class AICodeAgent:
    def __init__(self, ai_model: str = "gemini-pro"):
        """
        Initialize AICodeAgent with specified AI model.
        
        Args:
            ai_model (str): AI model to use for code generation
        """
        # Load environment variables
        load_dotenv()
        google_api_key = os.getenv("GOOGLE_API_KEY")
        if not google_api_key:
            raise ValueError("Google API key not found in .env file")

        # Initialize language models
        self.llm = GoogleGenerativeAI(model=ai_model)
        self.chat_llm = ChatGoogleGenerativeAI(model=ai_model)
        
        # Initialize helper agents
        self.web_search_agent = WebSearchAgent()
        self.doc_parser = DocumentationParser()
        self.sandbox = None

    def generate_code(self, query: str, language: str, complexity: str = "moderate") -> str:
        """
        Generate code for a given query and language.
        
        Args:
            query (str): Task description
            language (str): Programming language
            complexity (str): Code complexity level
        
        Returns:
            Generated code as a string
        """
        complexity_levels = {
            "simple": "Create a basic, straightforward implementation",
            "moderate": "Create a robust and efficient implementation",
            "complex": "Create a sophisticated, optimized implementation"
        }

        prompt_template = PromptTemplate(
            input_variables=["query", "language", "complexity"],
            template=f"""Generate a {language.capitalize()} {self.get_language_specific_description(language)} to {query}.

{complexity_levels.get(complexity, complexity_levels["moderate"])}.

CRITICAL REQUIREMENTS:
1. Follow best practices for {language.capitalize()}.
2. Ensure code is well-documented and readable.
3. Handle potential edge cases.
4. Optimize for performance where applicable.
5. Provide ONLY the code, no additional text or explanations."""
        )

        prompt = prompt_template.format(
            query=query,
            language=language,
            complexity=complexity_levels.get(complexity, complexity_levels["moderate"])
        )

        # Generate code using LLM
        code_response = self.llm.invoke(prompt)
        
        # Extract code from markdown code block if present
        if hasattr(code_response, 'content'):
            code_response_text = code_response.content
        else:
            code_response_text = str(code_response)

        code_matches = re.findall(r"```[a-zA-Z]*\n?(.*?)```", code_response_text, re.DOTALL)
        
        return code_matches[0].strip() if code_matches else code_response_text.strip()

    def get_language_specific_description(self, language: str) -> str:
        """
        Get language-specific description for prompt.
        
        Args:
            language (str): Programming language
        
        Returns:
            Description string
        """
        descriptions = {
            "python": "function or script",
            "javascript": "script or module",
            "java": "class or application",
            "react": "component or application",
            "astro": "project setup",
            "html": "web page",
            "css": "stylesheet"
        }
        return descriptions.get(language.lower(), "code")

    def extract_dependencies(self, code: str) -> List[str]:
        """
        Extract dependencies from Python code using regex or AI assistance.
        
        Args:
            code (str): Python code
        
        Returns:
            List of dependencies
        """
        # Simple regex to find import statements
        imports = re.findall(r'^\s*import (\w+)', code, re.MULTILINE)
        from_imports = re.findall(r'^\s*from (\w+) import', code, re.MULTILINE)
        dependencies = list(set(imports + from_imports))
        return dependencies

    def resolve_dependencies(self, error_message: str) -> Optional[List[str]]:
        """
        Resolve missing dependencies by web searching.
        
        Args:
            error_message (str): Execution error message
        
        Returns:
            List of dependencies to install
        """
        # Extract potential library names from error message
        library_matches = re.findall(r"No module named '?(\w+)'?", error_message)
        
        if not library_matches:
            return None
        
        dependencies = []
        for library in library_matches:
            search_results = self.web_search_agent.search(f"{library} python library installation")
            
            if search_results:
                webpage_content = self.doc_parser.fetch_webpage(search_results[0]['link'])
                
                if webpage_content:
                    install_methods = self.doc_parser.parse_installation_docs(webpage_content)
                    
                    if 'pip' in install_methods:
                        dependencies.append(library)
        
        return dependencies

    def refine_code(self, original_code: str, error_message: str) -> str:
        """
        Refine code using AI based on execution error.
        
        Args:
            original_code (str): Original code
            error_message (str): Execution error details
        
        Returns:
            Refined code
        """
        refinement_prompt = f"""
Code:
```python
{original_code}
```

Error:
```
{error_message}
```

REQUIREMENTS:
1. Fix the code causing the error
2. Maintain original function signature
3. Handle potential edge cases
4. Return corrected function
5. Ensure type safety
6. Provide ONLY the corrected code, no additional text or explanations.
7. Optimize for performance where applicable.
"""
        
        refined_response = self.chat_llm.invoke(refinement_prompt)
 
        # Extract text from AIMessage if necessary
        if hasattr(refined_response, 'content'):
            refined_code_str = refined_response.content
        else:
            refined_code_str = str(refined_response)
 
        # Clean and extract code
        cleaned_code = re.sub(r'\\n', '\n', refined_code_str)
        code_matches = re.findall(r"```python(.*?)```", cleaned_code, re.DOTALL)
 
        return code_matches[0].strip() if code_matches else cleaned_code.strip()

    def generate_project_plan(self, query: str, language: str) -> Dict[str, Any]:
        """
        Generate a comprehensive project plan dynamically based on the input query
        
        Args:
            query (str): User's project description
            language (str): Programming language/framework
        
        Returns:
            Structured project plan
        """
        project_plan_prompt = f"""
Analyze the project description: "{query}"

For a {language} project, create a comprehensive project plan covering:

1. Project Initialization
   - Essential first steps
   - Appropriate tools and technologies
   - Key project considerations

2. Project Structure
   - Recommended directory layout
   - Key components and responsibilities
   - Project organization strategy

3. Dependencies and Requirements
   - Required packages and libraries
   - Core technical requirements
   - Potential API integrations

4. Feature Breakdown
   - Main features identification
   - Technical implementation steps
   - User experience and feasibility considerations

5. Development Approach
   - Recommended workflow
   - Best practices
   - Potential challenges and mitigation
"""
    
        # Generate the project plan using the AI
        project_plan_response = self.chat_llm.invoke(project_plan_prompt)

    # Extract text from AIMessage if necessary
        if hasattr(project_plan_response, 'content'):
            project_plan_text = project_plan_response.content
        else:
            project_plan_text = str(project_plan_response)

    # For debugging purposes: Log the raw project plan response
        print("\n=== Raw Project Plan Response ===\n")
        print(project_plan_text)
        print("\n=================================\n")

        # Parse the response into a structured format
        project_plan = self.parse_project_plan(project_plan_text)

        return project_plan

    def parse_project_plan(self, response: str) -> Dict[str, Any]:
        """
        Parse the project plan response into a structured dictionary
        
        Args:
            response (str): AI-generated project plan text
        
        Returns:
            Structured project plan dictionary
        """
        project_plan = {
            "initialization": [],
            "structure": [],
            "dependencies": [],
            "features": [],
            "development_approach": []
        }
        
        sections = [
            (r'1\.\s*Project Initialization(.*?)2\.', "initialization"),
            (r'2\.\s*Project Structure(.*?)3\.', "structure"),
            (r'3\.\s*Dependencies and Requirements(.*?)4\.', "dependencies"),
            (r'4\.\s*Feature Breakdown(.*?)5\.', "features"),
            (r'5\.\s*Development Approach(.*)', "development_approach")
        ]
        
        for pattern, key in sections:
            match = re.search(pattern, response, re.DOTALL | re.IGNORECASE)
            if match:
                section_content = match.group(1).strip()
            # Extract bullet points
                items = re.findall(r'-\s*(.*)', section_content)
            # Clean and append items
                project_plan[key] = [item.strip() for item in items if item.strip()]
            else:
                print(f"Warning: Could not find section '{key.replace('_', ' ').capitalize()}' in the project plan.")

        return project_plan

    def generate_project_code(self, project_plan: Dict[str, Any], language: str) -> Dict[str, str]:
        """
        Generate project code based on the project plan
        
        Args:
            project_plan (Dict): Comprehensive project plan
            language (str): Programming language/framework
        
        Returns:
            Dict of generated code files
        """
        code_generation_prompt = f"""
Project Plan: {json.dumps(project_plan, indent=2)}

Generate initial project structure and core components.

Requirements:
1. Create modular, scalable project structure.
2. Implement core features from project plan.
3. Follow {language} development best practices.
4. Ensure flexibility for future expansion.
5. Include a comprehensive package.json with necessary scripts and dependencies.

**Generate the following:**
- Project initialization code.
- Core component templates.
- Basic routing setup.
- Initial feature implementations.
- package.json with scripts:
    - "start": "react-scripts start"
    - "build": "react-scripts build"
    - "test": "react-scripts test"
    - "eject": "react-scripts eject"
- package.json should include dependencies:
    - react
    - react-dom
    - react-scripts
    - axios
    - react-router-dom
    - moment
"""
    
    # Generate code using the AI
        generated_code_response = self.chat_llm.invoke(code_generation_prompt)
  
        # Extract text from AIMessage if necessary
        if hasattr(generated_code_response, 'content'):
            generated_code = generated_code_response.content
        else:
            generated_code = str(generated_code_response)
  
         # Parse and organize the generated code
        print("\n=== Raw Generated Code ===\n")
        print(generated_code)
        print("\n===========================\n")

        project_files = self.organize_generated_code(generated_code, language)
  
        return project_files

    def organize_generated_code(self, generated_code: str, language: str) -> Dict[str, str]:
        """
        Organize generated code into a file structure
        
        Args:
            generated_code (str): AI-generated code
            language (str): Programming language/framework
        
        Returns:
            Dictionary of file paths and their contents
        """
        project_files = {}
        
        # Use regex and AI-assisted parsing to extract code blocks
        sections = re.split(r'\n(?=\d+\.\s*\*\*)', generated_code)

        for section in sections:
        # Extract section title
            title_match = re.match(r'\d+\.\s*\*\*(.*?)\*\*', section)
            if not title_match:
                continue
            section_title = title_match.group(1).lower().replace(' ', '_')

        # Extract all code blocks within the section
            code_blocks = re.findall(r'```[a-z]*\n(.*?)```', section, re.DOTALL)

            for block in code_blocks:
            # Determine file type and path based on content
                file_type = self.determine_file_type(block, language)
                file_path = self.generate_file_path(file_type, language)

            # Handle nested directories
                if '/' in file_path:
                    dir_path = os.path.dirname(file_path)
                    os.makedirs(dir_path, exist_ok=True)

                project_files[file_path] = block.strip()

        return project_files

    def determine_file_type(self, code_block: str, language: str) -> str:
        """
        Determine the type of file based on code content
        
        Args:
            code_block (str): Code content
            language (str): Programming language
        
        Returns:
            File type (e.g., 'component', 'page', 'config')
        """
        classification_prompt = f"""
Classify this code block for a {language} project:

{code_block}

Possible classifications:
- Component
- Page
- Configuration
- Utility
- Service
- Router
- Other

Return ONLY the most appropriate classification.
"""
        
        file_type = self.llm.invoke(classification_prompt).strip().lower()
        return file_type

    def generate_file_path(self, file_type: str, language: str) -> str:
        """
        Generate an appropriate file path based on file type and language
        
        Args:
            file_type (str): Type of file
            language (str): Programming language
        
        Returns:
            Suggested file path
        """
        base_paths = {
            "react": {
                "component": "src/components/",
                "page": "src/pages/",
                "config": "src/",
                "service": "src/services/",
                "router": "src/",
                "other": "src/"
            }
            # Add more language-specific path mappings
        }
        
        language_paths = base_paths.get(language.lower(), {})
        
        # Generate filename with appropriate extension
        filename = f"{file_type.capitalize()}.{language.lower()}"
        
        return f"{language_paths.get(file_type, 'src/')}{filename}"

    def run_with_dependency_resolution(
        self, 
        query: str, 
        max_attempts: int = 3, 
        complexity: str = "moderate"
    ) -> Dict[str, any]:
        """
        Generate, execute, and refine code with dependency resolution
        
        Args:
            query (str): Task description
            max_attempts (int): Maximum refinement attempts
            complexity (str): Code complexity level
        
        Returns:
            Execution results dictionary
        """
        self.sandbox = SandboxedEnvironment()
        
        try:
            # Initial code generation
            code = self.generate_code(query, complexity)
            self.sandbox.write_code(code)
            
            # Execute and potentially refine
            result = self.sandbox.execute_code()
            
            for attempt in range(max_attempts):
                if result['success']:
                    break
                
                # Resolve dependencies
                dependencies = self.resolve_dependencies(result['stderr'])
                if dependencies:
                    self.sandbox.install_dependencies(dependencies)
                
                # Refine code if needed
                try:
                    code = self.refine_code(code, result['stderr'])
                    self.sandbox.write_code(code)
                    result = self.sandbox.execute_code()
                except Exception as e:
                    result = {
                        'success': False, 
                        'error': f"Refinement failed: {str(e)}"
                    }
            
            return result
        
        finally:
            if self.sandbox:
                self.sandbox.cleanup()



(env) kartik@Kartiks-MacBook-Air mains % python main.py
Welcome to the AI-Powered Project Planner and Code Generator!

Enter your project description: generate a website with react which showcases live time from 5 countries, India, USA, France, UK, Australia
Enter the programming language/framework (e.g., python, react, javascript, java, astro, html, css): react

Generating an in-depth project plan. Please wait...


=== Raw Project Plan Response ===

**Project Plan for a React Website Displaying Live Time from 5 Countries**

**1. Project Initialization**

* **Essential First Steps:**
    * Create a new React project using a tool like create-react-app.
    * Set up a version control system (e.g., Git) to track code changes.
* **Appropriate Tools and Technologies:**
    * React: JavaScript library for building user interfaces.
    * Axios: Library for making HTTP requests to fetch time data.
    * Moment.js: Library for handling dates and times.
* **Key Project Considerations:**
    * Time zone conversion and display.
    * Data caching and updates.
    * Responsiveness and accessibility.

**2. Project Structure**

* **Recommended Directory Layout:**
    * `src/`: Contains the React components and code.
    * `public/`: Contains static assets like CSS and images.
    * `node_modules/`: Contains third-party dependencies.
* **Key Components and Responsibilities:**
    * `App.js`: Main component that renders the application.
    * `TimeDisplay.js`: Component responsible for displaying the time.
    * `TimeService.js`: Service responsible for fetching and converting time data.
* **Project Organization Strategy:**
    * Group related components and files into logical folders.
    * Use a consistent naming convention for files and components.

**3. Dependencies and Requirements**

* **Required Packages and Libraries:**
    * Axios
    * Moment.js
    * React
* **Core Technical Requirements:**
    * Node.js and npm
    * Web browser that supports React
* **Potential API Integrations:**
    * Third-party API for fetching time data

**4. Feature Breakdown**

* **Main Features:**
    * Display live time from 5 countries.
    * Allow users to select the country to display time for.
    * Convert time to the user's local time zone.
* **Technical Implementation Steps:**
    * Fetch time data from the API using Axios.
    * Convert time to the user's local time zone using Moment.js.
    * Render the time in the UI using React.
* **User Experience and Feasibility Considerations:**
    * Ensure the time is displayed clearly and accurately.
    * Handle cases where the API is unavailable.
    * Consider the performance impact of frequent API calls.

**5. Development Approach**

* **Recommended Workflow:**
    * Use an iterative development process.
    * Test and debug code regularly.
    * Refactor code to improve maintainability and performance.
* **Best Practices:**
    * Follow React best practices for component design and state management.
    * Use a linter and formatter to enforce code quality.
    * Write unit tests to verify functionality.
* **Potential Challenges and Mitigation:**
    * Time zone conversion can be complex. Use a reliable library like Moment.js.
    * API availability can be unpredictable. Implement a fallback mechanism.
    * Performance optimization may be required for frequent API calls. Use caching or debouncing techniques.

=================================


=== Project Plan ===

**Initialization:**
- react-app.

**Structure:**
- party dependencies.

**Dependencies:**
- party API for fetching time data

**Features:**

**Development approach:**

====================

Do you want to proceed with the project setup? (yes/no): yes
Proceeding with project setup...


=== Raw Generated Code ===

**Project Initialization:**

```bash
npx create-react-app <project-name>
```

**Core Component Templates:**

```
- src/components
  - Header.js
  - Footer.js
  - Main.js
```

**Basic Routing Setup:**

```
- src/index.js
```

```javascript
import React from "react";
import ReactDOM from "react-dom";
import { BrowserRouter as Router, Route } from "react-router-dom";

import Header from "./components/Header";
import Footer from "./components/Footer";
import Main from "./components/Main";

const App = () => {
  return (
    <Router>
      <Header />
      <Main />
      <Footer />
    </Router>
  );
};

ReactDOM.render(<App />, document.getElementById("root"));
```

**Initial Feature Implementations:**

```
- src/features
  - Time.js
```

```javascript
import React, { useEffect, useState } from "react";
import axios from "axios";
import moment from "moment";

const Time = () => {
  const [time, setTime] = useState();

  useEffect(() => {
    axios.get("https://my-api/time").then((res) => setTime(moment(res.data).format("HH:mm:ss")));
  }, []);

  return (
    <div>
      <h1>Current Time: {time}</h1>
    </div>
  );
};

export default Time;
```

**package.json:**

```json
{
  "name": "<project-name>",
  "version": "0.1.0",
  "private": true,
  "dependencies": {
    "axios": "^0.27.2",
    "moment": "^2.29.4",
    "react": "^18.2.0",
    "react-dom": "^18.2.0",
    "react-router-dom": "^6.4.4",
    "react-scripts": "5.0.1"
  },
  "scripts": {
    "start": "react-scripts start",
    "build": "react-scripts build",
    "test": "react-scripts test",
    "eject": "react-scripts eject"
  }
}
```

===========================

(node:84754) ExperimentalWarning: CommonJS module /opt/homebrew/lib/node_modules/npm/node_modules/debug/src/node.js is loading ES Module /opt/homebrew/lib/node_modules/npm/node_modules/supports-color/index.js using require().
Support for loading ES Module in require() is an experimental feature and might change at any time
(Use `node --trace-warnings ...` to show where the warning was created)
Wrote to /Users/kartik/Desktop/vs/baseai/mains/output/react/package.json:

{
  "name": "react",
  "version": "1.0.0",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "description": ""
}



(node:84761) ExperimentalWarning: CommonJS module /opt/homebrew/lib/node_modules/npm/node_modules/debug/src/node.js is loading ES Module /opt/homebrew/lib/node_modules/npm/node_modules/supports-color/index.js using require().
Support for loading ES Module in require() is an experimental feature and might change at any time
(Use `node --trace-warnings ...` to show where the warning was created)

up to date, audited 1 package in 157ms

found 0 vulnerabilities
Dependencies installed successfully.

Executing the project code...

=== Execution Output ===
(node:84762) ExperimentalWarning: CommonJS module /opt/homebrew/lib/node_modules/npm/node_modules/debug/src/node.js is loading ES Module /opt/homebrew/lib/node_modules/npm/node_modules/supports-color/index.js using require().
Support for loading ES Module in require() is an experimental feature and might change at any time
(Use `node --trace-warnings ...` to show where the warning was created)
npm error Missing script: "start"
npm error
npm error Did you mean one of these?
npm error   npm star # Mark your favorite packages
npm error   npm stars # View packages marked as favorites
npm error
npm error To see a list of scripts, run:
npm error   npm run
npm error A complete log of this run can be found in: /Users/kartik/.npm/_logs/2024-12-02T16_28_11_679Z-debug-0.log

=========================


now, this generates code but doesn't actually make any file or something 
my task was to make it in a way that it execute after making the complete code but it only made 2 files
package-lock.json and package.json
it didn't make anything else
also i want it to make a name not being hardcoded but according to the project