-- ============================================================================
-- SCHEMA: financial
-- TABLE: wallets
-- DESCRIPTION: Sistema de Wallet Virtual con creditos USD equivalentes
-- VERSION: 1.0.0
-- CREATED: 2026-01-10
-- ============================================================================

-- Crear schema si no existe
CREATE SCHEMA IF NOT EXISTS financial;

-- Enum para estado de wallet
DO $$ BEGIN
    CREATE TYPE financial.wallet_status AS ENUM (
        'active',       -- Wallet activo y operativo
        'frozen',       -- Congelado temporalmente (investigacion)
        'suspended',    -- Suspendido por violacion de terminos
        'closed'        -- Cerrado permanentemente
    );
EXCEPTION
    WHEN duplicate_object THEN null;
END $$;

-- Tabla principal de Wallets
CREATE TABLE IF NOT EXISTS financial.wallets (
    -- Identificadores
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    tenant_id UUID NOT NULL,
    user_id UUID NOT NULL,

    -- Saldos en creditos (equivalente USD, no dinero real)
    balance DECIMAL(15, 4) NOT NULL DEFAULT 0
        CHECK (balance >= 0),
    reserved DECIMAL(15, 4) NOT NULL DEFAULT 0
        CHECK (reserved >= 0),

    -- Totales acumulados (para auditoria)
    total_credited DECIMAL(15, 4) NOT NULL DEFAULT 0,
    total_debited DECIMAL(15, 4) NOT NULL DEFAULT 0,

    -- Creditos promocionales (separados del balance principal)
    promo_balance DECIMAL(15, 4) NOT NULL DEFAULT 0
        CHECK (promo_balance >= 0),
    promo_expiry TIMESTAMPTZ,

    -- Configuracion
    currency VARCHAR(3) NOT NULL DEFAULT 'USD',
    status financial.wallet_status NOT NULL DEFAULT 'active',

    -- Limites operacionales
    daily_spend_limit DECIMAL(15, 4) DEFAULT 1000.0000,
    monthly_spend_limit DECIMAL(15, 4) DEFAULT 10000.0000,
    single_transaction_limit DECIMAL(15, 4) DEFAULT 500.0000,

    -- Tracking de uso
    daily_spent DECIMAL(15, 4) NOT NULL DEFAULT 0,
    monthly_spent DECIMAL(15, 4) NOT NULL DEFAULT 0,
    last_daily_reset DATE DEFAULT CURRENT_DATE,
    last_monthly_reset DATE DEFAULT DATE_TRUNC('month', CURRENT_DATE)::DATE,

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

    -- Constraints
    CONSTRAINT wallets_total_balance_check CHECK (balance + reserved >= 0),
    CONSTRAINT wallets_unique_user UNIQUE (tenant_id, user_id)
);

-- Columna calculada para balance total disponible
COMMENT ON TABLE financial.wallets IS
'Wallet virtual con creditos USD equivalentes. No es dinero real.';

COMMENT ON COLUMN financial.wallets.balance IS
'Saldo disponible en creditos (1 credito = 1 USD equivalente)';

COMMENT ON COLUMN financial.wallets.reserved IS
'Creditos reservados para operaciones pendientes (ej: fondeo de agentes)';

COMMENT ON COLUMN financial.wallets.promo_balance IS
'Creditos promocionales separados del balance principal';

-- Indices
CREATE INDEX IF NOT EXISTS idx_wallets_tenant_id
    ON financial.wallets(tenant_id);

CREATE INDEX IF NOT EXISTS idx_wallets_user_id
    ON financial.wallets(user_id);

CREATE INDEX IF NOT EXISTS idx_wallets_status
    ON financial.wallets(status);

CREATE INDEX IF NOT EXISTS idx_wallets_created_at
    ON financial.wallets(created_at DESC);

-- Trigger para updated_at
CREATE OR REPLACE FUNCTION financial.update_wallet_timestamp()
RETURNS TRIGGER AS $$
BEGIN
    NEW.updated_at = NOW();
    RETURN NEW;
END;
$$ LANGUAGE plpgsql;

DROP TRIGGER IF EXISTS wallet_updated_at ON financial.wallets;
CREATE TRIGGER wallet_updated_at
    BEFORE UPDATE ON financial.wallets
    FOR EACH ROW
    EXECUTE FUNCTION financial.update_wallet_timestamp();

-- Funcion para resetear limites diarios/mensuales
CREATE OR REPLACE FUNCTION financial.reset_wallet_limits()
RETURNS TRIGGER AS $$
BEGIN
    -- Reset diario
    IF NEW.last_daily_reset < CURRENT_DATE THEN
        NEW.daily_spent := 0;
        NEW.last_daily_reset := CURRENT_DATE;
    END IF;

    -- Reset mensual
    IF NEW.last_monthly_reset < DATE_TRUNC('month', CURRENT_DATE)::DATE THEN
        NEW.monthly_spent := 0;
        NEW.last_monthly_reset := DATE_TRUNC('month', CURRENT_DATE)::DATE;
    END IF;

    RETURN NEW;
END;
$$ LANGUAGE plpgsql;

DROP TRIGGER IF EXISTS wallet_reset_limits ON financial.wallets;
CREATE TRIGGER wallet_reset_limits
    BEFORE UPDATE ON financial.wallets
    FOR EACH ROW
    EXECUTE FUNCTION financial.reset_wallet_limits();

-- RLS Policy para multi-tenancy
ALTER TABLE financial.wallets ENABLE ROW LEVEL SECURITY;

CREATE POLICY wallets_tenant_isolation ON financial.wallets
    FOR ALL
    USING (tenant_id = current_setting('app.current_tenant_id', true)::UUID);

-- Grants
GRANT SELECT, INSERT, UPDATE ON financial.wallets TO trading_app;
GRANT SELECT ON financial.wallets TO trading_readonly;
