-- ============================================================================
-- SCHEMA: trading
-- TABLE: strategies
-- DESCRIPTION: Estrategias de trading definidas
-- VERSION: 1.0.0
-- CREATED: 2026-01-16
-- SPRINT: Sprint 3 - DDL Implementation Roadmap Q1-2026
-- ============================================================================

-- Enum para tipo de estrategia
DO $$ BEGIN
    CREATE TYPE trading.strategy_type AS ENUM (
        'manual',           -- Estrategia manual (usuario decide)
        'semi_auto',        -- Semi-automatica (senales con confirmacion)
        'fully_auto',       -- Totalmente automatizada
        'copy_trading'      -- Copy trading de otro usuario/bot
    );
EXCEPTION
    WHEN duplicate_object THEN null;
END $$;

-- Enum para metodologia de trading
DO $$ BEGIN
    CREATE TYPE trading.trading_methodology AS ENUM (
        'trend_following',      -- Seguimiento de tendencia
        'mean_reversion',       -- Reversion a la media
        'breakout',             -- Rupturas
        'scalping',             -- Scalping
        'swing',                -- Swing trading
        'position',             -- Position trading
        'arbitrage',            -- Arbitraje
        'news_based',           -- Basado en noticias
        'smc_ict',              -- Smart Money Concepts / ICT
        'harmonic',             -- Patrones armonicos
        'custom'                -- Personalizada
    );
EXCEPTION
    WHEN duplicate_object THEN null;
END $$;

-- Tabla de Estrategias
CREATE TABLE IF NOT EXISTS trading.strategies (
    -- Identificadores
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    tenant_id UUID NOT NULL REFERENCES tenants.tenants(id) ON DELETE CASCADE,
    created_by UUID REFERENCES users.users(id),

    -- Informacion basica
    name VARCHAR(100) NOT NULL,
    slug VARCHAR(100) NOT NULL,
    description TEXT,
    short_description VARCHAR(500),

    -- Clasificacion
    type trading.strategy_type NOT NULL DEFAULT 'manual',
    methodology trading.trading_methodology NOT NULL DEFAULT 'custom',

    -- Configuracion de riesgo
    risk_config JSONB NOT NULL DEFAULT '{
        "risk_per_trade_percent": 2,
        "max_daily_loss_percent": 5,
        "max_drawdown_percent": 20,
        "max_concurrent_trades": 3,
        "risk_reward_min": 1.5
    }'::JSONB,

    -- Configuracion de entrada
    entry_config JSONB NOT NULL DEFAULT '{
        "order_type": "market",
        "slippage_pips": 2,
        "max_spread_pips": 5,
        "entry_confirmation_required": false
    }'::JSONB,

    -- Configuracion de salida
    exit_config JSONB NOT NULL DEFAULT '{
        "use_trailing_stop": false,
        "trailing_stop_pips": 20,
        "partial_close_enabled": false,
        "partial_close_percent": 50,
        "breakeven_enabled": false,
        "breakeven_pips": 10
    }'::JSONB,

    -- Simbolos y timeframes
    allowed_symbols VARCHAR(20)[],                  -- NULL = todos
    allowed_timeframes trading.timeframe[],
    primary_timeframe trading.timeframe DEFAULT 'H1',

    -- Horarios de trading
    trading_hours JSONB DEFAULT '{
        "enabled": false,
        "sessions": ["london", "new_york"],
        "avoid_news": true,
        "news_buffer_minutes": 30
    }'::JSONB,

    -- Indicadores utilizados
    indicators_config JSONB DEFAULT '[]'::JSONB,

    -- Reglas de entrada (para estrategias automaticas)
    entry_rules JSONB DEFAULT '[]'::JSONB,

    -- Reglas de salida
    exit_rules JSONB DEFAULT '[]'::JSONB,

    -- Estado
    is_active BOOLEAN NOT NULL DEFAULT TRUE,
    is_public BOOLEAN NOT NULL DEFAULT FALSE,       -- Visible para otros usuarios
    is_premium BOOLEAN NOT NULL DEFAULT FALSE,      -- Requiere suscripcion

    -- Estadisticas
    total_trades INTEGER NOT NULL DEFAULT 0,
    winning_trades INTEGER NOT NULL DEFAULT 0,
    losing_trades INTEGER NOT NULL DEFAULT 0,
    win_rate DECIMAL(5, 2) DEFAULT 0,
    profit_factor DECIMAL(10, 4) DEFAULT 0,
    average_profit DECIMAL(15, 4) DEFAULT 0,
    average_loss DECIMAL(15, 4) DEFAULT 0,
    max_drawdown DECIMAL(15, 4) DEFAULT 0,
    total_profit_loss DECIMAL(15, 4) DEFAULT 0,

    -- Backtesting
    last_backtest_at TIMESTAMPTZ,
    backtest_results JSONB,

    -- Version control
    version INTEGER NOT NULL DEFAULT 1,
    previous_version_id UUID,

    -- Metadata
    tags VARCHAR(50)[],
    metadata JSONB DEFAULT '{}'::JSONB,

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

    -- Constraints
    CONSTRAINT strategies_unique_slug UNIQUE (tenant_id, slug),
    CONSTRAINT strategies_win_rate_check CHECK (win_rate BETWEEN 0 AND 100)
);

