-- ================================================================================================
-- Migration 045: Wave D Regime Tracking Tables
-- Creates tables for regime state, transitions, and adaptive strategy metrics
-- ================================================================================================

-- ================================================================================================
-- Table: regime_states
-- Stores current regime classification and associated metrics per symbol
-- ================================================================================================
CREATE TABLE regime_states (
    id BIGSERIAL PRIMARY KEY,
    symbol TEXT NOT NULL,
    event_timestamp TIMESTAMPTZ NOT NULL,
    regime TEXT NOT NULL CHECK (regime IN ('Normal', 'Trending', 'Ranging', 'Volatile', 'Crisis', 'Illiquid', 'Momentum')),
    confidence DOUBLE PRECISION NOT NULL CHECK (confidence >= 0.0 AND confidence <= 1.0),

    -- CUSUM metrics (Agent D13 features)
    cusum_s_plus DOUBLE PRECISION,
    cusum_s_minus DOUBLE PRECISION,
    cusum_alert_count INTEGER DEFAULT 0,

    -- ADX & Directional Indicators (Agent D14 features)
    adx DOUBLE PRECISION CHECK (adx IS NULL OR (adx >= 0.0 AND adx <= 100.0)),
    plus_di DOUBLE PRECISION CHECK (plus_di IS NULL OR (plus_di >= 0.0 AND plus_di <= 100.0)),
    minus_di DOUBLE PRECISION CHECK (minus_di IS NULL OR (minus_di >= 0.0 AND minus_di <= 100.0)),

    -- Regime stability metrics (Agent D15 features)
    stability DOUBLE PRECISION CHECK (stability IS NULL OR (stability >= 0.0 AND stability <= 1.0)),
    entropy DOUBLE PRECISION CHECK (entropy IS NULL OR entropy >= 0.0),

    created_at TIMESTAMPTZ DEFAULT NOW(),

    CONSTRAINT unique_regime_state UNIQUE (symbol, event_timestamp)
);

-- Index for fast lookups by symbol and time
CREATE INDEX idx_regime_states_symbol_timestamp ON regime_states(symbol, event_timestamp DESC);
CREATE INDEX idx_regime_states_regime ON regime_states(regime);
CREATE INDEX idx_regime_states_confidence ON regime_states(confidence DESC);

COMMENT ON TABLE regime_states IS 'Wave D: Stores regime classification and associated metrics per symbol';
COMMENT ON COLUMN regime_states.regime IS 'Current regime: Normal, Trending, Ranging, Volatile, Crisis, Illiquid, Momentum';
COMMENT ON COLUMN regime_states.confidence IS 'Regime classification confidence (0.0-1.0)';
COMMENT ON COLUMN regime_states.cusum_s_plus IS 'CUSUM positive sum (Agent D13)';
COMMENT ON COLUMN regime_states.cusum_s_minus IS 'CUSUM negative sum (Agent D13)';
COMMENT ON COLUMN regime_states.cusum_alert_count IS 'Number of CUSUM alerts detected (Agent D13)';
COMMENT ON COLUMN regime_states.adx IS 'Average Directional Index (0-100, Agent D14)';
COMMENT ON COLUMN regime_states.plus_di IS 'Positive Directional Indicator (+DI, 0-100, Agent D14)';
COMMENT ON COLUMN regime_states.minus_di IS 'Negative Directional Indicator (-DI, 0-100, Agent D14)';
COMMENT ON COLUMN regime_states.stability IS 'Regime stability score (0.0-1.0, Agent D15)';
COMMENT ON COLUMN regime_states.entropy IS 'Regime entropy measure (>0, Agent D15)';

-- ================================================================================================
-- Table: regime_transitions
-- Tracks regime changes over time for pattern analysis
-- ================================================================================================
CREATE TABLE regime_transitions (
    id BIGSERIAL PRIMARY KEY,
    symbol TEXT NOT NULL,
    event_timestamp TIMESTAMPTZ NOT NULL,
    from_regime TEXT NOT NULL CHECK (from_regime IN ('Normal', 'Trending', 'Ranging', 'Volatile', 'Crisis', 'Illiquid', 'Momentum')),
    to_regime TEXT NOT NULL CHECK (to_regime IN ('Normal', 'Trending', 'Ranging', 'Volatile', 'Crisis', 'Illiquid', 'Momentum')),
    duration_bars INTEGER CHECK (duration_bars >= 0),

    -- Transition probability (Agent D15 features)
    transition_probability DOUBLE PRECISION CHECK (transition_probability IS NULL OR (transition_probability >= 0.0 AND transition_probability <= 1.0)),

    -- Transition context
    adx_at_transition DOUBLE PRECISION,
    cusum_alert_triggered BOOLEAN DEFAULT FALSE,

    created_at TIMESTAMPTZ DEFAULT NOW(),

    CONSTRAINT regime_transition_valid CHECK (from_regime != to_regime)
);

