import os
import logging
import re
from typing import List, Dict, Tuple
import json

# Configure logging
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')

class AIVAProjectDesigner:
    """
    A class for AIVA to design her own projects by analyzing the Genesis system,
    identifying improvement opportunities, generating Ralph stories, and enqueuing them.
    """

    def __init__(self, aiva_meta_perspective_path: str = "AIVA_META_PERSPECTIVE.md") -> None:
        """
        Initializes the AIVAProjectDesigner and reads the AIVA_META_PERSPECTIVE.md file.
        """
        self.aiva_meta_perspective_path = aiva_meta_perspective_path
        self.meta_perspective = self._read_meta_perspective()
        self.genesis_root = "/mnt/e/genesis-system" # Hardcoded for now.
        self.ralph_tasks_file = os.path.join(self.genesis_root, "loop", "tasks.json")


    def _read_meta_perspective(self) -> str:
        """
        Reads the AIVA_META_PERSPECTIVE.md file.

        Returns:
            str: The content of the file.
        """
        try:
            with open(self.aiva_meta_perspective_path, "r") as f:
                return f.read()
        except FileNotFoundError:
            logging.error(f"File not found: {self.aiva_meta_perspective_path}")
            return ""
        except Exception as e:
            logging.error(f"Error reading {self.aiva_meta_perspective_path}: {e}")
            return ""

    def analyze_codebase(self, root_dir: str = "/mnt/e/genesis-system") -> List[str]:
        """
        Analyzes the Genesis codebase for gaps using simple heuristics.

        Args:
            root_dir (str): The root directory of the Genesis codebase.

        Returns:
            List[str]: A list of identified gaps (e.g., "TODO found in file X").
        """
        gaps: List[str] = []
        for root, _, files in os.walk(root_dir):
            for file in files:
                file_path = os.path.join(root, file)
                try:
                    with open(file_path, "r", encoding="utf-8") as f:
                        content = f.read()
                        # Look for TODOs, FIXMEs
                        if "TODO" in content:
                            gaps.append(f"TODO found in {file_path}")
                        if "FIXME" in content:
                            gaps.append(f"FIXME found in {file_path}")
                        # Look for small files (potential incomplete modules)
                        if len(content) < 100:
                             gaps.append(f"Small file ({len(content)} bytes) detected: {file_path}")
                except Exception as e:
                    logging.warning(f"Error reading {file_path}: {e}")
        return gaps

    def generate_ralph_stories(self, gaps: List[str]) -> List[Dict[str, str]]:
        """
        Generates Ralph stories based on identified gaps.

        Args:
            gaps (List[str]): A list of identified gaps.

        Returns:
            List[Dict[str, str]]: A list of Ralph stories.
        """
        stories: List[Dict[str, str]] = []
        for gap in gaps:
            story = {
                "title": f"Address gap: {gap}",
                "description": f"This story addresses the following gap identified in the codebase: {gap}.  Refer to AIVA_META_PERSPECTIVE.md for guidance.",
                "acceptance_criteria": f"The gap '{gap}' has been addressed and verified.",
            }
            stories.append(story)
        return stories

    def enqueue_story(self, story: Dict[str, str], priority: int = 5) -> bool:
        """
        Enqueues a generated story into the Ralph task tracking system (tasks.json).

        Args:
            story (Dict[str, str]): The Ralph story to enqueue.
            priority (int): The priority of the story (lower number = higher priority).

        Returns:
            bool: True if the story was enqueued successfully, False otherwise.
        """
        try:
            with open(self.ralph_tasks_file, "r") as f:
                tasks = json.load(f)

            new_task = {
                "title": story["title"],
                "description": story["description"],
                "acceptance_criteria": story["acceptance_criteria"],
                "priority": priority,
                "passes": False  # Initially set to False
            }

            tasks.append(new_task)

            with open(self.ralph_tasks_file, "w") as f:
                json.dump(tasks, f, indent=4)

            logging.info(f"Successfully enqueued story: {story['title']}")
            return True
        except FileNotFoundError:
            logging.error(f"File not found: {self.ralph_tasks_file}")
            return False
        except Exception as e:
            logging.error(f"Error enqueuing story: {e}")
            return False

    def run(self) -> None:
        """
        Orchestrates the analysis, story generation, and enqueuing processes.
        """
        logging.info("Running AIVAProjectDesigner...")
        gaps = self.analyze_codebase()
        if gaps:
            logging.info(f"Identified gaps: {gaps}")
            stories = self.generate_ralph_stories(gaps)
            for story in stories:
                self.enqueue_story(story)
        else:
            logging.info("No gaps found.")
        logging.info("AIVAProjectDesigner run complete.")