"""
Test LLM Optimization Runner with Bracket Problem

Objective: Maximize displacement
Constraint: Stress must remain under safety factor of 4

Assuming Aluminum 6061-T6:
- Yield Strength: 276 MPa
- Safety Factor: 4
- Allowable Stress: 276 / 4 = 69 MPa

This test validates Phase 3.2 LLM-enhanced optimization with stress constraints.
"""

import sys
from pathlib import Path

sys.path.insert(0, str(Path(__file__).parent.parent))

from optimization_engine.future.llm_optimization_runner import LLMOptimizationRunner

# LLM workflow for bracket optimization
# Goal: Maximize displacement while keeping stress below safety factor
llm_workflow = {
    'engineering_features': [
        {
            'action': 'extract_displacement',
            'domain': 'result_extraction',
            'description': 'Extract displacement results from OP2 file',
            'params': {'result_type': 'displacement'}
        },
        {
            'action': 'extract_solid_stress',
            'domain': 'result_extraction',
            'description': 'Extract von Mises stress from solid elements',
            'params': {
                'result_type': 'stress',
                'element_type': 'ctetra'
            }
        }
    ],
    'inline_calculations': [
        {
            'action': 'calculate_safety_factor',
            'params': {
                'input': 'max_von_mises',
                'yield_strength': 276.0,  # MPa for Aluminum 6061-T6
                'operation': 'divide'
            },
            'code_hint': 'safety_factor = 276.0 / max_von_mises'
        },
        {
            'action': 'negate_displacement',
            'params': {
                'input': 'max_displacement',
                'operation': 'negate'
            },
            'code_hint': 'neg_displacement = -max_displacement'
        }
    ],
    'post_processing_hooks': [
        {
            'action': 'weighted_objective',
            'params': {
                'inputs': ['neg_displacement'],
                'weights': [1.0],
                'objective': 'minimize'
            },
            'description': 'Minimize negative displacement (maximize actual displacement)'
        }
    ],
    'optimization': {
        'algorithm': 'TPE',
        'direction': 'minimize',  # Minimize negative displacement = maximize displacement
        'design_variables': [
            {
                'parameter': 'wall_thickness',
                'min': 3.0,
                'max': 8.0,
                'units': 'mm'
            }
        ]
    }
}


def dummy_updater(design_vars):
    """Dummy model updater for testing."""
    print(f"  [Test] Would update model with: {design_vars}")


def dummy_runner():
    """Dummy simulation runner for testing."""
    print("  [Test] Would run NX simulation...")
    # Return path to existing test OP2
    return Path('tests/bracket_sim1-solution_1.op2')


if __name__ == '__main__':
    print("=" * 80)
    print("Test: LLM Runner with Bracket Problem")
    print("=" * 80)
    print()
    print("Problem Definition:")
    print("  Objective: MAXIMIZE displacement")
    print("  Constraint: Stress must remain below yield/SF")
    print("  Material: Aluminum 6061-T6 (Yield = 276 MPa)")
    print("  Safety Factor: 4.0")
    print("  Allowable Stress: 69 MPa")
    print()
    print("LLM Workflow:")
    print(f"  Engineering features: {len(llm_workflow['engineering_features'])}")
    print(f"  Inline calculations: {len(llm_workflow['inline_calculations'])}")
    print(f"  Post-processing hooks: {len(llm_workflow['post_processing_hooks'])}")
    print(f"  Design variables: {len(llm_workflow['optimization']['design_variables'])}")
    print()

    # Initialize LLM runner
    print("Initializing LLM optimization runner...")
    try:
        runner = LLMOptimizationRunner(
            llm_workflow=llm_workflow,
            model_updater=dummy_updater,
            simulation_runner=dummy_runner,
            study_name='bracket_maximize_disp_constrained'
        )

        print()
        print("=" * 80)
        print("Runner Initialized Successfully!")
        print("=" * 80)
        print(f"  Extractors generated: {len(runner.extractors)}")
        print(f"  Inline calculations: {len(runner.inline_code)}")
        hook_summary = runner.hook_manager.get_summary()
        print(f"  Hooks loaded: {hook_summary['enabled_hooks']}")
        print()

        print("To run full optimization, call runner.run_optimization(n_trials=50)")

    except Exception as e:
        print(f"\nERROR during initialization: {e}")
        import traceback
        traceback.print_exc()
        sys.exit(1)