-- Indexes for fast transition analysis
CREATE INDEX idx_regime_transitions_symbol_timestamp ON regime_transitions(symbol, event_timestamp DESC);
CREATE INDEX idx_regime_transitions_from_to ON regime_transitions(from_regime, to_regime);
CREATE INDEX idx_regime_transitions_symbol_from_to ON regime_transitions(symbol, from_regime, to_regime);

COMMENT ON TABLE regime_transitions IS 'Wave D: Tracks regime transitions for pattern analysis';
COMMENT ON COLUMN regime_transitions.from_regime IS 'Source regime before transition';
COMMENT ON COLUMN regime_transitions.to_regime IS 'Destination regime after transition';
COMMENT ON COLUMN regime_transitions.duration_bars IS 'Number of bars in previous regime';
COMMENT ON COLUMN regime_transitions.transition_probability IS 'Transition probability from matrix (Agent D15)';
COMMENT ON COLUMN regime_transitions.adx_at_transition IS 'ADX value at transition point';
COMMENT ON COLUMN regime_transitions.cusum_alert_triggered IS 'Whether CUSUM alert triggered transition';

-- ================================================================================================
-- Table: adaptive_strategy_metrics
-- Stores adaptive strategy adjustments and performance per regime
-- ================================================================================================
CREATE TABLE adaptive_strategy_metrics (
    id BIGSERIAL PRIMARY KEY,
    symbol TEXT NOT NULL,
    event_timestamp TIMESTAMPTZ NOT NULL,
    regime TEXT NOT NULL CHECK (regime IN ('Normal', 'Trending', 'Ranging', 'Volatile', 'Crisis', 'Illiquid', 'Momentum')),

    -- Adaptive Strategy Metrics (Agent D16 features)
    position_multiplier DOUBLE PRECISION NOT NULL CHECK (position_multiplier >= 0.0 AND position_multiplier <= 2.0),
    stop_loss_multiplier DOUBLE PRECISION NOT NULL CHECK (stop_loss_multiplier >= 1.0 AND stop_loss_multiplier <= 5.0),
    regime_sharpe DOUBLE PRECISION,
    risk_budget_utilization DOUBLE PRECISION CHECK (risk_budget_utilization IS NULL OR (risk_budget_utilization >= 0.0 AND risk_budget_utilization <= 1.0)),

    -- Performance tracking
    total_trades INTEGER DEFAULT 0,
    winning_trades INTEGER DEFAULT 0,
    total_pnl BIGINT DEFAULT 0,

    created_at TIMESTAMPTZ DEFAULT NOW(),

    CONSTRAINT unique_adaptive_metrics UNIQUE (symbol, event_timestamp, regime)
);

-- Indexes for performance analysis
CREATE INDEX idx_adaptive_metrics_symbol_timestamp ON adaptive_strategy_metrics(symbol, event_timestamp DESC);
CREATE INDEX idx_adaptive_metrics_regime ON adaptive_strategy_metrics(regime);
CREATE INDEX idx_adaptive_metrics_sharpe ON adaptive_strategy_metrics(regime_sharpe DESC) WHERE regime_sharpe IS NOT NULL;

COMMENT ON TABLE adaptive_strategy_metrics IS 'Wave D: Adaptive strategy adjustments and regime-specific performance';
COMMENT ON COLUMN adaptive_strategy_metrics.position_multiplier IS 'Position size multiplier for regime (0.2-2.0x, Agent D16)';
COMMENT ON COLUMN adaptive_strategy_metrics.stop_loss_multiplier IS 'Stop-loss distance multiplier for regime (1.0-5.0x, Agent D16)';
COMMENT ON COLUMN adaptive_strategy_metrics.regime_sharpe IS 'Sharpe ratio conditioned on regime (Agent D16)';
COMMENT ON COLUMN adaptive_strategy_metrics.risk_budget_utilization IS 'Risk budget usage ratio (0.0-1.0, Agent D16)';

-- ================================================================================================
-- Function: Get latest regime state for symbol
-- ================================================================================================
CREATE OR REPLACE FUNCTION get_latest_regime(p_symbol TEXT)
RETURNS TABLE (
    regime TEXT,
    confidence DOUBLE PRECISION,
    event_timestamp TIMESTAMPTZ,
    cusum_s_plus DOUBLE PRECISION,
    cusum_s_minus DOUBLE PRECISION,
    adx DOUBLE PRECISION,
    stability DOUBLE PRECISION
) AS $$
BEGIN
    RETURN QUERY
    SELECT
        rs.regime,
        rs.confidence,
        rs.event_timestamp,
        rs.cusum_s_plus,
        rs.cusum_s_minus,
        rs.adx,
        rs.stability
    FROM regime_states rs
    WHERE rs.symbol = p_symbol
    ORDER BY rs.event_timestamp DESC
    LIMIT 1;
