-- ============================================================================
-- OrbiQuant IA - Esquema INVESTMENT
-- ============================================================================
-- Archivo: 04_investment_schema.sql
-- Descripción: Cuentas de inversión, productos y gestión de portafolios
-- Fecha: 2025-12-05
-- ============================================================================

SET search_path TO investment;

-- ============================================================================
-- TIPOS ENUMERADOS
-- ============================================================================

CREATE TYPE product_type_enum AS ENUM (
    'fixed_return',      -- Rendimiento fijo objetivo (ej: 5% mensual)
    'variable_return',   -- Rendimiento variable con reparto de utilidades
    'long_term_portfolio' -- Cartera de largo plazo (acciones, ETFs)
);

CREATE TYPE account_status_enum AS ENUM (
    'pending_kyc',    -- Esperando verificación KYC
    'pending_deposit', -- Esperando depósito inicial
    'active',         -- Cuenta activa operando
    'paused',         -- Pausada por usuario o admin
    'suspended',      -- Suspendida por compliance
    'closed'          -- Cerrada
);

CREATE TYPE fee_type_enum AS ENUM (
    'management',     -- Comisión de administración
    'performance',    -- Comisión de rendimiento
    'deposit',        -- Comisión de depósito
    'withdrawal',     -- Comisión de retiro
    'subscription'    -- Comisión de suscripción
);

-- ============================================================================
-- TABLA: products
-- Descripción: Productos de inversión disponibles
-- ============================================================================
CREATE TABLE IF NOT EXISTS products (
    id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),

    -- Identificación
    name VARCHAR(100) NOT NULL,
    slug VARCHAR(100) NOT NULL UNIQUE,
    description TEXT,
    short_description VARCHAR(500),

    -- Tipo y riesgo
    product_type product_type_enum NOT NULL,
    risk_profile public.risk_profile_enum NOT NULL,

    -- Objetivos
    target_monthly_return DECIMAL(5,2),   -- % objetivo mensual
    max_drawdown DECIMAL(5,2),            -- % máximo drawdown permitido
    guaranteed_return BOOLEAN DEFAULT FALSE, -- SIEMPRE FALSE para cumplimiento

    -- Comisiones
    management_fee_percent DECIMAL(5,2) DEFAULT 0, -- % anual sobre AUM
    performance_fee_percent DECIMAL(5,2) DEFAULT 0, -- % sobre ganancias
    profit_share_platform DECIMAL(5,2),    -- % de utilidades para plataforma (ej: 50)
    profit_share_client DECIMAL(5,2),      -- % de utilidades para cliente (ej: 50)

    -- Límites
    min_investment DECIMAL(15,2) DEFAULT 100,
    max_investment DECIMAL(15,2),
    min_investment_period_days INT DEFAULT 30,

    -- Restricciones
    requires_kyc_level INT DEFAULT 1,
    allowed_risk_profiles public.risk_profile_enum[],

    -- Bot/Agente asociado
    default_bot_id UUID REFERENCES trading.bots(id),

    -- Estado
    is_active BOOLEAN DEFAULT TRUE,
    is_visible BOOLEAN DEFAULT TRUE,

    -- Metadata
    terms_url TEXT,
    risk_disclosure_url TEXT,

    created_at TIMESTAMPTZ DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMPTZ DEFAULT CURRENT_TIMESTAMP
);

CREATE INDEX idx_products_slug ON products(slug);
CREATE INDEX idx_products_type ON products(product_type);
CREATE INDEX idx_products_risk ON products(risk_profile);

