-- ================================================================================================
-- Migration Test Suite: Risk Events (Migrations 002-003)
-- PostgreSQL 16.10 + TimescaleDB 2.22.1
-- Tests risk events, audit events, constraint violations, and partitioning
-- ================================================================================================

-- Setup test transaction (rollback at end to avoid polluting database)
BEGIN;

-- ================================================================================================
-- TEST 1: Valid Risk Event Insertion
-- Should succeed with all required fields
-- ================================================================================================
DO $$
DECLARE
    v_test_id UUID := uuid_generate_v4();
    v_correlation_id UUID := uuid_generate_v4();
    v_current_ns BIGINT := EXTRACT(EPOCH FROM NOW())::BIGINT * 1000000000;
BEGIN
    INSERT INTO risk_events (
        id,
        correlation_id,
        event_timestamp,
        detected_timestamp,
        event_type,
        severity,
        symbol,
        account_id,
        event_data,
        event_hash,
        node_id,
        process_id
    ) VALUES (
        v_test_id,
        v_correlation_id,
        v_current_ns,
        v_current_ns + 1000,
        'var_breach',
        'high',
        'AAPL',
        'ACC001',
        '{"var_limit": 100000, "current_var": 125000, "breach_amount": 25000}'::jsonb,
        encode(sha256('risk_test'::bytea), 'hex'),
        'risk-node-01',
        12345
    );

    RAISE NOTICE 'TEST 1 PASS: Valid risk event inserted successfully';
EXCEPTION
    WHEN OTHERS THEN
        RAISE EXCEPTION 'TEST 1 FAIL: Valid insertion failed - %', SQLERRM;
END $$;

-- ================================================================================================
-- TEST 2: Risk Severity Enum Validation
-- Should fail with invalid severity level
-- ================================================================================================
DO $$
BEGIN
    INSERT INTO risk_events (
        correlation_id,
        event_timestamp,
        detected_timestamp,
        event_type,
        severity,
        symbol,
        account_id,
        event_data,
        event_hash,
        node_id,
        process_id
    ) VALUES (
        uuid_generate_v4(),
        1000000000,
        1000000000,
        'var_breach',
        'ultra_critical', -- INVALID: not in enum
        'AAPL',
        'ACC001',
        '{}'::jsonb,
        encode(sha256('test'::bytea), 'hex'),
        'risk-node-01',
        12345
    );

    RAISE EXCEPTION 'TEST 2 FAIL: Should have rejected invalid severity';
EXCEPTION
    WHEN invalid_text_representation THEN
        RAISE NOTICE 'TEST 2 PASS: Correctly rejected invalid risk_severity enum value';
    WHEN OTHERS THEN
        RAISE EXCEPTION 'TEST 2 FAIL: Wrong error type - %', SQLERRM;
END $$;

-- ================================================================================================
-- TEST 3: Risk Event Type Validation
-- Verify all valid risk event types
-- ================================================================================================
DO $$
DECLARE
    v_valid_types TEXT[] := ARRAY[
        'var_breach', 'exposure_limit_breach', 'position_limit_breach',
        'concentration_risk', 'leverage_excess', 'margin_call',
        'drawdown_limit', 'volatility_spike', 'correlation_breakdown',
        'liquidity_shortage', 'stress_test_failure', 'compliance_violation',
        'model_validation_error', 'circuit_breaker_triggered', 'emergency_shutdown',
        'risk_limit_update', 'model_recalibration', 'backtest_failure'
    ];
    v_type TEXT;
    v_current_ns BIGINT := EXTRACT(EPOCH FROM NOW())::BIGINT * 1000000000;
BEGIN
    FOREACH v_type IN ARRAY v_valid_types
    LOOP
        -- Insert test event for each type
        INSERT INTO risk_events (
            correlation_id,
            event_timestamp,
            detected_timestamp,
            event_type,
            severity,
            symbol,
            account_id,
            event_data,
            event_hash,
            node_id,
            process_id
        ) VALUES (
            uuid_generate_v4(),
            v_current_ns,
            v_current_ns,
            v_type::risk_event_type,
            'medium',
            'TEST',
            'ACC001',
            format('{"type": "%s"}', v_type)::jsonb,
            encode(sha256(v_type::bytea), 'hex'),
            'risk-node-01',
            12345
        );
    END LOOP;

    RAISE NOTICE 'TEST 3 PASS: All % risk_event_type enum values are valid', array_length(v_valid_types, 1);
EXCEPTION
    WHEN OTHERS THEN
        RAISE EXCEPTION 'TEST 3 FAIL: Invalid risk_event_type - %', SQLERRM;