END;
$$ LANGUAGE plpgsql;

COMMENT ON FUNCTION get_latest_regime IS 'Get most recent regime classification for a symbol';

-- ================================================================================================
-- Function: Get regime transition matrix
-- Calculate transition probabilities between regimes
-- ================================================================================================
CREATE OR REPLACE FUNCTION get_regime_transition_matrix(
    p_symbol TEXT,
    p_window_hours INTEGER DEFAULT 168  -- 1 week default
)
RETURNS TABLE (
    from_regime TEXT,
    to_regime TEXT,
    transition_count BIGINT,
    transition_probability DOUBLE PRECISION
) AS $$
BEGIN
    RETURN QUERY
    WITH transition_counts AS (
        SELECT
            rt.from_regime,
            rt.to_regime,
            COUNT(*) AS count
        FROM regime_transitions rt
        WHERE
            rt.symbol = p_symbol
            AND rt.event_timestamp >= NOW() - (p_window_hours || ' hours')::INTERVAL
        GROUP BY rt.from_regime, rt.to_regime
    ),
    from_regime_totals AS (
        SELECT
            tc2.from_regime AS regime,
            SUM(tc2.count) AS total
        FROM transition_counts tc2
        GROUP BY tc2.from_regime
    )
    SELECT
        tc.from_regime,
        tc.to_regime,
        tc.count AS transition_count,
        (tc.count::DOUBLE PRECISION / frt.total::DOUBLE PRECISION) AS transition_probability
    FROM transition_counts tc
    JOIN from_regime_totals frt ON tc.from_regime = frt.regime
    ORDER BY tc.from_regime, tc.to_regime;
END;
$$ LANGUAGE plpgsql;

COMMENT ON FUNCTION get_regime_transition_matrix IS 'Calculate regime transition probabilities over time window';

-- ================================================================================================
-- Function: Get adaptive strategy performance by regime
-- ================================================================================================
CREATE OR REPLACE FUNCTION get_regime_performance(
    p_symbol TEXT DEFAULT NULL,
    p_window_hours INTEGER DEFAULT 24
)
RETURNS TABLE (
    regime TEXT,
    total_trades BIGINT,
    win_rate DOUBLE PRECISION,
    avg_sharpe DOUBLE PRECISION,
    avg_position_multiplier DOUBLE PRECISION,
    avg_stop_loss_multiplier DOUBLE PRECISION,
    total_pnl NUMERIC,
    avg_risk_utilization DOUBLE PRECISION
) AS $$
BEGIN
    RETURN QUERY
    SELECT
        asm.regime,
        SUM(asm.total_trades) AS total_trades,
        CASE
            WHEN SUM(asm.total_trades) > 0 THEN
                SUM(asm.winning_trades)::DOUBLE PRECISION / SUM(asm.total_trades)::DOUBLE PRECISION
            ELSE 0.0
        END AS win_rate,
        AVG(asm.regime_sharpe) AS avg_sharpe,
        AVG(asm.position_multiplier) AS avg_position_multiplier,
        AVG(asm.stop_loss_multiplier) AS avg_stop_loss_multiplier,
        SUM(asm.total_pnl) AS total_pnl,
        AVG(asm.risk_budget_utilization) AS avg_risk_utilization
    FROM adaptive_strategy_metrics asm
    WHERE
        asm.event_timestamp >= NOW() - (p_window_hours || ' hours')::INTERVAL
        AND (p_symbol IS NULL OR asm.symbol = p_symbol)
    GROUP BY asm.regime
    ORDER BY asm.regime;
END;
$$ LANGUAGE plpgsql;

COMMENT ON FUNCTION get_regime_performance IS 'Get adaptive strategy performance metrics by regime';

-- ================================================================================================
-- Grant permissions
-- ================================================================================================
GRANT SELECT, INSERT, UPDATE ON regime_states TO foxhunt;
GRANT SELECT, INSERT ON regime_transitions TO foxhunt;
GRANT SELECT, INSERT, UPDATE ON adaptive_strategy_metrics TO foxhunt;
GRANT USAGE, SELECT ON SEQUENCE regime_states_id_seq TO foxhunt;
GRANT USAGE, SELECT ON SEQUENCE regime_transitions_id_seq TO foxhunt;
GRANT USAGE, SELECT ON SEQUENCE adaptive_strategy_metrics_id_seq TO foxhunt;
GRANT EXECUTE ON FUNCTION get_latest_regime TO foxhunt;
GRANT EXECUTE ON FUNCTION get_regime_transition_matrix TO foxhunt;
GRANT EXECUTE ON FUNCTION get_regime_performance TO foxhunt;

-- ================================================================================================
-- END MIGRATION 045
-- ================================================================================================