COMMENT ON TABLE trading.strategies IS
'Estrategias de trading con configuracion de riesgo, entrada y salida';

COMMENT ON COLUMN trading.strategies.risk_config IS
'Configuracion de gestion de riesgo de la estrategia';

-- Indices
CREATE INDEX IF NOT EXISTS idx_strategies_tenant
    ON trading.strategies(tenant_id);

CREATE INDEX IF NOT EXISTS idx_strategies_creator
    ON trading.strategies(created_by);

CREATE INDEX IF NOT EXISTS idx_strategies_type
    ON trading.strategies(type);

CREATE INDEX IF NOT EXISTS idx_strategies_methodology
    ON trading.strategies(methodology);

CREATE INDEX IF NOT EXISTS idx_strategies_active
    ON trading.strategies(tenant_id, is_active)
    WHERE is_active = TRUE;

CREATE INDEX IF NOT EXISTS idx_strategies_public
    ON trading.strategies(is_public, win_rate DESC)
    WHERE is_public = TRUE;

-- GIN index para tags
CREATE INDEX IF NOT EXISTS idx_strategies_tags_gin
    ON trading.strategies USING GIN (tags);

-- Trigger para updated_at
DROP TRIGGER IF EXISTS strategy_updated_at ON trading.strategies;
CREATE TRIGGER strategy_updated_at
    BEFORE UPDATE ON trading.strategies
    FOR EACH ROW
    EXECUTE FUNCTION trading.update_trading_timestamp();

-- Funcion para calcular estadisticas de estrategia
CREATE OR REPLACE FUNCTION trading.recalculate_strategy_stats(p_strategy_id UUID)
RETURNS VOID AS $$
DECLARE
    v_stats RECORD;
BEGIN
    SELECT
        COUNT(*) AS total,
        COUNT(*) FILTER (WHERE profit_loss > 0) AS wins,
        COUNT(*) FILTER (WHERE profit_loss < 0) AS losses,
        COALESCE(AVG(profit_loss) FILTER (WHERE profit_loss > 0), 0) AS avg_profit,
        COALESCE(AVG(ABS(profit_loss)) FILTER (WHERE profit_loss < 0), 0) AS avg_loss,
        COALESCE(SUM(profit_loss), 0) AS total_pnl
    INTO v_stats
    FROM trading.positions
    WHERE strategy_id = p_strategy_id
      AND status IN ('closed', 'stopped', 'target_hit');

    UPDATE trading.strategies
    SET total_trades = v_stats.total,
        winning_trades = v_stats.wins,
        losing_trades = v_stats.losses,
        win_rate = CASE WHEN v_stats.total > 0
                        THEN (v_stats.wins::DECIMAL / v_stats.total * 100)
                        ELSE 0 END,
        profit_factor = CASE WHEN v_stats.avg_loss > 0
                             THEN v_stats.avg_profit / v_stats.avg_loss
                             ELSE 0 END,
        average_profit = v_stats.avg_profit,
        average_loss = v_stats.avg_loss,
        total_profit_loss = v_stats.total_pnl
    WHERE id = p_strategy_id;
END;
$$ LANGUAGE plpgsql;

-- Vista de estrategias publicas
CREATE OR REPLACE VIEW trading.v_public_strategies AS
SELECT
    id,
    name,
    description,
    type,
    methodology,
    primary_timeframe,
    total_trades,
    win_rate,
    profit_factor,
    max_drawdown,
    is_premium,
    created_at
FROM trading.strategies
WHERE is_public = TRUE
  AND is_active = TRUE
  AND total_trades >= 10  -- Minimo de trades para mostrar
ORDER BY win_rate DESC, profit_factor DESC;

-- RLS Policy para multi-tenancy
ALTER TABLE trading.strategies ENABLE ROW LEVEL SECURITY;

CREATE POLICY strategies_tenant_isolation ON trading.strategies
    FOR ALL
    USING (tenant_id = current_setting('app.current_tenant_id', true)::UUID);

-- Grants
GRANT SELECT, INSERT, UPDATE, DELETE ON trading.strategies TO trading_app;
GRANT SELECT ON trading.strategies TO trading_readonly;
GRANT SELECT ON trading.v_public_strategies TO trading_app;
GRANT EXECUTE ON FUNCTION trading.recalculate_strategy_stats TO trading_app;
