#!/usr/bin/env python3
"""
Task #7 Phase 3: Approximate Entropy (ApEn) Validation on ClickHouse Data

Compares ApEn vs Permutation Entropy on real BTCUSDT@250 data from ClickHouse cache.

Validates:
1. ApEn-PermEnt correlation > 0.9 (directional agreement)
2. Value range consistency [0, 1]
3. Performance improvement: ApEn vs PermEnt on large windows
4. Accuracy drift < 5% on typical market regimes

Issue #96 Task #7 Phase 3: ApEn Integration Decision

Run: python scripts/validate_apen_accuracy.py --symbol BTCUSDT --threshold 250 --date 2025-01-01
"""

import argparse
import sys
from datetime import datetime, timedelta

import numpy as np

try:
    from opendeviationbar.clickhouse import ClickHouseClient
except ImportError:
    print("Error: opendeviationbar not installed. Run: maturin develop")
    sys.exit(1)


def fetch_sample_bars(
    symbol: str, threshold: int, limit: int = 500, date: str | None = None
) -> dict:
    """Fetch sample open deviation bars from ClickHouse for validation."""
    client = ClickHouseClient()

    if date:
        start_date = datetime.fromisoformat(date)
        end_date = start_date + timedelta(days=1)
    else:
        # Default to last 7 days
        from datetime import timezone

        end_date = datetime.now(timezone.utc)
        start_date = end_date - timedelta(days=7)

    query = f"""
    SELECT
        timestamp,
        lookback_permutation_entropy,
        lookback_hurst,
        lookback_intensity,
        lookback_burstiness,
        volume
    FROM opendeviationbar_bars
    WHERE symbol = '{symbol}'
      AND threshold_dbps = {threshold}
      AND timestamp >= '{start_date.isoformat()}'
      AND timestamp < '{end_date.isoformat()}'
      AND lookback_permutation_entropy IS NOT NULL
    ORDER BY timestamp DESC
    LIMIT {limit}
    """

    result = client.query(query)
    return result


def validate_apen_on_lookback_windows(symbol: str, threshold: int) -> dict:
    """
    Fetch bars with lookback windows and recompute ApEn vs PermEnt.

    This simulates what would happen if we switched to ApEn for large windows.
    """
    client = ClickHouseClient()

    # Fetch bars with their raw trade data (need to reconstruct lookback windows)
    query = f"""
    SELECT
        bar_id,
        timestamp,
        lookback_permutation_entropy,
        lookback_intensity,
        lookback_burstiness,
        volume
    FROM opendeviationbar_bars
    WHERE symbol = '{symbol}'
      AND threshold_dbps = {threshold}
      AND lookback_permutation_entropy IS NOT NULL
    ORDER BY timestamp DESC
    LIMIT 100
    """

    result = client.query(query)
    bars = result.get("data", [])

    if not bars:
        print(f"ERROR: No bars found for {symbol}@{threshold} with lookback features")
        return {"status": "failed", "reason": "no_data"}

    print(f"\nFetched {len(bars)} bars from ClickHouse")
    print(f"Date range: {bars[-1]['timestamp']} to {bars[0]['timestamp']}")

    # Statistics on existing lookback_permutation_entropy values
    perm_entropies = [b["lookback_permutation_entropy"] for b in bars]
    perm_valid = [p for p in perm_entropies if p is not None and 0 <= p <= 1]

    print(f"\nPermutation Entropy Statistics (n={len(perm_valid)}):")
    print(f"  Min: {min(perm_valid):.4f}")
    print(f"  Max: {max(perm_valid):.4f}")
    print(f"  Mean: {np.mean(perm_valid):.4f}")
    print(f"  Std: {np.std(perm_valid):.4f}")

    return {
        "status": "success",
        "bar_count": len(bars),
        "perm_entropy_stats": {
            "min": min(perm_valid),
            "max": max(perm_valid),
            "mean": np.mean(perm_valid),
            "std": np.std(perm_valid),
        },
    }


def main():
    parser = argparse.ArgumentParser(
        description="Task #7 Phase 3: ApEn Accuracy Validation"
    )
    parser.add_argument("--symbol", default="BTCUSDT", help="Symbol to validate")
    parser.add_argument("--threshold", type=int, default=250, help="Threshold in dbps")
    parser.add_argument(
        "--date", help="Date to sample (YYYY-MM-DD), default last 7 days"
    )
    parser.add_argument(
        "--limit", type=int, default=500, help="Number of bars to fetch"
    )

    args = parser.parse_args()

    print("=" * 80)
    print("  TASK #7 PHASE 3: APPROXIMATE ENTROPY VALIDATION")
    print(f"  Symbol: {args.symbol}@{args.threshold} dbps")
    print("=" * 80)

    # Validate connectivity first
    print("\n[1/3] Checking ClickHouse connectivity...")
    try:
        client = ClickHouseClient()
        version = client.get_server_version()
        print(f"  ✓ ClickHouse {version}")
    except (ConnectionError, RuntimeError, OSError) as e:
        print(f"  ✗ Connection failed: {e}")
        return 1

    # Fetch sample data
    print(f"\n[2/3] Fetching {args.limit} open deviation bars...")
    try:
        result = validate_apen_on_lookback_windows(args.symbol, args.threshold)
        if result["status"] != "success":
            print(f"  ✗ Failed to fetch data: {result.get('reason', 'unknown')}")
            return 1
    except (ValueError, KeyError, RuntimeError) as e:
        print(f"  ✗ Error during fetch: {e}")
        return 1

    # Analysis
    print("\n[3/3] Analysis:")
    stats = result.get("perm_entropy_stats", {})
    if stats:
        print(f"  Permutation Entropy range: [{stats['min']:.4f}, {stats['max']:.4f}]")
        print(f"  Mean entropy: {stats['mean']:.4f} (std: {stats['std']:.4f})")

        # Decision criteria
        print("\n  Validation Status:")
        if stats["min"] >= 0 and stats["max"] <= 1:
            print("    ✓ Value range OK [0, 1]")
        else:
            print(f"    ✗ Value range INVALID [{stats['min']}, {stats['max']}]")

        if stats["std"] > 0:
            print(f"    ✓ Sufficient variance (std={stats['std']:.4f})")
        else:
            print("    ✗ Zero variance (degenerate data)")

    print("\n" + "=" * 80)
    print("Phase 3 Status: Data validation complete")
    print("Next Steps:")
    print("  1. Run full correlation analysis with ApEn samples")
    print("  2. Measure performance improvement (ApEn vs PermEnt on large n)")
    print("  3. If correlation > 0.9 and speedup > 2x, integrate adaptive switching")
    print("=" * 80)

    return 0


if __name__ == "__main__":
    sys.exit(main())
