-- Migration 018: Centralized Configuration Management System
-- PostgreSQL NOTIFY/LISTEN hot-reload, validation, and audit support

-- Main configuration settings table
CREATE TABLE IF NOT EXISTS config_settings (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    service_scope VARCHAR(64) NOT NULL,
    config_key VARCHAR(128) NOT NULL,
    config_value JSONB NOT NULL,
    data_type VARCHAR(32) NOT NULL,
    validation_rules JSONB,
    description TEXT,
    is_active BOOLEAN NOT NULL DEFAULT TRUE,
    created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
    updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
    updated_by VARCHAR(128),
    CONSTRAINT unique_service_key UNIQUE (service_scope, config_key)
);

-- Index for faster lookups by service_scope and key
CREATE INDEX IF NOT EXISTS idx_config_settings_service_key 
ON config_settings (service_scope, config_key);

-- Index for active configurations
CREATE INDEX IF NOT EXISTS idx_config_settings_active 
ON config_settings (is_active) WHERE is_active = TRUE;

-- Configuration audit log table
CREATE TABLE IF NOT EXISTS config_audit_log (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    action VARCHAR(32) NOT NULL,
    service_scope VARCHAR(64) NOT NULL,
    config_key VARCHAR(128) NOT NULL,
    old_value JSONB,
    new_value JSONB,
    changed_by VARCHAR(128) NOT NULL,
    change_timestamp TIMESTAMPTZ NOT NULL DEFAULT NOW()
);

-- Index for audit log queries
CREATE INDEX IF NOT EXISTS idx_config_audit_log_timestamp 
ON config_audit_log (change_timestamp DESC);

CREATE INDEX IF NOT EXISTS idx_config_audit_log_service_key 
ON config_audit_log (service_scope, config_key);

-- Trigger for updated_at column
CREATE OR REPLACE FUNCTION update_config_settings_updated_at()
RETURNS TRIGGER AS $$
BEGIN
    NEW.updated_at = NOW();
    RETURN NEW;
END;
$$ LANGUAGE plpgsql;

CREATE TRIGGER trigger_update_config_settings_updated_at
BEFORE UPDATE ON config_settings
FOR EACH ROW
EXECUTE FUNCTION update_config_settings_updated_at();

-- Trigger for PostgreSQL NOTIFY on configuration changes
CREATE OR REPLACE FUNCTION notify_config_change()
RETURNS TRIGGER AS $$
DECLARE
    payload JSON;
BEGIN
    -- Build notification payload
    payload := json_build_object(
        'service_scope', NEW.service_scope,
        'config_key', NEW.config_key,
        'action', TG_OP
    );
    
    -- Global notification for all services
    PERFORM pg_notify('config_updates_global', payload::text);
    
    -- Service-specific notification
    PERFORM pg_notify('config_updates_' || NEW.service_scope, 
        json_build_object('config_key', NEW.config_key, 'action', TG_OP)::text);
    
    RETURN NEW;
END;
$$ LANGUAGE plpgsql;

CREATE TRIGGER trigger_notify_config_change
AFTER INSERT OR UPDATE ON config_settings
FOR EACH ROW
EXECUTE FUNCTION notify_config_change();

-- Seed default configurations
INSERT INTO config_settings (service_scope, config_key, config_value, data_type, validation_rules, description, updated_by)
VALUES
    -- Global configurations
    ('global', 'system_timezone', '"UTC"', 'string', '{"regex": "^[A-Z]{3}$"}', 'System timezone', 'system'),
    ('global', 'max_concurrent_connections', '1000', 'integer', '{"min": 1, "max": 10000}', 'Maximum concurrent connections', 'system'),
    ('global', 'cache_ttl_seconds', '300', 'integer', '{"min": 1, "max": 3600}', 'Cache TTL in seconds', 'system'),
    
    -- Trading service configurations
    ('trading', 'max_position_size', '0.1', 'float', '{"min": 0.0, "max": 1.0}', 'Maximum position size as fraction of portfolio', 'system'),
    ('trading', 'risk_limit_daily', '0.02', 'float', '{"min": 0.0, "max": 0.1}', 'Daily risk limit as fraction', 'system'),
    ('trading', 'order_timeout_ms', '5000', 'integer', '{"min": 100, "max": 30000}', 'Order timeout in milliseconds', 'system'),
    
    -- Backtesting service configurations
    ('backtesting', 'default_commission_bps', '5.0', 'float', '{"min": 0.0, "max": 100.0}', 'Default commission in basis points', 'system'),
    ('backtesting', 'slippage_model', '"FIXED"', 'string', '{"enum": ["FIXED", "VOLUME_BASED", "SPREAD_BASED"]}', 'Slippage model type', 'system'),
    
    -- ML Training service configurations
    ('ml_training', 'batch_size', '64', 'integer', '{"min": 1, "max": 1024}', 'Training batch size', 'system'),
    ('ml_training', 'learning_rate', '0.001', 'float', '{"min": 0.00001, "max": 0.1}', 'Learning rate', 'system'),
    ('ml_training', 'max_epochs', '100', 'integer', '{"min": 1, "max": 1000}', 'Maximum training epochs', 'system')
ON CONFLICT (service_scope, config_key) DO NOTHING;

-- Grant permissions (adjust as needed for your security model)
-- GRANT SELECT, INSERT, UPDATE ON config_settings TO api_gateway_role;
-- GRANT SELECT, INSERT ON config_audit_log TO api_gateway_role;