-- ============================================================================
-- TABLA: accounts
-- Descripción: Cuentas de inversión de usuarios
-- ============================================================================
CREATE TABLE IF NOT EXISTS accounts (
    id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),

    -- Referencias
    user_id UUID NOT NULL REFERENCES auth.users(id) ON DELETE RESTRICT,
    product_id UUID NOT NULL REFERENCES products(id),
    bot_id UUID REFERENCES trading.bots(id),

    -- Identificación
    account_number VARCHAR(20) NOT NULL UNIQUE, -- OQ-INV-XXXXXX
    name VARCHAR(100),

    -- Moneda
    currency CHAR(3) DEFAULT 'USD',

    -- Balances
    initial_deposit DECIMAL(15,2) NOT NULL,
    current_balance DECIMAL(15,2) NOT NULL,
    available_balance DECIMAL(15,2) NOT NULL, -- Balance disponible para retiro
    reserved_balance DECIMAL(15,2) DEFAULT 0, -- En operaciones abiertas

    -- Rendimiento acumulado
    total_profit DECIMAL(15,2) DEFAULT 0,
    total_fees_paid DECIMAL(15,2) DEFAULT 0,
    total_deposits DECIMAL(15,2) DEFAULT 0,
    total_withdrawals DECIMAL(15,2) DEFAULT 0,

    -- Métricas de rendimiento
    total_return_percent DECIMAL(8,4) DEFAULT 0,
    monthly_return_percent DECIMAL(8,4) DEFAULT 0,
    max_drawdown_percent DECIMAL(5,2) DEFAULT 0,
    sharpe_ratio DECIMAL(5,2),

    -- Estado
    status account_status_enum DEFAULT 'pending_deposit',
    activated_at TIMESTAMPTZ,
    paused_at TIMESTAMPTZ,
    closed_at TIMESTAMPTZ,

    -- Configuración del usuario
    auto_compound BOOLEAN DEFAULT TRUE, -- Reinvertir ganancias
    max_drawdown_override DECIMAL(5,2), -- Override del drawdown máximo
    pause_on_drawdown BOOLEAN DEFAULT TRUE, -- Pausar si alcanza DD máximo

    -- Aceptación de términos
    terms_accepted_at TIMESTAMPTZ,
    risk_disclosure_accepted_at TIMESTAMPTZ,

    created_at TIMESTAMPTZ DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMPTZ DEFAULT CURRENT_TIMESTAMP
);

CREATE INDEX idx_accounts_user ON accounts(user_id);
CREATE INDEX idx_accounts_product ON accounts(product_id);
CREATE INDEX idx_accounts_status ON accounts(status);
CREATE INDEX idx_accounts_number ON accounts(account_number);

-- ============================================================================
-- TABLA: account_transactions
-- Descripción: Movimientos en cuentas de inversión
-- ============================================================================
CREATE TYPE account_transaction_type AS ENUM (
    'deposit',
    'withdrawal',
    'profit',
    'loss',
    'fee',
    'adjustment',
    'transfer_in',
    'transfer_out'
);

CREATE TABLE IF NOT EXISTS account_transactions (
    id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
    account_id UUID NOT NULL REFERENCES accounts(id) ON DELETE RESTRICT,

    -- Tipo y monto
    transaction_type account_transaction_type NOT NULL,
    amount DECIMAL(15,2) NOT NULL, -- Positivo o negativo según tipo
    currency CHAR(3) DEFAULT 'USD',

    -- Balances
    balance_before DECIMAL(15,2) NOT NULL,
    balance_after DECIMAL(15,2) NOT NULL,

    -- Referencia externa
    reference_type VARCHAR(50), -- 'wallet_transaction', 'position', 'fee_charge'
    reference_id UUID,

    -- Descripción
    description TEXT,

    -- Estado
    status VARCHAR(20) DEFAULT 'completed', -- 'pending', 'completed', 'cancelled'
    processed_at TIMESTAMPTZ DEFAULT CURRENT_TIMESTAMP,

    created_at TIMESTAMPTZ DEFAULT CURRENT_TIMESTAMP
);

CREATE INDEX idx_account_tx_account ON account_transactions(account_id);
CREATE INDEX idx_account_tx_type ON account_transactions(transaction_type);
CREATE INDEX idx_account_tx_created ON account_transactions(created_at DESC);

