#!/usr/bin/env python3
"""
Test script to verify both Flash Attention v2 and v3 can perform inference
"""

import torch


def test_fa2_fa3():
    """Test both FA2 and FA3 inference capabilities"""

    print('Testing FA2 and FA3 availability...')
    print('=' * 60)

    # Test FA2
    fa2_available = False
    try:
        import flash_attn
        print('✓ FA2 (flash_attn) imported successfully')
        print(f'  Version: {flash_attn.__version__}')
        print(f'  Location: {flash_attn.__file__}')

        # Try to import the main function
        from flash_attn import flash_attn_func
        print('  ✓ flash_attn_func available')
        fa2_available = True
    except Exception as e:
        print(f'✗ FA2 import failed: {e}')

    print()

    # Test FA3
    fa3_available = False
    try:
        import flash_attn_interface
        print('✓ FA3 (flash_attn_interface) imported successfully')
        print(f'  Location: {flash_attn_interface.__file__}')

        # Check what functions are available
        funcs = [attr for attr in dir(flash_attn_interface) if not attr.startswith('_')]
        print(f'  Available functions: {funcs[:5]}...')  # Show first 5
        fa3_available = True
    except Exception as e:
        print(f'✗ FA3 import failed: {e}')

    print()
    print('=' * 60)
    print('Testing actual inference...')
    print('=' * 60)

    # Test parameters
    batch_size = 2
    seqlen = 128
    nheads = 8
    headdim = 64

    # Create test tensors
    q = torch.randn(batch_size, seqlen, nheads, headdim, device='cuda', dtype=torch.float16)
    k = torch.randn(batch_size, seqlen, nheads, headdim, device='cuda', dtype=torch.float16)
    v = torch.randn(batch_size, seqlen, nheads, headdim, device='cuda', dtype=torch.float16)

    # Test FA2
    if fa2_available:
        try:
            from flash_attn import flash_attn_func

            out_fa2 = flash_attn_func(q, k, v)
            print(f'✓ FA2 inference working: output shape {out_fa2.shape}')
        except Exception as e:
            print(f'✗ FA2 inference failed: {e}')
    else:
        print('⚠ FA2 not available, skipping inference test')

    # Test FA3
    if fa3_available:
        try:
            import flash_attn_interface

            # FA3 typically has the same interface
            if hasattr(flash_attn_interface, 'flash_attn_func'):
                out_fa3 = flash_attn_interface.flash_attn_func(q, k, v)
                print(f'✓ FA3 inference working: output shape {out_fa3.shape}')
            else:
                print('⚠ FA3 available but API differs from FA2')
                print(f'  Available in flash_attn_interface: {[x for x in dir(flash_attn_interface) if "flash" in x.lower()]}')
        except Exception as e:
            print(f'✗ FA3 inference test failed: {e}')
    else:
        print('⚠ FA3 not available, skipping inference test')

    print('=' * 60)


if __name__ == '__main__':
    test_fa2_fa3()