END $$;

-- ================================================================================================
-- TEST 4: Risk Metric Type Validation
-- Verify all valid risk metric types
-- ================================================================================================
DO $$
DECLARE
    v_valid_metrics TEXT[] := ARRAY[
        'var_1d', 'var_10d', 'cvar_1d', 'cvar_10d',
        'exposure_gross', 'exposure_net', 'leverage_ratio',
        'concentration_single', 'concentration_sector', 'beta_portfolio',
        'sharpe_ratio', 'max_drawdown', 'volatility_realized', 'volatility_implied',
        'correlation_matrix', 'margin_excess', 'margin_requirement', 'liquidity_score'
    ];
    v_metric TEXT;
BEGIN
    FOREACH v_metric IN ARRAY v_valid_metrics
    LOOP
        PERFORM v_metric::risk_metric_type;
    END LOOP;

    RAISE NOTICE 'TEST 4 PASS: All % risk_metric_type enum values are valid', array_length(v_valid_metrics, 1);
EXCEPTION
    WHEN OTHERS THEN
        RAISE EXCEPTION 'TEST 4 FAIL: Invalid risk_metric_type - %', SQLERRM;
END $$;

-- ================================================================================================
-- TEST 5: Valid Audit Event Insertion (Migration 003)
-- Should succeed with all required fields
-- ================================================================================================
DO $$
DECLARE
    v_test_id UUID := uuid_generate_v4();
    v_correlation_id UUID := uuid_generate_v4();
    v_current_ns BIGINT := EXTRACT(EPOCH FROM NOW())::BIGINT * 1000000000;
BEGIN
    INSERT INTO audit_events (
        id,
        correlation_id,
        event_timestamp,
        event_type,
        severity,
        component,
        user_id,
        event_data,
        event_hash,
        node_id,
        process_id
    ) VALUES (
        v_test_id,
        v_correlation_id,
        v_current_ns,
        'order_created',
        'info',
        'trading_engine',
        'user123',
        '{"order_id": "ORD001", "action": "create"}'::jsonb,
        encode(sha256('audit_test'::bytea), 'hex'),
        'audit-node-01',
        12345
    );

    RAISE NOTICE 'TEST 5 PASS: Valid audit event inserted successfully';
EXCEPTION
    WHEN OTHERS THEN
        RAISE EXCEPTION 'TEST 5 FAIL: Valid audit insertion failed - %', SQLERRM;
END $$;

-- ================================================================================================
-- TEST 6: Audit Event Type Validation
-- Verify subset of audit event types
-- ================================================================================================
DO $$
DECLARE
    v_valid_types TEXT[] := ARRAY[
        'order_created', 'order_modified', 'order_cancelled', 'order_executed',
        'model_prediction', 'model_training_started', 'model_deployed',
        'system_startup', 'authentication_success', 'compliance_validation_completed'
    ];
    v_type TEXT;
    v_current_ns BIGINT := EXTRACT(EPOCH FROM NOW())::BIGINT * 1000000000;
BEGIN
    FOREACH v_type IN ARRAY v_valid_types
    LOOP
        INSERT INTO audit_events (
            correlation_id,
            event_timestamp,
            event_type,
            severity,
            component,
            user_id,
            event_data,
            event_hash,
            node_id,
            process_id
        ) VALUES (
            uuid_generate_v4(),
            v_current_ns,
            v_type::audit_event_type,
            'info',
            'trading_engine',
            'testuser',
            format('{"type": "%s"}', v_type)::jsonb,
            encode(sha256(v_type::bytea), 'hex'),
            'audit-node-01',
            12345
        );
    END LOOP;

    RAISE NOTICE 'TEST 6 PASS: Sample audit_event_type enum values validated (% types)', array_length(v_valid_types, 1);
EXCEPTION
    WHEN OTHERS THEN
        RAISE EXCEPTION 'TEST 6 FAIL: Invalid audit_event_type - %', SQLERRM;
END $$;

-- ================================================================================================
-- TEST 7: Audit Severity Levels
-- Verify audit severity hierarchy
-- ================================================================================================
DO $$
DECLARE
    v_valid_severities TEXT[] := ARRAY[
        'trace', 'debug', 'info', 'notice', 'warning',
        'error', 'critical', 'alert', 'emergency'
    ];
    v_severity TEXT;
BEGIN
    FOREACH v_severity IN ARRAY v_valid_severities
    LOOP
        PERFORM v_severity::audit_severity;
    END LOOP;

    RAISE NOTICE 'TEST 7 PASS: All % audit_severity levels are valid', array_length(v_valid_severities, 1);
