-- ============================================================================
-- SCHEMA: broker_integration
-- TABLE: spread_statistics, price_adjustment_model
-- DESCRIPTION: Estadisticas de spread y modelos de ajuste de precio
-- VERSION: 1.0.0
-- CREATED: 2026-01-16
-- SPRINT: Sprint 6 - DDL Implementation Roadmap Q1-2026
-- ============================================================================

-- Tabla de Estadisticas de Spread
CREATE TABLE IF NOT EXISTS broker_integration.spread_statistics (
    -- Identificadores
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    tenant_id UUID NOT NULL,
    broker_account_id UUID REFERENCES broker_integration.broker_accounts(id) ON DELETE CASCADE,

    -- Simbolo y periodo
    symbol VARCHAR(20) NOT NULL,
    period_start TIMESTAMPTZ NOT NULL,
    period_end TIMESTAMPTZ NOT NULL,
    period_type VARCHAR(20) NOT NULL,                   -- 'hourly', 'daily', 'session'

    -- Estadisticas de spread
    spread_min DECIMAL(10, 4),
    spread_max DECIMAL(10, 4),
    spread_avg DECIMAL(10, 4),
    spread_median DECIMAL(10, 4),
    spread_stddev DECIMAL(10, 4),
    spread_percentile_95 DECIMAL(10, 4),

    -- Spread por sesion
    spread_asia_avg DECIMAL(10, 4),
    spread_london_avg DECIMAL(10, 4),
    spread_ny_avg DECIMAL(10, 4),

    -- Frecuencia de widening
    widening_events INTEGER NOT NULL DEFAULT 0,
    max_widening_factor DECIMAL(10, 2),

    -- Samples
    sample_count INTEGER NOT NULL DEFAULT 0,
    trading_hours_covered INTEGER,                      -- Horas de trading cubiertas

    -- Comparacion historica
    spread_vs_7d_avg DECIMAL(10, 4),                   -- % vs promedio 7 dias
    spread_vs_30d_avg DECIMAL(10, 4),                  -- % vs promedio 30 dias

    -- Metadata
    metadata JSONB DEFAULT '{}'::JSONB,

    -- Timestamps
    calculated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
    created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),

    -- Constraints
    CONSTRAINT spread_stats_unique UNIQUE (broker_account_id, symbol, period_start, period_type)
);

COMMENT ON TABLE broker_integration.spread_statistics IS
'Estadisticas historicas de spread por simbolo, broker y periodo';

-- Indices
CREATE INDEX IF NOT EXISTS idx_spread_stats_account
    ON broker_integration.spread_statistics(broker_account_id);

CREATE INDEX IF NOT EXISTS idx_spread_stats_symbol
    ON broker_integration.spread_statistics(symbol, period_start DESC);

CREATE INDEX IF NOT EXISTS idx_spread_stats_period
    ON broker_integration.spread_statistics(period_type, period_start DESC);

-- ============================================================================
-- TABLE: price_adjustment_model
-- ============================================================================

-- Tabla de Modelos de Ajuste de Precio
CREATE TABLE IF NOT EXISTS broker_integration.price_adjustment_model (
    -- Identificadores
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    tenant_id UUID NOT NULL,

    -- Simbolo
    symbol VARCHAR(20) NOT NULL,

    -- Tipo de modelo
    model_type VARCHAR(50) NOT NULL DEFAULT 'spread_based',

    -- Parametros del modelo
    base_spread_pips DECIMAL(10, 4) NOT NULL DEFAULT 1,
    slippage_avg_pips DECIMAL(10, 4) NOT NULL DEFAULT 0.2,
    slippage_max_pips DECIMAL(10, 4) NOT NULL DEFAULT 2,

    -- Ajustes por sesion
    asia_adjustment DECIMAL(5, 4) DEFAULT 1.2,          -- Multiplicador
    london_adjustment DECIMAL(5, 4) DEFAULT 1.0,
    ny_adjustment DECIMAL(5, 4) DEFAULT 1.0,
    overlap_adjustment DECIMAL(5, 4) DEFAULT 0.9,       -- London-NY overlap

    -- Ajustes por volatilidad
    low_volatility_adjustment DECIMAL(5, 4) DEFAULT 0.8,
    high_volatility_adjustment DECIMAL(5, 4) DEFAULT 1.5,
    extreme_volatility_adjustment DECIMAL(5, 4) DEFAULT 2.5,

    -- Ajustes por horario
    market_open_adjustment DECIMAL(5, 4) DEFAULT 1.5,
    market_close_adjustment DECIMAL(5, 4) DEFAULT 1.3,
    news_event_adjustment DECIMAL(5, 4) DEFAULT 2.0,

    -- Limites
    max_total_adjustment DECIMAL(5, 2) DEFAULT 5.0,     -- Max pips de ajuste total
    min_acceptable_spread DECIMAL(10, 4),
    max_acceptable_spread DECIMAL(10, 4),

    -- Estado
    is_active BOOLEAN NOT NULL DEFAULT TRUE,

    -- Validez
    valid_from TIMESTAMPTZ NOT NULL DEFAULT NOW(),
    valid_until TIMESTAMPTZ,

    -- Performance
    accuracy_score DECIMAL(5, 2),                       -- 0-100
    last_accuracy_check TIMESTAMPTZ,
    predictions_count INTEGER NOT NULL DEFAULT 0,
    accurate_predictions INTEGER NOT NULL DEFAULT 0,

    -- Metadata
    training_data_range JSONB,                          -- {"start": "...", "end": "..."}
    metadata JSONB DEFAULT '{}'::JSONB,
    notes TEXT,

    -- Timestamps
    created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
    updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),

    -- Constraints
    CONSTRAINT price_adj_model_unique UNIQUE (tenant_id, symbol, model_type)
);

