import asyncio
import re
import hashlib
from datetime import datetime

# Mock database connector (replace with actual implementation)
class MockMemory:
    def __init__(self):
        self.audit_logs = []
        self.worker_trust = {}
        self.data_quality = {} # Store data quality metrics
        self.data_storage = {} # Simulate data storage

    def log_audit(self, system, event_type, data):
        self.audit_logs.append({"system": system, "event_type": event_type, "data": data})

    def update_worker_trust(self, worker_id, passed):
        if worker_id not in self.worker_trust:
            self.worker_trust[worker_id] = {"successes": 0, "failures": 0}
        if passed:
            self.worker_trust[worker_id]["successes"] += 1
        else:
            self.worker_trust[worker_id]["failures"] += 1

    def store_data_quality(self, data_id, quality_score, metadata):
        self.data_quality[data_id] = {"score": quality_score, "metadata": metadata}

    def store_data(self, data_id, data):
        self.data_storage[data_id] = data

    def retrieve_data(self, data_id):
        return self.data_storage.get(data_id)

memory = MockMemory()

# --- Gate Definitions ---

class ValidationGate:
    def __init__(self, memory, next_gate=None):
        self.memory = memory
        self.next_gate = next_gate
        self.gate_name = "BaseGate"

    async def validate(self, data, task_description, worker_id, metadata):
        """Abstract validation method.  Must be overridden."""
        raise NotImplementedError

    async def _log_decision(self, data_id, decision, reason, details=None):
        log_data = {
            "gate": self.gate_name,
            "decision": decision,
            "reason": reason,
            "details": details,
            "timestamp": datetime.utcnow().isoformat()
        }
        self.memory.log_audit("validation_gate", f"{self.gate_name}_{data_id}", log_data)
        print(f"[{self.gate_name}] Decision: {decision}, Reason: {reason}") # Console output

    async def _chain_validation(self, data, task_description, worker_id, metadata):
        if self.next_gate:
            return await self.next_gate.validate(data, task_description, worker_id, metadata)
        else:
            return True  # End of the chain


class GateAlpha(ValidationGate):
    """Gate Alpha: Input Validity (Source Data Quality)"""
    def __init__(self, memory, next_gate=None):
        super().__init__(memory, next_gate)
        self.gate_name = "GateAlpha"

    async def validate(self, data, task_description, worker_id, metadata):
        data_id = metadata.get("data_id", "unknown_data")
        quality_score = self._assess_data_quality(data)

        self.memory.store_data_quality(data_id, quality_score, metadata)

        if quality_score >= 0.7:
            await self._log_decision(data_id, "PASS", "Data quality sufficient.", {"quality_score": quality_score})
            return await self._chain_validation(data, task_description, worker_id, metadata)
        else:
            await self._log_decision(data_id, "FAIL", "Data quality insufficient.", {"quality_score": quality_score})
            return False

    def _assess_data_quality(self, data):
        """Placeholder for data quality assessment logic."""
        # Example: Check if the data is not empty and contains relevant keywords
        if not data:
            return 0.0
        keywords = ["example", "data", "important"]
        keyword_count = sum(1 for keyword in keywords if keyword in data.lower())
        return min(1.0, keyword_count / len(keywords))  # Normalize to 0-1


class GateBeta(ValidationGate):
    """Gate Beta: Output Quality (Accuracy & Completeness)"""
    def __init__(self, memory, next_gate=None):
        super().__init__(memory, next_gate)
        self.gate_name = "GateBeta"

    async def validate(self, data, task_description, worker_id, metadata):
        data_id = metadata.get("data_id", "unknown_data")
        accuracy_score = self._check_accuracy(data, task_description)
        completeness_score = self._check_completeness(data)

        overall_score = (accuracy_score + completeness_score) / 2

        if overall_score >= 0.8:
            await self._log_decision(data_id, "PASS", "Output accuracy and completeness sufficient.", {"accuracy_score": accuracy_score, "completeness_score": completeness_score})
            return await self._chain_validation(data, task_description, worker_id, metadata)
        else:
            await self._log_decision(data_id, "FAIL", "Output accuracy or completeness insufficient.", {"accuracy_score": accuracy_score, "completeness_score": completeness_score})
            return False

    def _check_accuracy(self, output, task_description):
        """Placeholder for accuracy check logic."""
        # Example: Check if the output contains expected keywords from the task description
        expected_keywords = task_description.lower().split()
        found_keywords = sum(1 for keyword in expected_keywords if keyword in output.lower())
        return min(1.0, found_keywords / len(expected_keywords)) if expected_keywords else 1.0

    def _check_completeness(self, output):
        """Placeholder for completeness check logic."""
        # Example: Check if the output is not too short
        return 1.0 if len(output) > 10 else 0.5  # Arbitrary length threshold


class GateGamma(ValidationGate):
    """Gate Gamma: Insight Purity (Hallucination Detection)"""
    def __init__(self, memory, next_gate=None):
        super().__init__(memory, next_gate)
        self.gate_name = "GateGamma"

    async def validate(self, data, task_description, worker_id, metadata):
        data_id = metadata.get("data_id", "unknown_data")
        hallucination_score = self._detect_hallucinations(data)

        if hallucination_score <= 0.2:
            await self._log_decision(data_id, "PASS", "Hallucination level acceptable.", {"hallucination_score": hallucination_score})
            return await self._chain_validation(data, task_description, worker_id, metadata)
        else:
            await self._log_decision(data_id, "FAIL", "Hallucination level too high.", {"hallucination_score": hallucination_score})
            return False

    def _detect_hallucinations(self, text):
        """Placeholder for hallucination detection logic."""
        # Example: Check for nonsensical phrases or contradictions
        nonsensical_phrases = ["purple elephants fly", "water is dry"]
        phrase_count = sum(1 for phrase in nonsensical_phrases if phrase in text.lower())
        return min(1.0, phrase_count / len(nonsensical_phrases)) if nonsensical_phrases else 0.0


