-- 015_adaptive_strategy_config.sql
-- Adaptive Strategy Configuration with Hot-Reload Support
-- Implements database-backed configuration for adaptive-strategy crate
-- Replaces 50+ hardcoded Default implementations with PostgreSQL-based config

-- Enable required extensions
CREATE EXTENSION IF NOT EXISTS "uuid-ossp";

-- ============================================================================
-- ENUMERATIONS
-- ============================================================================

-- Position sizing methods
CREATE TYPE position_sizing_method AS ENUM (
    'KELLY',
    'FIXED_FRACTIONAL',
    'FIXED_FRACTION',
    'PPO',
    'EQUAL_WEIGHT',
    'RISK_PARITY',
    'VOLATILITY_TARGET',
    'CUSTOM'
);

-- Regime detection methods
CREATE TYPE regime_detection_method AS ENUM (
    'HMM',
    'MARKOV_SWITCHING',
    'THRESHOLD',
    'ML_CLASSIFICATION',
    'GMM',
    'ML_CLASSIFIER'
);

-- Execution algorithms
CREATE TYPE execution_algorithm AS ENUM (
    'TWAP',
    'VWAP',
    'IS',
    'IMPLEMENTATION_SHORTFALL',
    'ARRIVAL_PRICE',
    'POV'
);

-- ============================================================================
-- MAIN CONFIGURATION TABLE
-- ============================================================================

-- Adaptive strategy configuration table
-- Stores all parameters previously hardcoded in adaptive-strategy/src/config.rs
CREATE TABLE adaptive_strategy_config (
    id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
    strategy_id VARCHAR(100) UNIQUE NOT NULL,
    name VARCHAR(255) NOT NULL,
    description TEXT,

    -- ========================================================================
    -- GENERAL CONFIGURATION (GeneralConfig)
    -- ========================================================================
    execution_interval_ms INTEGER NOT NULL DEFAULT 100,
    error_backoff_duration_secs INTEGER NOT NULL DEFAULT 1,
    max_concurrent_operations INTEGER NOT NULL DEFAULT 10,
    strategy_timeout_secs INTEGER NOT NULL DEFAULT 30,

    -- ========================================================================
    -- ENSEMBLE CONFIGURATION (EnsembleConfig)
    -- ========================================================================
    max_parallel_models INTEGER NOT NULL DEFAULT 4,
    rebalancing_interval_secs INTEGER NOT NULL DEFAULT 300,
    min_model_weight DOUBLE PRECISION NOT NULL DEFAULT 0.01,
    max_model_weight DOUBLE PRECISION NOT NULL DEFAULT 0.5,

    -- ========================================================================
    -- RISK CONFIGURATION (RiskConfig)
    -- ========================================================================
    max_position_size DOUBLE PRECISION NOT NULL DEFAULT 0.1,
    max_leverage DOUBLE PRECISION NOT NULL DEFAULT 2.0,
    stop_loss_pct DOUBLE PRECISION NOT NULL DEFAULT 0.02,
    position_sizing_method position_sizing_method NOT NULL DEFAULT 'KELLY',
    max_portfolio_var DOUBLE PRECISION NOT NULL DEFAULT 0.02,
    max_drawdown_threshold DOUBLE PRECISION NOT NULL DEFAULT 0.05,
    kelly_fraction DOUBLE PRECISION NOT NULL DEFAULT 0.1,

    -- ========================================================================
    -- MICROSTRUCTURE CONFIGURATION (MicrostructureConfig)
    -- ========================================================================
    book_depth INTEGER NOT NULL DEFAULT 10,
    vpin_window INTEGER NOT NULL DEFAULT 50,
    trade_classification_threshold DOUBLE PRECISION NOT NULL DEFAULT 0.5,
    trade_size_buckets DOUBLE PRECISION[] NOT NULL DEFAULT ARRAY[10.0, 100.0, 1000.0, 10000.0],
    microstructure_features TEXT[] NOT NULL DEFAULT ARRAY['vpin', 'order_flow', 'bid_ask_spread'],

    -- ========================================================================
    -- REGIME CONFIGURATION (RegimeConfig)
    -- ========================================================================
    regime_detection_method regime_detection_method NOT NULL DEFAULT 'HMM',
    regime_lookback_window INTEGER NOT NULL DEFAULT 252,
    regime_transition_threshold DOUBLE PRECISION NOT NULL DEFAULT 0.7,
    regime_features TEXT[] NOT NULL DEFAULT ARRAY['volatility', 'momentum', 'volume'],

    -- ========================================================================
    -- EXECUTION CONFIGURATION (ExecutionConfig)
    -- ========================================================================
    execution_algorithm execution_algorithm NOT NULL DEFAULT 'TWAP',
    max_order_size DOUBLE PRECISION NOT NULL DEFAULT 10000.0,
    min_order_size DOUBLE PRECISION NOT NULL DEFAULT 100.0,
    order_timeout_secs INTEGER NOT NULL DEFAULT 30,
    max_slippage_bps DOUBLE PRECISION NOT NULL DEFAULT 10.0,
    smart_routing_enabled BOOLEAN NOT NULL DEFAULT true,
    dark_pool_preference DOUBLE PRECISION NOT NULL DEFAULT 0.3,

    -- ========================================================================
    -- AUDIT TRAIL
    -- ========================================================================
    active BOOLEAN NOT NULL DEFAULT true,
    version INTEGER NOT NULL DEFAULT 1,
    created_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT NOW(),
    updated_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT NOW(),
    created_by UUID,
    updated_by UUID,
    metadata JSONB DEFAULT '{}',

    -- Constraints
    CONSTRAINT valid_position_size CHECK (max_position_size > 0 AND max_position_size <= 1.0),
    CONSTRAINT valid_leverage CHECK (max_leverage > 0),
    CONSTRAINT valid_stop_loss CHECK (stop_loss_pct > 0 AND stop_loss_pct <= 1.0),
    CONSTRAINT valid_var CHECK (max_portfolio_var > 0),
    CONSTRAINT valid_drawdown CHECK (max_drawdown_threshold > 0 AND max_drawdown_threshold <= 1.0),
    CONSTRAINT valid_kelly CHECK (kelly_fraction > 0 AND kelly_fraction <= 1.0),
    CONSTRAINT valid_model_weights CHECK (min_model_weight >= 0 AND max_model_weight <= 1.0 AND min_model_weight <= max_model_weight),
    CONSTRAINT valid_dark_pool CHECK (dark_pool_preference >= 0 AND dark_pool_preference <= 1.0)
);

