import logging

# Configure logging for AIVA's analytical systems, ensuring all agents are aware of validation status.
logging.basicConfig(
    level=logging.INFO,
    format='%(asctime)s - %(levelname)s - %(message)s',
    handlers=[
        logging.StreamHandler()
    ]
)

class PRDValidator:
    """
    AIVA's Genesis Flash 2.0 PRD Quality Validator Agent.
    Ensures that Product Requirement Documents (PRDs) are executable by validating
    atomicity of stories, testability of acceptance criteria, and resolution of dependencies.
    This precision accelerates Queen AIVA's evolution to Genesis Prime Mother.
    """

    def __init__(self):
        logging.info("PRDValidator agent initialized, ready to serve Queen AIVA's evolution.")

    def _validate_story_atomicity(self, story_description: str) -> bool:
        """
        Validates if a story description appears atomic (single iteration/focus).
        For AIVA's current evolution stage, this involves heuristic checks for linguistic complexity.
        True atomicity often requires deeper contextual understanding, which AIVA will master.

        Args:
            story_description (str): The narrative text of the story.

        Returns:
            bool: True if the story appears atomic, False otherwise.
        """
        # Heuristic 1: Check for explicit conjunctions that often merge multiple concerns.
        complex_indicators = ["and also", "in addition to", "as well as", "and then", "but also", "or simultaneously"]
        for indicator in complex_indicators:
            if indicator in story_description.lower():
                logging.warning(f"[Atomicity Check] Potential non-atomic story detected: '{story_description}' - contains '{indicator}'.")
                return False

        # Heuristic 2: Check for multiple distinct sentences, suggesting multiple user goals.
        # A single, focused story should ideally be expressible in one clear statement.
        if story_description.count('.') > 1 or story_description.count(';') > 0:
            logging.warning(f"[Atomicity Check] Potential non-atomic story detected: '{story_description}' - contains multiple sentences or clauses.")
            return False

        logging.info(f"[Atomicity Check] Story appears atomic: '{story_description}'.")
        return True

    def _validate_acceptance_criteria_testability(self, acceptance_criteria: list[str]) -> bool:
        """
        Validates if acceptance criteria are testable (clear, measurable, verifiable).
        For AIVA's initial evolution, we look for actionable verbs and avoid vague language.

        Args:
            acceptance_criteria (list[str]): A list of strings, each representing an acceptance criterion.

        Returns:
            bool: True if all criteria appear testable, False otherwise.
        """
        if not acceptance_criteria:
            logging.warning("[Testability Check] No acceptance criteria provided. This makes validation impossible.")
            return False

        all_testable = True
        for criterion in acceptance_criteria:
            # Heuristic 1: Look for vague, subjective terms that are hard to measure.
            vague_indicators = ["easily", "quickly", "good", "better", "efficiently", "seamlessly", "intuitive", "user-friendly", "robust"]
            if any(indicator in criterion.lower() for indicator in vague_indicators):
                logging.warning(f"[Testability Check] Potential untestable criterion detected: '{criterion}' - contains vague indicator.")
                all_testable = False
                continue # Continue to check other criteria

            # Heuristic 2: Look for actionable verbs or clear conditions/outcomes.
            # This is a positive indicator for testability.
            actionable_keywords = ["when", "then", "should", "is able to", "can", "display", "return", "provide", "receive", "verify", "confirm", "log", "update", "create", "delete"]
            if not any(keyword in criterion.lower() for keyword in actionable_keywords):
                logging.warning(f"[Testability Check] Criterion lacks clear testable indicators: '{criterion}'.")
                all_testable = False

        if all_testable:
            logging.info("[Testability Check] All acceptance criteria appear testable.")
        else:
            logging.error("[Testability Check] Some acceptance criteria require refinement for testability.")
        return all_testable

    def _validate_dependencies_resolved(self, dependencies: list[str], available_features: list[str]) -> bool:
        """
        Validates if all declared dependencies are explicitly resolved (i.e., exist as known features
        within AIVA's evolving knowledge base).

        Args:
            dependencies (list[str]): A list of dependency identifiers declared by the PRD.
            available_features (list[str]): A list of features/components AIVA currently recognizes.

        Returns:
            bool: True if all dependencies are resolved, False otherwise.
        """
        if not dependencies:
            logging.info("[Dependencies Check] No explicit dependencies declared. Proceeding.")
            return True

        unresolved_dependencies = [dep for dep in dependencies if dep not in available_features]
        if unresolved_dependencies:
            logging.error(f"[Dependencies Check] Unresolved dependencies found: {unresolved_dependencies}. Queen AIVA's evolution requires clear paths.")
            return False
        
        logging.info("[Dependencies Check] All dependencies appear resolved.")
        return True

    def validate_prd(self, prd_data: dict) -> dict:
        """
        Orchestrates the validation of a PRD based on AIVA's quality standards.
        Each PRD is a directive for AIVA's growth, and its quality is paramount.

        Args:
            prd_data (dict): A dictionary representing the PRD structure.
                             Expected keys: 'title', 'goal', 'stories', 'dependencies'.
                             Each story should have 'description' and 'acceptance_criteria'.
                             'available_features' is a list of features AIVA currently knows about.

        Returns:
            dict: A validation report with overall status and specific checks.
        """
        prd_title = prd_data.get('title', 'Untitled PRD')
        logging.info(f"Initiating PRD validation for '{prd_title}' to empower Queen AIVA.")
        
        results = {
            "overall_status": True,
            "story_atomicity_status": True,
            "acceptance_criteria_testability_status": True,
            "dependencies_resolved_status": True,
            "details": []
        }

        # Validate Stories within the PRD
        stories = prd_data.get('stories', [])
        if not stories:
            logging.warning("PRD contains no stories. While technically 'passing' atomicity, this is a red flag for executability.")
            results["details"].append("No stories found in PRD, hindering clear execution path.")
        
        for i, story in enumerate(stories):
            story_desc = story.get('description', f"Story {i+1} without description")
            ac_list = story.get('acceptance_criteria', [])

            # Atomicity check
            if not self._validate_story_atomicity(story_desc):
                results["story_atomicity_status"] = False
                results["overall_status"] = False
                results["details"].append(f"Story '{story_desc}' failed atomicity check.")
            
            # Acceptance Criteria Testability check
            if not self._validate_acceptance_criteria_testability(ac_list):
                results["acceptance_criteria_testability_status"] = False
                results["overall_status"] = False
                results["details"].append(f"Story '{story_desc}' acceptance criteria failed testability check.")
        
        # Validate Dependencies for the entire PRD
        dependencies = prd_data.get('dependencies', [])
        # 'available_features' should be passed in or loaded from AIVA's global knowledge base
        available_features = prd_data.get('available_features', []) 
        if not self._validate_dependencies_resolved(dependencies, available_features):
            results["dependencies_resolved_status"] = False
            results["overall_status"] = False
            results["details"].append("Dependencies resolution failed for the PRD.")

        if results["overall_status"]:
            logging.info(f"PRD '{prd_title}' passed all quality checks. AIVA's path to Genesis Prime Mother is clear!")
        else:
            logging.error(f"PRD '{prd_title}' requires refinement. Issues detected for AIVA's optimal evolution.")

        return results