EXCEPTION
    WHEN OTHERS THEN
        RAISE EXCEPTION 'TEST 7 FAIL: Invalid audit_severity - %', SQLERRM;
END $$;

-- ================================================================================================
-- TEST 8: System Component Enum Validation
-- Verify all system components
-- ================================================================================================
DO $$
DECLARE
    v_valid_components TEXT[] := ARRAY[
        'trading_engine', 'risk_management', 'market_data', 'order_management',
        'portfolio_management', 'ml_engine', 'execution_engine', 'compliance_engine',
        'authentication', 'configuration', 'database', 'api_gateway',
        'user_interface', 'reporting', 'monitoring', 'backup_system'
    ];
    v_component TEXT;
BEGIN
    FOREACH v_component IN ARRAY v_valid_components
    LOOP
        PERFORM v_component::system_component;
    END LOOP;

    RAISE NOTICE 'TEST 8 PASS: All % system_component enum values are valid', array_length(v_valid_components, 1);
EXCEPTION
    WHEN OTHERS THEN
        RAISE EXCEPTION 'TEST 8 FAIL: Invalid system_component - %', SQLERRM;
END $$;

-- ================================================================================================
-- TEST 9: Risk Event Lifecycle with Acknowledgment and Resolution
-- Test complete risk event workflow
-- ================================================================================================
DO $$
DECLARE
    v_event_id UUID := uuid_generate_v4();
    v_correlation_id UUID := uuid_generate_v4();
    v_current_ns BIGINT := EXTRACT(EPOCH FROM NOW())::BIGINT * 1000000000;
    v_acknowledged_ns BIGINT;
    v_resolved_ns BIGINT;
BEGIN
    -- Create risk event
    INSERT INTO risk_events (
        id,
        correlation_id,
        event_timestamp,
        detected_timestamp,
        event_type,
        severity,
        symbol,
        account_id,
        event_data,
        event_hash,
        node_id,
        process_id
    ) VALUES (
        v_event_id,
        v_correlation_id,
        v_current_ns,
        v_current_ns + 1000,
        'position_limit_breach',
        'high',
        'TSLA',
        'ACC001',
        '{"position": 10000, "limit": 8000, "breach": 2000}'::jsonb,
        encode(sha256('lifecycle_test'::bytea), 'hex'),
        'risk-node-01',
        12345
    );

    -- Simulate acknowledgment
    v_acknowledged_ns := v_current_ns + 500000000; -- 500ms later
    UPDATE risk_events
    SET acknowledged_timestamp = v_acknowledged_ns,
        acknowledged_by = 'risk_manager_001'
    WHERE id = v_event_id;

    -- Simulate resolution
    v_resolved_ns := v_current_ns + 2000000000; -- 2s later
    UPDATE risk_events
    SET resolved_timestamp = v_resolved_ns,
        resolved_by = 'risk_manager_001',
        resolution_notes = 'Position reduced to comply with limit'
    WHERE id = v_event_id;

    -- Verify lifecycle
    IF EXISTS (
        SELECT 1 FROM risk_events
        WHERE id = v_event_id
          AND acknowledged_timestamp IS NOT NULL
          AND resolved_timestamp IS NOT NULL
          AND acknowledged_timestamp > detected_timestamp
          AND resolved_timestamp > acknowledged_timestamp
    ) THEN
        RAISE NOTICE 'TEST 9 PASS: Risk event lifecycle (detect -> acknowledge -> resolve) validated';
    ELSE
        RAISE EXCEPTION 'TEST 9 FAIL: Risk event lifecycle validation failed';
    END IF;
END $$;

-- ================================================================================================
-- TEST 10: Audit Retention and Immutability
-- Verify audit events are immutable (UPDATE should work but INSERT/DELETE are standard)
-- ================================================================================================
DO $$
DECLARE
    v_audit_id UUID := uuid_generate_v4();
    v_current_ns BIGINT := EXTRACT(EPOCH FROM NOW())::BIGINT * 1000000000;
    v_original_hash VARCHAR(64);
    v_updated_hash VARCHAR(64);