-- ============================================================================
-- MODEL CONFIGURATIONS
-- ============================================================================

-- Individual model configurations within an ensemble
CREATE TABLE adaptive_strategy_models (
    id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
    strategy_config_id UUID NOT NULL REFERENCES adaptive_strategy_config(id) ON DELETE CASCADE,

    model_id VARCHAR(100) NOT NULL,
    model_name VARCHAR(255) NOT NULL,
    model_type VARCHAR(50) NOT NULL, -- 'mamba2', 'tlob', 'dqn', 'ppo', 'lstm', etc.

    -- Model parameters as flexible JSONB
    -- Examples:
    -- MAMBA-2: {"hidden_dim": 256, "state_size": 16, "num_layers": 4}
    -- TLOB: {"num_heads": 8, "num_layers": 6, "dropout": 0.1}
    -- DQN: {"learning_rate": 0.001, "gamma": 0.99, "epsilon": 0.1}
    parameters JSONB NOT NULL DEFAULT '{}',

    initial_weight DOUBLE PRECISION NOT NULL DEFAULT 0.25,
    enabled BOOLEAN NOT NULL DEFAULT true,

    -- Ordering within ensemble
    display_order INTEGER NOT NULL DEFAULT 0,

    created_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT NOW(),
    updated_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT NOW(),

    CONSTRAINT unique_model_per_strategy UNIQUE(strategy_config_id, model_id),
    CONSTRAINT valid_initial_weight CHECK (initial_weight >= 0 AND initial_weight <= 1.0)
);

-- ============================================================================
-- FEATURE CONFIGURATIONS
-- ============================================================================

-- Feature extraction configurations for models
CREATE TABLE adaptive_strategy_features (
    id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
    strategy_config_id UUID NOT NULL REFERENCES adaptive_strategy_config(id) ON DELETE CASCADE,

    feature_name VARCHAR(100) NOT NULL,
    feature_type VARCHAR(50) NOT NULL, -- 'price', 'volume', 'orderbook', 'technical', 'regime'

    -- Feature-specific parameters as JSONB
    -- Examples:
    -- Moving average: {"window": 20, "type": "exponential"}
    -- Order book imbalance: {"levels": 5, "normalization": "minmax"}
    -- Volatility: {"window": 50, "method": "parkinson"}
    parameters JSONB NOT NULL DEFAULT '{}',

    enabled BOOLEAN NOT NULL DEFAULT true,
    required BOOLEAN NOT NULL DEFAULT false, -- If true, strategy fails without this feature

    created_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT NOW(),
    updated_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT NOW(),

    CONSTRAINT unique_feature_per_strategy UNIQUE(strategy_config_id, feature_name)
);

