-- ============================================================================
-- SCHEMA: broker_integration
-- TABLE: broker_accounts
-- DESCRIPTION: Cuentas de broker conectadas (MT4, MT5, etc.)
-- VERSION: 1.0.0
-- CREATED: 2026-01-16
-- SPRINT: Sprint 6 - DDL Implementation Roadmap Q1-2026
-- ============================================================================

-- Crear schema
CREATE SCHEMA IF NOT EXISTS broker_integration;

COMMENT ON SCHEMA broker_integration IS
'Integracion con brokers de trading (MT4, MT5, API de brokers)';

-- Enum para tipo de broker
DO $$ BEGIN
    CREATE TYPE broker_integration.broker_type AS ENUM (
        'mt4',
        'mt5',
        'ctrader',
        'fix_api',
        'rest_api',
        'binance',
        'interactive_brokers',
        'oanda',
        'alpaca',
        'custom'
    );
EXCEPTION
    WHEN duplicate_object THEN null;
END $$;

-- Enum para tipo de cuenta
DO $$ BEGIN
    CREATE TYPE broker_integration.account_type AS ENUM (
        'demo',
        'live',
        'contest'
    );
EXCEPTION
    WHEN duplicate_object THEN null;
END $$;

-- Enum para estado de conexion
DO $$ BEGIN
    CREATE TYPE broker_integration.connection_status AS ENUM (
        'connected',
        'disconnected',
        'connecting',
        'error',
        'maintenance',
        'suspended',
        'expired'
    );
EXCEPTION
    WHEN duplicate_object THEN null;
END $$;

-- Tabla de Cuentas de Broker
CREATE TABLE IF NOT EXISTS broker_integration.broker_accounts (
    -- Identificadores
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    tenant_id UUID NOT NULL REFERENCES tenants.tenants(id) ON DELETE CASCADE,
    user_id UUID NOT NULL REFERENCES users.users(id) ON DELETE CASCADE,

    -- Broker info
    broker_type broker_integration.broker_type NOT NULL,
    broker_name VARCHAR(100) NOT NULL,                  -- "XM", "IC Markets"
    broker_server VARCHAR(255),                         -- Server name/address

    -- Cuenta
    account_type broker_integration.account_type NOT NULL DEFAULT 'demo',
    account_number VARCHAR(50) NOT NULL,
    account_name VARCHAR(100),

    -- Conexion
    connection_status broker_integration.connection_status NOT NULL DEFAULT 'disconnected',
    connection_provider VARCHAR(50),                    -- "metaapi", "direct"
    provider_account_id VARCHAR(100),                   -- ID en el proveedor

    -- Credenciales (encriptadas)
    login_encrypted TEXT,
    password_encrypted TEXT,
    investor_password_encrypted TEXT,
    api_token_encrypted TEXT,
    additional_credentials JSONB DEFAULT '{}'::JSONB,

    -- Configuracion
    leverage INTEGER,
    currency VARCHAR(10) NOT NULL DEFAULT 'USD',
    timezone VARCHAR(50) DEFAULT 'UTC',

    -- Balance y equity
    balance DECIMAL(15, 2),
    equity DECIMAL(15, 2),
    margin DECIMAL(15, 2),
    free_margin DECIMAL(15, 2),
    margin_level DECIMAL(10, 2),

    -- Configuracion de trading
    enable_trading BOOLEAN NOT NULL DEFAULT FALSE,
    max_positions INTEGER,
    max_lot_size DECIMAL(10, 2),
    min_lot_size DECIMAL(10, 4) DEFAULT 0.01,
    lot_step DECIMAL(10, 4) DEFAULT 0.01,

    -- Permisos
    allow_copy_trading BOOLEAN NOT NULL DEFAULT FALSE,
    allow_signals BOOLEAN NOT NULL DEFAULT TRUE,
    allow_auto_trading BOOLEAN NOT NULL DEFAULT FALSE,

    -- Restricciones
    allowed_symbols VARCHAR(20)[],                      -- NULL = todos
    blocked_symbols VARCHAR(20)[],
    allowed_directions VARCHAR(10)[],                   -- ['long', 'short']
    trading_hours JSONB,

    -- Estado
    is_active BOOLEAN NOT NULL DEFAULT TRUE,
    is_default BOOLEAN NOT NULL DEFAULT FALSE,
    is_verified BOOLEAN NOT NULL DEFAULT FALSE,

    -- Ultima sincronizacion
    last_sync_at TIMESTAMPTZ,
    last_sync_error TEXT,
    sync_interval_seconds INTEGER DEFAULT 60,

    -- Estadisticas
    total_trades INTEGER NOT NULL DEFAULT 0,
    open_positions INTEGER NOT NULL DEFAULT 0,
    total_profit DECIMAL(15, 2) NOT NULL DEFAULT 0,
    today_profit DECIMAL(15, 2) NOT NULL DEFAULT 0,

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

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

    -- Constraints
    CONSTRAINT broker_accounts_unique UNIQUE (tenant_id, broker_type, account_number)
);