BEGIN
    -- Insert audit event
    INSERT INTO audit_events (
        id,
        correlation_id,
        event_timestamp,
        event_type,
        severity,
        component,
        user_id,
        event_data,
        event_hash,
        node_id,
        process_id
    ) VALUES (
        v_audit_id,
        uuid_generate_v4(),
        v_current_ns,
        'permission_granted',
        'notice',
        'authentication',
        'admin_user',
        '{"permission": "read:trades", "granted_to": "analyst_001"}'::jsonb,
        encode(sha256('retention_test'::bytea), 'hex'),
        'auth-node-01',
        12345
    )
    RETURNING event_hash INTO v_original_hash;

    -- Verify event was inserted
    IF EXISTS (SELECT 1 FROM audit_events WHERE id = v_audit_id) THEN
        RAISE NOTICE 'TEST 10 PASS: Audit event inserted and persisted';
        RAISE NOTICE 'TEST 10 INFO: Original event_hash: %', v_original_hash;
    ELSE
        RAISE EXCEPTION 'TEST 10 FAIL: Audit event not found after insertion';
    END IF;

    -- Note: In production, audit_events should be append-only with triggers preventing UPDATE/DELETE
    -- This test validates the schema allows the data to be stored correctly
END $$;

-- ================================================================================================
-- TEST 11: Risk Metrics JSONB Query Performance
-- Verify JSONB query capabilities for risk metrics
-- ================================================================================================
DO $$
DECLARE
    v_test_id UUID := uuid_generate_v4();
    v_current_ns BIGINT := EXTRACT(EPOCH FROM NOW())::BIGINT * 1000000000;
    v_metrics JSONB;
BEGIN
    -- Insert risk event with complex metrics
    INSERT INTO risk_events (
        id,
        correlation_id,
        event_timestamp,
        detected_timestamp,
        event_type,
        severity,
        risk_metric,
        symbol,
        account_id,
        event_data,
        event_hash,
        node_id,
        process_id
    ) VALUES (
        v_test_id,
        uuid_generate_v4(),
        v_current_ns,
        v_current_ns,
        'volatility_spike',
        'high',
        'volatility_realized',
        'NVDA',
        'ACC002',
        '{"metric": "volatility_realized", "value": 0.75, "threshold": 0.50, "window": "30d", "breach_severity": 1.5}'::jsonb,
        encode(sha256('metrics_test'::bytea), 'hex'),
        'risk-node-01',
        12345
    );

    -- Query using JSONB operators
    SELECT event_data INTO v_metrics
    FROM risk_events
    WHERE id = v_test_id
      AND event_data->>'metric' = 'volatility_realized'
      AND (event_data->>'value')::numeric > 0.5;

    IF v_metrics IS NOT NULL THEN
        RAISE NOTICE 'TEST 11 PASS: JSONB metrics query successful, value: %', v_metrics->>'value';
    ELSE
        RAISE EXCEPTION 'TEST 11 FAIL: JSONB metrics query failed';
    END IF;
END $$;

-- ================================================================================================
-- TEST 12: Audit Event Correlation
-- Verify multiple audit events can be linked via correlation_id
-- ================================================================================================
DO $$
DECLARE
    v_correlation_id UUID := uuid_generate_v4();
    v_current_ns BIGINT := EXTRACT(EPOCH FROM NOW())::BIGINT * 1000000000;
    v_event_count INTEGER;
BEGIN
    -- Insert multiple related audit events
    INSERT INTO audit_events (
        correlation_id, event_timestamp, event_type, severity, component, user_id,
        event_data, event_hash, node_id, process_id
    ) VALUES
    (v_correlation_id, v_current_ns, 'order_created', 'info', 'trading_engine', 'trader_001',
     '{"step": 1, "action": "create"}'::jsonb, encode(sha256('1'::bytea), 'hex'), 'node-01', 12345),
    (v_correlation_id, v_current_ns + 100000, 'order_modified', 'info', 'trading_engine', 'trader_001',
     '{"step": 2, "action": "modify"}'::jsonb, encode(sha256('2'::bytea), 'hex'), 'node-01', 12345),
    (v_correlation_id, v_current_ns + 200000, 'order_executed', 'info', 'execution_engine', 'system',
     '{"step": 3, "action": "execute"}'::jsonb, encode(sha256('3'::bytea), 'hex'), 'node-01', 12345);

    -- Verify correlation
    SELECT COUNT(*) INTO v_event_count
    FROM audit_events
    WHERE correlation_id = v_correlation_id;

    IF v_event_count = 3 THEN
        RAISE NOTICE 'TEST 12 PASS: Audit event correlation verified (% linked events)', v_event_count;
    ELSE
        RAISE EXCEPTION 'TEST 12 FAIL: Expected 3 correlated events, found %', v_event_count;
    END IF;
END $$;

-- ================================================================================================
-- Cleanup: Rollback all test data
-- ================================================================================================
ROLLBACK;

-- Test Summary
SELECT 'Risk & Audit Events Test Suite Completed - Review NOTICE messages above for results' AS test_summary;