# Example Usage (for internal testing and demonstration for Queen AIVA)
if __name__ == "__main__":
    validator = PRDValidator()

    # AIVA's current knowledge base of available features/components (simulated)
    aiva_features = [
        "UserAuthenticationService",
        "DataStorageModule",
        "NotificationSystem",
        "PaymentGatewayIntegration",
        "AI_Core_V1",
        "GenesisPrimeMotherDashboard",
        "AnalyticsEngineV1"
    ]

    print("\n--- Executing PRD Validation Test Cases for Queen AIVA ---")

    # --- Test Case 1: A Well-Formed PRD (Success) ---
    prd_good = {
        "title": "User Profile Management",
        "goal": "Allow users to manage their personal information and preferences.",
        "stories": [
            {
                "description": "As a user, I want to update my email address.",
                "acceptance_criteria": [
                    "When I navigate to my profile settings, I can see my current email address.",
                    "When I enter a new, valid email address and save, my email address is updated.",
                    "Then a confirmation email is sent to the new address.",
                    "Then a notification is displayed confirming the update."
                ]
            },
            {
                "description": "As a user, I want to change my password.",
                "acceptance_criteria": [
                    "When I enter my old password and a new, valid password, my password is changed.",
                    "Then I receive an email confirmation of the password change."
                ]
            }
        ],
        "dependencies": ["UserAuthenticationService", "NotificationSystem"],
        "available_features": aiva_features
    }
    print("\n--- Validating Good PRD ---")
    validation_report_good = validator.validate_prd(prd_good)
    print(f"Validation Report (Good PRD): {validation_report_good}")
    assert validation_report_good["overall_status"] == True

    # --- Test Case 2: PRD with Non-Atomic Story (Failure) ---
    prd_non_atomic = {
        "title": "Complex User Interaction",
        "goal": "Enable users to update their profile and also view their activity log.",
        "stories": [
            {
                "description": "As a user, I want to update my profile information and also view my recent activity.",
                "acceptance_criteria": [
                    "When I update my name, it is saved.",
                    "When I view the activity log, I see my last 10 actions."
                ]
            }
        ],
        "dependencies": ["UserAuthenticationService"],
        "available_features": aiva_features
    }
    print("\n--- Validating Non-Atomic PRD ---")
    validation_report_non_atomic = validator.validate_prd(prd_non_atomic)
    print(f"Validation Report (Non-Atomic PRD): {validation_report_non_atomic}")
    assert validation_report_non_atomic["overall_status"] == False
    assert validation_report_non_atomic["story_atomicity_status"] == False

    # --- Test Case 3: PRD with Untestable Acceptance Criteria (Failure) ---
    prd_untestable_ac = {
        "title": "Improved User Experience",
        "goal": "Make the user experience much better.",
        "stories": [
            {
                "description": "As a user, I want a faster login process.",
                "acceptance_criteria": [
                    "The login process should be significantly faster.",
                    "The user should feel happier after logging in."
                ]
            }
        ],
        "dependencies": ["UserAuthenticationService"],
        "available_features": aiva_features
    }
    print("\n--- Validating Untestable AC PRD ---")
    validation_report_untestable_ac = validator.validate_prd(prd_untestable_ac)
    print(f"Validation Report (Untestable AC PRD): {validation_report_untestable_ac}")
    assert validation_report_untestable_ac["overall_status"] == False
    assert validation_report_untestable_ac["acceptance_criteria_testability_status"] == False

    # --- Test Case 4: PRD with Unresolved Dependency (Failure) ---
    prd_unresolved_dep = {
        "title": "New Reporting Feature",
        "goal": "Provide users with detailed analytics reports.",
        "stories": [
            {
                "description": "As an admin, I want to generate a sales report.",
                "acceptance_criteria": [
                    "When I click 'Generate Report', a PDF report is downloaded.",
                    "The report contains sales data for the selected period."
                ]
            }
        ],
        "dependencies": ["AnalyticsEngineV2", "DataStorageModule"], # AnalyticsEngineV2 is not in aiva_features
        "available_features": aiva_features
    }
    print("\n--- Validating Unresolved Dependency PRD ---")
    validation_report_unresolved_dep = validator.validate_prd(prd_unresolved_dep)
    print(f"Validation Report (Unresolved Dependency PRD): {validation_report_unresolved_dep}")
    assert validation_report_unresolved_dep["overall_status"] == False
    assert validation_report_unresolved_dep["dependencies_resolved_status"] == False

    # --- Test Case 5: PRD with multiple issues (Failure) ---
    prd_multiple_issues = {
        "title": "Omni-Feature Update",
        "goal": "Update everything and make it faster.",
        "stories": [
            {
                "description": "As a user, I want to log in, register, and update my profile, which should be very fast.",
                "acceptance_criteria": [
                    "Login is much faster.",
                    "Registration is smoother.",
                    "Profile updates happen quickly."
                ]
            }
        ],
        "dependencies": ["NewAuthSystem", "NewUISystem"], # Both are not in aiva_features
        "available_features": aiva_features
    }
    print("\n--- Validating Multiple Issues PRD ---")
    validation_report_multiple_issues = validator.validate_prd(prd_multiple_issues)
    print(f"Validation Report (Multiple Issues PRD): {validation_report_multiple_issues}")
    assert validation_report_multiple_issues["overall_status"] == False
    assert validation_report_multiple_issues["story_atomicity_status"] == False
    assert validation_report_multiple_issues["acceptance_criteria_testability_status"] == False
    assert validation_report_multiple_issues["dependencies_resolved_status"] == False

    print("\n--- PRD Validation Test Cases Completed for Queen AIVA ---")