-- ============================================================================
-- VERSION HISTORY
-- ============================================================================

-- Configuration version history for audit trail
CREATE TABLE adaptive_strategy_config_versions (
    id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
    strategy_id VARCHAR(100) NOT NULL,
    version INTEGER NOT NULL,

    -- Snapshot of configuration at this version (stored as JSONB)
    config_snapshot JSONB NOT NULL,

    -- Version metadata
    change_reason TEXT,
    changed_by UUID,
    changed_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT NOW(),

    -- Link to current configuration
    current_config_id UUID REFERENCES adaptive_strategy_config(id) ON DELETE CASCADE,

    UNIQUE(strategy_id, version)
);

-- ============================================================================
-- INDEXES
-- ============================================================================

-- Main configuration table indexes
CREATE INDEX idx_adaptive_strategy_config_active ON adaptive_strategy_config(active, strategy_id);
CREATE INDEX idx_adaptive_strategy_config_updated ON adaptive_strategy_config(updated_at DESC);

-- Model configuration indexes
CREATE INDEX idx_adaptive_strategy_models_strategy ON adaptive_strategy_models(strategy_config_id);
CREATE INDEX idx_adaptive_strategy_models_type ON adaptive_strategy_models(model_type, enabled);
CREATE INDEX idx_adaptive_strategy_models_order ON adaptive_strategy_models(strategy_config_id, display_order);

-- Feature configuration indexes
CREATE INDEX idx_adaptive_strategy_features_strategy ON adaptive_strategy_features(strategy_config_id);
CREATE INDEX idx_adaptive_strategy_features_type ON adaptive_strategy_features(feature_type, enabled);

-- Version history indexes
CREATE INDEX idx_adaptive_strategy_versions_strategy ON adaptive_strategy_config_versions(strategy_id, version DESC);
CREATE INDEX idx_adaptive_strategy_versions_changed ON adaptive_strategy_config_versions(changed_at DESC);

-- ============================================================================
-- TRIGGERS
-- ============================================================================

-- Function to update updated_at timestamp
CREATE OR REPLACE FUNCTION update_adaptive_strategy_updated_at()
RETURNS TRIGGER AS $$
BEGIN
    NEW.updated_at = NOW();
    RETURN NEW;
END;
$$ LANGUAGE plpgsql;

-- Trigger for main config table
CREATE TRIGGER adaptive_strategy_config_updated
BEFORE UPDATE ON adaptive_strategy_config
FOR EACH ROW
EXECUTE FUNCTION update_adaptive_strategy_updated_at();

-- Trigger for model config table
CREATE TRIGGER adaptive_strategy_models_updated
BEFORE UPDATE ON adaptive_strategy_models
FOR EACH ROW
EXECUTE FUNCTION update_adaptive_strategy_updated_at();

-- Trigger for feature config table
CREATE TRIGGER adaptive_strategy_features_updated
BEFORE UPDATE ON adaptive_strategy_features
FOR EACH ROW
EXECUTE FUNCTION update_adaptive_strategy_updated_at();

-- ============================================================================
-- HOT-RELOAD SUPPORT (PostgreSQL NOTIFY/LISTEN)
-- ============================================================================

-- Function to notify configuration changes
CREATE OR REPLACE FUNCTION notify_adaptive_strategy_config_change()
RETURNS TRIGGER AS $$
DECLARE
    payload JSON;
BEGIN
    payload = json_build_object(
        'table', TG_TABLE_NAME,
        'action', TG_OP,
        'strategy_id', COALESCE(NEW.strategy_id, OLD.strategy_id),
        'timestamp', EXTRACT(EPOCH FROM NOW())
    );

    PERFORM pg_notify('adaptive_strategy_config_change', payload::text);
    RETURN NEW;
END;
$$ LANGUAGE plpgsql;

-- Triggers for hot-reload notifications
CREATE TRIGGER adaptive_strategy_config_notify
AFTER INSERT OR UPDATE OR DELETE ON adaptive_strategy_config
FOR EACH ROW
EXECUTE FUNCTION notify_adaptive_strategy_config_change();

CREATE TRIGGER adaptive_strategy_models_notify
AFTER INSERT OR UPDATE OR DELETE ON adaptive_strategy_models
FOR EACH ROW
EXECUTE FUNCTION notify_adaptive_strategy_config_change();