class GateDelta(ValidationGate):
    """Gate Delta: Memory Integration (Validate Storage Operations)"""
    def __init__(self, memory, next_gate=None):
        super().__init__(memory, next_gate)
        self.gate_name = "GateDelta"

    async def validate(self, data, task_description, worker_id, metadata):
        data_id = metadata.get("data_id", "unknown_data")
        storage_success = self._validate_storage(data_id, data)

        if storage_success:
            await self._log_decision(data_id, "PASS", "Data storage successful.", {"data_id": data_id})
            return await self._chain_validation(data, task_description, worker_id, metadata)
        else:
            await self._log_decision(data_id, "FAIL", "Data storage failed.", {"data_id": data_id})
            return False

    def _validate_storage(self, data_id, data):
        """Placeholder for storage validation logic."""
        try:
            self.memory.store_data(data_id, data)
            retrieved_data = self.memory.retrieve_data(data_id)
            return retrieved_data == data  # Check if stored data matches
        except Exception as e:
            print(f"Storage error: {e}")
            return False


class GateEpsilon(ValidationGate):
    """Gate Epsilon: Strategy Alignment (Revenue Pathway Fit)"""
    def __init__(self, memory, next_gate=None):
        super().__init__(memory, next_gate)
        self.gate_name = "GateEpsilon"

    async def validate(self, data, task_description, worker_id, metadata):
        data_id = metadata.get("data_id", "unknown_data")
        alignment_score = self._assess_strategy_alignment(data, task_description)

        if alignment_score >= 0.6:
            await self._log_decision(data_id, "PASS", "Strategy alignment sufficient.", {"alignment_score": alignment_score})
            return await self._chain_validation(data, task_description, worker_id, metadata)
        else:
            await self._log_decision(data_id, "FAIL", "Strategy alignment insufficient.", {"alignment_score": alignment_score})
            return False

    def _assess_strategy_alignment(self, data, task_description):
        """Placeholder for strategy alignment assessment logic."""
        # Example: Check if the output aligns with predefined revenue strategies
        revenue_strategies = ["increase sales", "reduce costs", "improve customer satisfaction"]
        strategy_match_count = sum(1 for strategy in revenue_strategies if strategy in data.lower() or strategy in task_description.lower())
        return min(1.0, strategy_match_count / len(revenue_strategies)) if revenue_strategies else 1.0


class GateZeta(ValidationGate):
    """Gate Zeta: Budget Compliance (Resource Monitoring)"""
    def __init__(self, memory, next_gate=None):
        super().__init__(memory, next_gate)
        self.gate_name = "GateZeta"

    async def validate(self, data, task_description, worker_id, metadata):
        data_id = metadata.get("data_id", "unknown_data")
        budget_compliance = self._check_budget_compliance(metadata)

        if budget_compliance:
            await self._log_decision(data_id, "PASS", "Budget compliance verified.", {"metadata": metadata})
            return True  # End of the chain
        else:
            await self._log_decision(data_id, "FAIL", "Budget compliance failed.", {"metadata": metadata})
            return False

    def _check_budget_compliance(self, metadata):
        """Placeholder for budget compliance check logic."""
        # Example: Check if the resource usage is within the allocated budget
        resource_usage = metadata.get("resource_usage", 0)
        budget_limit = metadata.get("budget_limit", 100)
        return resource_usage <= budget_limit

# --- Orchestrator ---
class SixGateValidator:
    def __init__(self):
        self.memory = memory
        # Chain the gates together
        self.gate_alpha = GateAlpha(self.memory)
        self.gate_beta = GateBeta(self.memory, next_gate=self.gate_alpha)
        self.gate_gamma = GateGamma(self.memory, next_gate=self.gate_beta)
        self.gate_delta = GateDelta(self.memory, next_gate=self.gate_gamma)
        self.gate_epsilon = GateEpsilon(self.memory, next_gate=self.gate_delta)
        self.gate_zeta = GateZeta(self.memory, next_gate=self.gate_epsilon)


    async def validate_worker_output(self, output, task_description, worker_id, metadata):
        """Run complete 6-gate validation suite"""

        # Start validation chain at Gate Zeta
        passed = await self.gate_zeta.validate(output, task_description, worker_id, metadata)

        # Update worker trust (Patent P9)
        try:
            self.memory.update_worker_trust(worker_id, passed)
        except Exception as e:
            print(f"[WARNING] Trust update failed: {e}")

        report = {
            "timestamp": datetime.utcnow().isoformat(),
            "worker_id": worker_id,
            "passed": passed,
        }

        # Log to immutable audit trail
        try:
            self.memory.log_audit("six_gate_validation", worker_id, report)
        except Exception as e:
            print(f"[WARNING] Audit logging failed: {e}")

        return report

# Global validator instance
validator = SixGateValidator()

# --- Example Usage ---
async def main():
    output = "This is some example data. It should increase sales and improve customer satisfaction. purple elephants fly"
    task_description = "Analyze the data and provide insights."
    worker_id = "worker123"
    metadata = {
        "data_id": "data456",
        "output_hash": hashlib.sha256(output.encode()).hexdigest(),
        "timestamp": datetime.utcnow().isoformat(),
        "resource_usage": 50,
        "budget_limit": 100
    }

    report = await validator.validate_worker_output(output, task_description, worker_id, metadata)
    print("Validation Report:", report)

if __name__ == "__main__":
    asyncio.run(main())