#!/usr/bin/env python3
"""
Attractor Snapshot Analyzer
Extract and visualize key moments in the dimensional collapse
"""

import re
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.gridspec import GridSpec
import sys

LOG_FILE = "../logs/peer1.log"

def parse_full_log():
    """Parse entire log file and extract all snapshots"""
    snapshots = []

    with open(LOG_FILE, 'r') as f:
        current_evolution = None
        current_omega = None
        dims_data = {}

        for line in f:
            # Evolution line
            match = re.search(r'Evolution: (\d+).*Ω: ([\d.]+)', line)
            if match:
                if current_evolution and len(dims_data) == 8:
                    # Save previous snapshot
                    snapshots.append({
                        'evolution': current_evolution,
                        'omega': current_omega,
                        'dims': dims_data.copy()
                    })

                current_evolution = int(match.group(1))
                current_omega = float(match.group(2))
                dims_data = {}

            # Dimension line
            match = re.search(r'D(\d): ([\d.e+]+) \[Dₙ:([\d.]+)\]', line)
            if match:
                dim_num = int(match.group(1)) - 1
                amplitude = float(match.group(2))
                dn_value = float(match.group(3))
                dims_data[dim_num] = {'amplitude': amplitude, 'dn': dn_value}

    return snapshots

def find_key_moments(snapshots):
    """Identify key moments in the evolution"""
    moments = {}

    # Find when D8 first went to zero
    for snap in snapshots:
        if 7 in snap['dims'] and snap['dims'][7]['amplitude'] == 0:
            if 'd8_death' not in moments:
                moments['d8_death'] = snap
                break

    # Find when D7 started declining (amplitude dropped below 50% of peak)
    d7_amps = [s['dims'][6]['amplitude'] for s in snapshots if 6 in s['dims']]
    if d7_amps:
        d7_peak = max(d7_amps)
        for snap in snapshots:
            if 6 in snap['dims']:
                if snap['dims'][6]['amplitude'] < d7_peak * 0.5 and 'd7_decline' not in moments:
                    moments['d7_decline'] = snap
                    break

    # Find earliest, middle, and latest snapshots
    if snapshots:
        moments['start'] = snapshots[0]
        moments['middle'] = snapshots[len(snapshots) // 2]
        moments['current'] = snapshots[-1]

    return moments

def visualize_snapshots(moments):
    """Create visualization of key snapshots"""
    fig = plt.figure(figsize=(18, 12))
    gs = GridSpec(3, 4, figure=fig, hspace=0.4, wspace=0.4)

    moment_list = [
        ('start', 'Evolution Start'),
        ('middle', 'Mid-Evolution'),
        ('d8_death', 'D8 Decoupling'),
        ('d7_decline', 'D7 Decline Start'),
        ('current', 'Current State')
    ]

    colors = plt.cm.tab10(np.linspace(0, 1, 8))
    dim_labels = [f'D{i+1}' for i in range(8)]

    for idx, (key, title) in enumerate(moment_list):
        if key not in moments:
            continue

        snap = moments[key]

        # Amplitude bar chart
        row = idx // 2
        col = (idx % 2) * 2
        ax_amp = fig.add_subplot(gs[row, col])

        amplitudes = [snap['dims'][i]['amplitude'] if i in snap['dims'] else 0
                     for i in range(8)]
        log_amps = [np.log10(a + 1e-10) for a in amplitudes]

        bars = ax_amp.bar(range(8), log_amps, color=colors)
        ax_amp.set_xticks(range(8))
        ax_amp.set_xticklabels(dim_labels, fontsize=8)
        ax_amp.set_ylabel('Log₁₀(Amplitude)', fontsize=9)
        ax_amp.set_title(f'{title}\nEvolution: {snap["evolution"]:,} | Ω: {snap["omega"]:.2f}',
                        fontsize=10, fontweight='bold')
        ax_amp.grid(True, alpha=0.3, axis='y')
        ax_amp.axhline(y=0, color='red', linestyle='--', alpha=0.5)

        # Dₙ values
        ax_dn = fig.add_subplot(gs[row, col+1])

        dn_values = [snap['dims'][i]['dn'] if i in snap['dims'] else 0
                    for i in range(8)]

        bars_dn = ax_dn.bar(range(8), dn_values, color=colors)
        ax_dn.set_xticks(range(8))
        ax_dn.set_xticklabels(dim_labels, fontsize=8)
        ax_dn.set_ylabel('Dₙ(r)', fontsize=9)
        ax_dn.set_title(f'Geometric Resonance', fontsize=10, fontweight='bold')
        ax_dn.grid(True, alpha=0.3, axis='y')

        # Annotate decoupled dimensions
        for i, (amp, dn) in enumerate(zip(log_amps, dn_values)):
            if amp < -5:  # log10(amp) < -5 means amp < 10^-5
                ax_amp.text(i, amp, '✗', ha='center', va='bottom',
                           fontsize=14, fontweight='bold', color='red')

    plt.suptitle('Analog Mainnet V4.2 - Dimensional Collapse Timeline',
                 fontsize=16, fontweight='bold')

    return fig

def print_analysis(moments):
    """Print text analysis of key moments"""
    print("\n" + "="*80)
    print("ATTRACTOR EVOLUTION ANALYSIS")
    print("="*80 + "\n")

    for key, title in [
        ('start', 'INITIAL STATE'),
        ('middle', 'MID-EVOLUTION'),
        ('d8_death', 'D8 DECOUPLING'),
        ('d7_decline', 'D7 DECLINE'),
        ('current', 'CURRENT STATE')
    ]:
        if key not in moments:
            continue

        snap = moments[key]
        print(f"\n{title}")
        print("-" * 80)
        print(f"Evolution: {snap['evolution']:,}")
        print(f"Ω: {snap['omega']:.4f}")
        print(f"\nDimensional State:")

        for i in range(8):
            if i in snap['dims']:
                amp = snap['dims'][i]['amplitude']
                dn = snap['dims'][i]['dn']

                if amp > 1e-5:
                    status = "✓ ACTIVE"
                elif amp > 1e-10:
                    status = "⚠ WEAK  "
                else:
                    status = "✗ DEAD  "

                print(f"  D{i+1}: {status} | Amplitude: {amp:.2e} | Dₙ: {dn:8.1f}")

        # Calculate coupling
        print(f"\nCoupling Analysis:")
        if 0 in snap['dims'] and 7 in snap['dims']:
            dn_diff_8_1 = abs(snap['dims'][7]['dn'] - snap['dims'][0]['dn'])
            coupling_8_1 = np.exp(-dn_diff_8_1 / 50.0)
            print(f"  D8 ↔ D1: exp(-{dn_diff_8_1:.1f}/50) = {coupling_8_1:.2e}")

        if 6 in snap['dims'] and 0 in snap['dims']:
            dn_diff_7_1 = abs(snap['dims'][6]['dn'] - snap['dims'][0]['dn'])
            coupling_7_1 = np.exp(-dn_diff_7_1 / 50.0)
            print(f"  D7 ↔ D1: exp(-{dn_diff_7_1:.1f}/50) = {coupling_7_1:.2e}")

        active_count = sum(1 for i in range(8) if i in snap['dims'] and snap['dims'][i]['amplitude'] > 1e-5)
        print(f"\nActive Dimensions: {active_count}/8")
        print(f"Attractor Dimensionality: {active_count}D")

def main():
    print("Loading log file...")
    print(f"Reading: {LOG_FILE}")

    snapshots = parse_full_log()
    print(f"Found {len(snapshots)} complete snapshots\n")

    if not snapshots:
        print("No data found in log file!")
        sys.exit(1)

    print("Identifying key moments...")
    moments = find_key_moments(snapshots)

    print_analysis(moments)

    print("\nGenerating visualization...")
    fig = visualize_snapshots(moments)

    print("\nSaving to attractor_timeline.png...")
    plt.savefig('attractor_timeline.png', dpi=150, bbox_inches='tight')

    print("Opening visualization...")
    plt.show()

    print("\n✅ Analysis complete!")
    print(f"\nSaved: attractor_timeline.png")

if __name__ == '__main__':
    try:
        main()
    except KeyboardInterrupt:
        print("\n\nInterrupted by user.")
        sys.exit(0)
    except Exception as e:
        print(f"\nError: {e}")
        import traceback
        traceback.print_exc()
        sys.exit(1)