COMMENT ON TABLE broker_integration.price_adjustment_model IS
'Modelos para ajustar precios de entrada considerando spread y slippage';

-- Indices
CREATE INDEX IF NOT EXISTS idx_price_adj_symbol
    ON broker_integration.price_adjustment_model(symbol);

CREATE INDEX IF NOT EXISTS idx_price_adj_active
    ON broker_integration.price_adjustment_model(symbol, is_active)
    WHERE is_active = TRUE;

-- Funcion para calcular ajuste de precio
CREATE OR REPLACE FUNCTION broker_integration.calculate_price_adjustment(
    p_symbol VARCHAR,
    p_direction VARCHAR,
    p_current_price DECIMAL,
    p_session VARCHAR DEFAULT NULL,
    p_volatility VARCHAR DEFAULT 'normal'
)
RETURNS TABLE (
    adjusted_entry DECIMAL,
    adjusted_sl DECIMAL,
    adjusted_tp DECIMAL,
    total_adjustment_pips DECIMAL,
    adjustment_breakdown JSONB
) AS $$
DECLARE
    v_model broker_integration.price_adjustment_model;
    v_adjustment DECIMAL;
    v_session_mult DECIMAL;
    v_volatility_mult DECIMAL;
BEGIN
    SELECT * INTO v_model
    FROM broker_integration.price_adjustment_model
    WHERE symbol = p_symbol
      AND is_active = TRUE
      AND (valid_until IS NULL OR valid_until > NOW())
    ORDER BY valid_from DESC
    LIMIT 1;

    IF NOT FOUND THEN
        -- Retornar sin ajuste
        RETURN QUERY SELECT
            p_current_price,
            p_current_price,
            p_current_price,
            0::DECIMAL,
            '{}'::JSONB;
        RETURN;
    END IF;

    -- Determinar multiplicador de sesion
    v_session_mult := CASE p_session
        WHEN 'asia' THEN v_model.asia_adjustment
        WHEN 'london' THEN v_model.london_adjustment
        WHEN 'ny' THEN v_model.ny_adjustment
        WHEN 'overlap' THEN v_model.overlap_adjustment
        ELSE 1.0
    END;

    -- Determinar multiplicador de volatilidad
    v_volatility_mult := CASE p_volatility
        WHEN 'low' THEN v_model.low_volatility_adjustment
        WHEN 'high' THEN v_model.high_volatility_adjustment
        WHEN 'extreme' THEN v_model.extreme_volatility_adjustment
        ELSE 1.0
    END;

    -- Calcular ajuste total en pips
    v_adjustment := (v_model.base_spread_pips + v_model.slippage_avg_pips)
                    * v_session_mult * v_volatility_mult;

    -- Limitar ajuste
    v_adjustment := LEAST(v_adjustment, v_model.max_total_adjustment);

    -- Convertir a precio
    v_adjustment := v_adjustment * 0.0001;  -- 1 pip = 0.0001

    RETURN QUERY SELECT
        CASE p_direction
            WHEN 'long' THEN p_current_price + v_adjustment
            ELSE p_current_price - v_adjustment
        END,
        p_current_price,  -- SL sin ajustar
        p_current_price,  -- TP sin ajustar
        v_adjustment * 10000,  -- En pips
        jsonb_build_object(
            'base_spread', v_model.base_spread_pips,
            'slippage', v_model.slippage_avg_pips,
            'session_multiplier', v_session_mult,
            'volatility_multiplier', v_volatility_mult
        );
END;
$$ LANGUAGE plpgsql;

-- Trigger para updated_at
DROP TRIGGER IF EXISTS price_adj_updated_at ON broker_integration.price_adjustment_model;
CREATE TRIGGER price_adj_updated_at
    BEFORE UPDATE ON broker_integration.price_adjustment_model
    FOR EACH ROW
    EXECUTE FUNCTION broker_integration.update_broker_timestamp();

-- RLS
ALTER TABLE broker_integration.spread_statistics ENABLE ROW LEVEL SECURITY;
ALTER TABLE broker_integration.price_adjustment_model ENABLE ROW LEVEL SECURITY;

CREATE POLICY spread_stats_tenant ON broker_integration.spread_statistics
    FOR ALL
    USING (tenant_id = current_setting('app.current_tenant_id', true)::UUID);

CREATE POLICY price_adj_tenant ON broker_integration.price_adjustment_model
    FOR ALL
    USING (tenant_id = current_setting('app.current_tenant_id', true)::UUID);

-- Grants
GRANT SELECT, INSERT, UPDATE, DELETE ON broker_integration.spread_statistics TO trading_app;
GRANT SELECT, INSERT, UPDATE, DELETE ON broker_integration.price_adjustment_model TO trading_app;
GRANT SELECT ON broker_integration.spread_statistics TO trading_readonly;
GRANT SELECT ON broker_integration.price_adjustment_model TO trading_readonly;
GRANT EXECUTE ON FUNCTION broker_integration.calculate_price_adjustment TO trading_app;