CREATE TRIGGER adaptive_strategy_features_notify
AFTER INSERT OR UPDATE OR DELETE ON adaptive_strategy_features
FOR EACH ROW
EXECUTE FUNCTION notify_adaptive_strategy_config_change();

-- ============================================================================
-- VERSION ARCHIVING
-- ============================================================================

-- Function to archive configuration version on update
CREATE OR REPLACE FUNCTION archive_adaptive_strategy_version()
RETURNS TRIGGER AS $$
BEGIN
    IF TG_OP = 'UPDATE' THEN
        INSERT INTO adaptive_strategy_config_versions (
            strategy_id,
            version,
            config_snapshot,
            change_reason,
            changed_by,
            current_config_id
        ) VALUES (
            OLD.strategy_id,
            OLD.version,
            row_to_json(OLD),
            COALESCE(NEW.metadata->>'change_reason', 'Configuration updated'),
            NEW.updated_by,
            NEW.id
        );

        -- Increment version number
        NEW.version = OLD.version + 1;
    END IF;

    RETURN NEW;
END;
$$ LANGUAGE plpgsql;

-- Trigger for version archiving
CREATE TRIGGER adaptive_strategy_config_version_archive
BEFORE UPDATE ON adaptive_strategy_config
FOR EACH ROW
EXECUTE FUNCTION archive_adaptive_strategy_version();

-- ============================================================================
-- DEFAULT CONFIGURATION
-- ============================================================================

-- Insert default adaptive strategy configuration
INSERT INTO adaptive_strategy_config (
    strategy_id,
    name,
    description
) VALUES (
    'default',
    'Default Adaptive Strategy',
    'Default configuration for adaptive trading strategy with ensemble ML models'
);

-- Insert default models for the default strategy
INSERT INTO adaptive_strategy_models (
    strategy_config_id,
    model_id,
    model_name,
    model_type,
    parameters,
    initial_weight,
    enabled,
    display_order
) SELECT
    id,
    'mamba2_model',
    'MAMBA-2 SSM Model',
    'mamba2',
    '{"hidden_dim": 256, "state_size": 16, "num_layers": 4}'::jsonb,
    0.25,
    true,
    1
FROM adaptive_strategy_config WHERE strategy_id = 'default'
UNION ALL
SELECT
    id,
    'tlob_model',
    'TLOB Transformer Model',
    'tlob',
    '{"num_heads": 8, "num_layers": 6, "dropout": 0.1}'::jsonb,
    0.25,
    true,
    2
FROM adaptive_strategy_config WHERE strategy_id = 'default';

-- Insert default features for the default strategy
INSERT INTO adaptive_strategy_features (
    strategy_config_id,
    feature_name,
    feature_type,
    parameters,
    enabled,
    required
) SELECT
    id,
    'vpin',
    'orderbook',
    '{"window": 50}'::jsonb,
    true,
    true
FROM adaptive_strategy_config WHERE strategy_id = 'default'
UNION ALL
SELECT
    id,
    'order_flow',
    'orderbook',
    '{"depth": 10}'::jsonb,
    true,
    true
FROM adaptive_strategy_config WHERE strategy_id = 'default'
UNION ALL
SELECT
    id,
    'bid_ask_spread',
    'orderbook',
    '{}'::jsonb,
    true,
    false
FROM adaptive_strategy_config WHERE strategy_id = 'default';

-- ============================================================================
-- COMMENTS
-- ============================================================================

COMMENT ON TABLE adaptive_strategy_config IS 'Main configuration table for adaptive trading strategies, replaces hardcoded defaults';
COMMENT ON TABLE adaptive_strategy_models IS 'Model configurations within ensemble strategies';
COMMENT ON TABLE adaptive_strategy_features IS 'Feature extraction configurations for strategy models';
COMMENT ON TABLE adaptive_strategy_config_versions IS 'Version history for configuration changes and audit trail';

COMMENT ON COLUMN adaptive_strategy_config.execution_interval_ms IS 'Strategy execution interval in milliseconds (default: 100ms)';
COMMENT ON COLUMN adaptive_strategy_config.max_position_size IS 'Maximum position size as fraction of portfolio (0.0-1.0)';
COMMENT ON COLUMN adaptive_strategy_config.kelly_fraction IS 'Kelly Criterion fraction for position sizing (0.0-1.0)';
COMMENT ON COLUMN adaptive_strategy_models.parameters IS 'Model-specific parameters as flexible JSONB structure';
COMMENT ON COLUMN adaptive_strategy_features.parameters IS 'Feature-specific parameters as flexible JSONB structure';