-- ============================================================================
-- TABLA: performance_snapshots
-- Descripción: Snapshots periódicos de rendimiento
-- ============================================================================
CREATE TABLE IF NOT EXISTS performance_snapshots (
    id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
    account_id UUID NOT NULL REFERENCES accounts(id) ON DELETE CASCADE,

    -- Período
    snapshot_date DATE NOT NULL,
    period_type VARCHAR(20) NOT NULL, -- 'daily', 'weekly', 'monthly'

    -- Valores
    opening_balance DECIMAL(15,2) NOT NULL,
    closing_balance DECIMAL(15,2) NOT NULL,
    deposits DECIMAL(15,2) DEFAULT 0,
    withdrawals DECIMAL(15,2) DEFAULT 0,
    profit_loss DECIMAL(15,2) NOT NULL,
    fees DECIMAL(15,2) DEFAULT 0,

    -- Métricas
    return_percent DECIMAL(8,4),
    drawdown_percent DECIMAL(5,2),

    -- Trading stats
    total_trades INT DEFAULT 0,
    winning_trades INT DEFAULT 0,
    positions_opened INT DEFAULT 0,
    positions_closed INT DEFAULT 0,

    created_at TIMESTAMPTZ DEFAULT CURRENT_TIMESTAMP,

    UNIQUE(account_id, snapshot_date, period_type)
);

CREATE INDEX idx_perf_snapshots_account ON performance_snapshots(account_id);
CREATE INDEX idx_perf_snapshots_date ON performance_snapshots(snapshot_date DESC);

-- ============================================================================
-- TABLA: profit_distributions
-- Descripción: Distribución de utilidades (para cuentas con profit sharing)
-- ============================================================================
CREATE TABLE IF NOT EXISTS profit_distributions (
    id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
    account_id UUID NOT NULL REFERENCES accounts(id) ON DELETE RESTRICT,

    -- Período
    period_start DATE NOT NULL,
    period_end DATE NOT NULL,

    -- Cálculo
    gross_profit DECIMAL(15,2) NOT NULL,
    management_fee DECIMAL(15,2) DEFAULT 0,
    net_profit DECIMAL(15,2) NOT NULL,

    -- Distribución
    platform_share_percent DECIMAL(5,2) NOT NULL,
    client_share_percent DECIMAL(5,2) NOT NULL,
    platform_amount DECIMAL(15,2) NOT NULL,
    client_amount DECIMAL(15,2) NOT NULL,

    -- Estado
    status VARCHAR(20) DEFAULT 'pending', -- 'pending', 'approved', 'distributed', 'cancelled'
    distributed_at TIMESTAMPTZ,
    approved_by UUID REFERENCES auth.users(id),

    -- Referencia de pago
    payment_reference VARCHAR(100),

    created_at TIMESTAMPTZ DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMPTZ DEFAULT CURRENT_TIMESTAMP
);

CREATE INDEX idx_profit_dist_account ON profit_distributions(account_id);
CREATE INDEX idx_profit_dist_period ON profit_distributions(period_end DESC);
CREATE INDEX idx_profit_dist_status ON profit_distributions(status);

-- ============================================================================
-- TABLA: deposit_requests
-- Descripción: Solicitudes de depósito a cuentas de inversión
-- ============================================================================
CREATE TABLE IF NOT EXISTS deposit_requests (
    id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
    account_id UUID NOT NULL REFERENCES accounts(id) ON DELETE RESTRICT,
    user_id UUID NOT NULL REFERENCES auth.users(id),

    amount DECIMAL(15,2) NOT NULL,
    currency CHAR(3) DEFAULT 'USD',

    -- Origen
    source_type VARCHAR(50) NOT NULL, -- 'wallet', 'external'
    source_wallet_id UUID, -- Referencia a financial.wallets

    -- Estado
    status VARCHAR(20) DEFAULT 'pending', -- 'pending', 'approved', 'completed', 'rejected'
    processed_at TIMESTAMPTZ,
    processed_by UUID REFERENCES auth.users(id),
    rejection_reason TEXT,

    -- Transacción resultante
    transaction_id UUID REFERENCES account_transactions(id),

    created_at TIMESTAMPTZ DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMPTZ DEFAULT CURRENT_TIMESTAMP
);

CREATE INDEX idx_deposit_requests_account ON deposit_requests(account_id);
CREATE INDEX idx_deposit_requests_user ON deposit_requests(user_id);
CREATE INDEX idx_deposit_requests_status ON deposit_requests(status);