COMMENT ON TABLE broker_integration.broker_accounts IS
'Cuentas de broker conectadas para trading real o demo';

COMMENT ON COLUMN broker_integration.broker_accounts.enable_trading IS
'Si TRUE, permite ejecutar ordenes reales en esta cuenta';

-- Indices
CREATE INDEX IF NOT EXISTS idx_broker_accounts_tenant
    ON broker_integration.broker_accounts(tenant_id);

CREATE INDEX IF NOT EXISTS idx_broker_accounts_user
    ON broker_integration.broker_accounts(user_id);

CREATE INDEX IF NOT EXISTS idx_broker_accounts_type
    ON broker_integration.broker_accounts(broker_type);

CREATE INDEX IF NOT EXISTS idx_broker_accounts_status
    ON broker_integration.broker_accounts(connection_status);

CREATE INDEX IF NOT EXISTS idx_broker_accounts_active
    ON broker_integration.broker_accounts(user_id, is_active, connection_status)
    WHERE is_active = TRUE;

CREATE INDEX IF NOT EXISTS idx_broker_accounts_default
    ON broker_integration.broker_accounts(user_id, is_default)
    WHERE is_default = TRUE;

CREATE INDEX IF NOT EXISTS idx_broker_accounts_sync
    ON broker_integration.broker_accounts(last_sync_at)
    WHERE is_active = TRUE AND connection_status = 'connected';

-- Funcion de timestamp
CREATE OR REPLACE FUNCTION broker_integration.update_broker_timestamp()
RETURNS TRIGGER AS $$
BEGIN
    NEW.updated_at := NOW();
    RETURN NEW;
END;
$$ LANGUAGE plpgsql;

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

-- Trigger para asegurar solo una cuenta default
CREATE OR REPLACE FUNCTION broker_integration.ensure_single_default_broker()
RETURNS TRIGGER AS $$
BEGIN
    IF NEW.is_default = TRUE THEN
        UPDATE broker_integration.broker_accounts
        SET is_default = FALSE
        WHERE user_id = NEW.user_id
          AND id != NEW.id
          AND is_default = TRUE;
    END IF;
    RETURN NEW;
END;
$$ LANGUAGE plpgsql;

DROP TRIGGER IF EXISTS broker_account_single_default ON broker_integration.broker_accounts;
CREATE TRIGGER broker_account_single_default
    BEFORE INSERT OR UPDATE OF is_default ON broker_integration.broker_accounts
    FOR EACH ROW
    WHEN (NEW.is_default = TRUE)
    EXECUTE FUNCTION broker_integration.ensure_single_default_broker();

-- Vista de cuentas activas
CREATE OR REPLACE VIEW broker_integration.v_active_accounts AS
SELECT
    id,
    user_id,
    broker_type,
    broker_name,
    account_type,
    account_number,
    connection_status,
    balance,
    equity,
    leverage,
    currency,
    open_positions,
    is_default,
    last_sync_at
FROM broker_integration.broker_accounts
WHERE is_active = TRUE
ORDER BY is_default DESC, broker_name;

-- RLS Policies
ALTER TABLE broker_integration.broker_accounts ENABLE ROW LEVEL SECURITY;

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

CREATE POLICY broker_accounts_user ON broker_integration.broker_accounts
    FOR ALL
    USING (user_id = current_setting('app.current_user_id', true)::UUID);

-- Grants
GRANT USAGE ON SCHEMA broker_integration TO trading_app;
GRANT SELECT, INSERT, UPDATE, DELETE ON broker_integration.broker_accounts TO trading_app;
GRANT SELECT ON broker_integration.broker_accounts TO trading_readonly;
GRANT SELECT ON broker_integration.v_active_accounts TO trading_app;
