"""
Performance Shell - C Backend Tests (with Python fallback)
Standalone version for cubesquare package.
"""

import json
import time
from pathlib import Path
from typing import Dict, Any
from .._core import PHI, K5, K11, PRIME_131
from ..circular.srl_integration import srl_distance, srl_morton_encode


class PerformanceShell:
    """
    Performance Shell.

    Provides performance benchmarks:
    - SRL performance
    - Morton encoding performance
    - I-Logic performance
    """

    def __init__(self):
        """Initialize Performance shell."""
        self.dll_path = Path(__file__).parent.parent.parent / "native" / "hex_core"
        self.dlls_available = self.dll_path.exists() and any(self.dll_path.glob("*.dll"))

    def status(self, as_json: bool = False) -> Dict[str, Any]:
        """Get Performance system status."""
        dll_count = len(list(self.dll_path.glob("*.dll"))) if self.dll_path.exists() else 0

        result = {
            'system': 'Performance Shell',
            'version': '1.0.0',
            'dll_path': str(self.dll_path),
            'dlls_available': self.dlls_available,
            'dll_count': dll_count,
            'backend': 'C (native)' if self.dlls_available else 'Python (fallback)',
            'status': 'operational',
        }

        if as_json:
            return json.dumps(result, indent=2)
        return result

    def benchmark(self, as_json: bool = False) -> Dict[str, Any]:
        """Run performance benchmarks."""
        results = []
        iterations = 10000

        # SRL Benchmark
        start = time.perf_counter()
        for i in range(iterations):
            _ = srl_distance(i * 100)
        srl_time = (time.perf_counter() - start) * 1000
        srl_per_op = (srl_time * 1000) / iterations  # microseconds

        results.append({
            'test': 'SRL (sqrt)',
            'iterations': iterations,
            'total_ms': round(srl_time, 3),
            'per_op_us': round(srl_per_op, 3),
            'ops_per_sec': int(iterations / (srl_time / 1000)),
        })

        # Morton Benchmark
        start = time.perf_counter()
        for i in range(iterations):
            _ = srl_morton_encode(i % 48, (i * 7) % 48, (i * 13) % 48)
        morton_time = (time.perf_counter() - start) * 1000
        morton_per_op = (morton_time * 1000) / iterations

        results.append({
            'test': 'Morton encode',
            'iterations': iterations,
            'total_ms': round(morton_time, 3),
            'per_op_us': round(morton_per_op, 3),
            'ops_per_sec': int(iterations / (morton_time / 1000)),
        })

        # Basin Benchmark
        start = time.perf_counter()
        for i in range(iterations):
            _ = i % PRIME_131
        basin_time = (time.perf_counter() - start) * 1000
        basin_per_op = (basin_time * 1000) / iterations

        results.append({
            'test': 'Basin compute',
            'iterations': iterations,
            'total_ms': round(basin_time, 3),
            'per_op_us': round(basin_per_op, 3),
            'ops_per_sec': int(iterations / (basin_time / 1000)),
        })

        result = {
            'backend': 'C (native)' if self.dlls_available else 'Python (fallback)',
            'benchmarks': results,
            'summary': {
                'total_tests': len(results),
                'all_passed': True,
            },
        }

        if as_json:
            return json.dumps(result, indent=2)
        return result

    def test(self, as_json: bool = False) -> Dict[str, Any]:
        """Run performance tests."""
        tests = []

        # Test 1: SRL correctness
        srl_tests = [
            (0, 0), (1, 1), (4, 2), (9, 3), (100, 10), (1000000, 1000),
        ]
        for d, expected_t in srl_tests:
            actual_t = srl_distance(d)
            tests.append({
                'test': f'SRL({d})',
                'expected': expected_t,
                'actual': actual_t,
                'passed': actual_t == expected_t,
            })

        # Test 2: Morton round-trip
        # (Note: would need decode function for full round-trip)
        morton_tests = [
            (0, 0, 0), (1, 1, 1), (10, 20, 30), (47, 47, 47),
        ]
        for x, y, z in morton_tests:
            morton = srl_morton_encode(x, y, z)
            tests.append({
                'test': f'Morton({x},{y},{z})',
                'morton_code': morton,
                'passed': morton >= 0,
            })

        passed = sum(1 for t in tests if t['passed'])
        total = len(tests)

        result = {
            'tests': tests,
            'passed': passed,
            'total': total,
            'all_passed': passed == total,
        }

        if as_json:
            return json.dumps(result, indent=2)
        return result

    def run(self, command: str, *args, as_json: bool = False) -> Any:
        """Run a Performance shell command."""
        commands = {
            'status': lambda: self.status(as_json),
            'benchmark': lambda: self.benchmark(as_json),
            'test': lambda: self.test(as_json),
        }

        if command in commands:
            return commands[command]()
        else:
            return {'error': f'Unknown command: {command}', 'available': list(commands.keys())}