-- ============================================================================
-- TABLA: withdrawal_requests
-- Descripción: Solicitudes de retiro de cuentas de inversión
-- ============================================================================
CREATE TABLE IF NOT EXISTS withdrawal_requests (
    id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
    account_id UUID NOT NULL REFERENCES accounts(id) ON DELETE RESTRICT,
    user_id UUID NOT NULL REFERENCES auth.users(id),

    amount DECIMAL(15,2) NOT NULL,
    currency CHAR(3) DEFAULT 'USD',

    -- Destino
    destination_type VARCHAR(50) NOT NULL, -- 'wallet', 'bank_transfer'
    destination_wallet_id UUID,

    -- Estado
    status VARCHAR(20) DEFAULT 'pending', -- 'pending', 'processing', 'completed', 'rejected'
    processed_at TIMESTAMPTZ,
    processed_by UUID REFERENCES auth.users(id),
    rejection_reason TEXT,

    -- Comisiones
    fee_amount DECIMAL(10,2) DEFAULT 0,
    net_amount DECIMAL(15,2),

    -- Transacción resultante
    transaction_id UUID REFERENCES account_transactions(id),

    created_at TIMESTAMPTZ DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMPTZ DEFAULT CURRENT_TIMESTAMP
);

CREATE INDEX idx_withdrawal_requests_account ON withdrawal_requests(account_id);
CREATE INDEX idx_withdrawal_requests_user ON withdrawal_requests(user_id);
CREATE INDEX idx_withdrawal_requests_status ON withdrawal_requests(status);

-- ============================================================================
-- TABLA: bot_assignments
-- Descripción: Asignación de bots a cuentas de inversión
-- ============================================================================
CREATE TABLE IF NOT EXISTS bot_assignments (
    id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
    account_id UUID NOT NULL REFERENCES accounts(id) ON DELETE CASCADE,
    bot_id UUID NOT NULL REFERENCES trading.bots(id),

    -- Estado
    is_active BOOLEAN DEFAULT TRUE,
    assigned_at TIMESTAMPTZ DEFAULT CURRENT_TIMESTAMP,
    deactivated_at TIMESTAMPTZ,

    -- Razón del cambio
    assignment_reason TEXT,
    deactivation_reason TEXT,

    -- Usuario que asignó
    assigned_by UUID REFERENCES auth.users(id), -- NULL = automático

    created_at TIMESTAMPTZ DEFAULT CURRENT_TIMESTAMP
);

CREATE INDEX idx_bot_assignments_account ON bot_assignments(account_id);
CREATE INDEX idx_bot_assignments_bot ON bot_assignments(bot_id);
CREATE INDEX idx_bot_assignments_active ON bot_assignments(is_active) WHERE is_active = TRUE;

-- ============================================================================
-- TRIGGERS
-- ============================================================================

CREATE TRIGGER update_products_updated_at
    BEFORE UPDATE ON products
    FOR EACH ROW
    EXECUTE FUNCTION public.update_updated_at_column();

CREATE TRIGGER update_accounts_updated_at
    BEFORE UPDATE ON accounts
    FOR EACH ROW
    EXECUTE FUNCTION public.update_updated_at_column();

CREATE TRIGGER update_deposit_requests_updated_at
    BEFORE UPDATE ON deposit_requests
    FOR EACH ROW
    EXECUTE FUNCTION public.update_updated_at_column();

CREATE TRIGGER update_withdrawal_requests_updated_at
    BEFORE UPDATE ON withdrawal_requests
    FOR EACH ROW
    EXECUTE FUNCTION public.update_updated_at_column();

CREATE TRIGGER update_profit_distributions_updated_at
    BEFORE UPDATE ON profit_distributions
    FOR EACH ROW
    EXECUTE FUNCTION public.update_updated_at_column();

-- ============================================================================
-- FUNCIÓN: Generar número de cuenta
-- ============================================================================
CREATE OR REPLACE FUNCTION generate_account_number()
RETURNS TRIGGER AS $$
DECLARE
    seq_num INT;
BEGIN
    SELECT COALESCE(MAX(CAST(SUBSTRING(account_number FROM 8) AS INT)), 0) + 1
    INTO seq_num
    FROM investment.accounts;

    NEW.account_number := 'OQ-INV-' || LPAD(seq_num::TEXT, 6, '0');
    RETURN NEW;
END;
$$ LANGUAGE plpgsql;

CREATE TRIGGER set_account_number
    BEFORE INSERT ON accounts
    FOR EACH ROW
    WHEN (NEW.account_number IS NULL)
    EXECUTE FUNCTION generate_account_number();
