-- ===========================================
-- MECANICAS DIESEL - Funciones RLS Multi-Tenant
-- ===========================================
-- Funciones para Row-Level Security

-- Función para obtener el tenant_id actual de la sesión
CREATE OR REPLACE FUNCTION get_current_tenant_id()
RETURNS UUID AS $$
BEGIN
    RETURN NULLIF(current_setting('app.current_tenant_id', true), '')::UUID;
EXCEPTION
    WHEN OTHERS THEN
        RETURN NULL;
END;
$$ LANGUAGE plpgsql STABLE SECURITY DEFINER;

COMMENT ON FUNCTION get_current_tenant_id() IS 'Obtiene el tenant_id de la sesión actual para RLS';

-- Función para establecer el tenant_id en la sesión
CREATE OR REPLACE FUNCTION set_current_tenant_id(p_tenant_id UUID)
RETURNS VOID AS $$
BEGIN
    PERFORM set_config('app.current_tenant_id', p_tenant_id::TEXT, false);
END;
$$ LANGUAGE plpgsql SECURITY DEFINER;

COMMENT ON FUNCTION set_current_tenant_id(UUID) IS 'Establece el tenant_id para la sesión actual';

-- Función para obtener el user_id actual
CREATE OR REPLACE FUNCTION get_current_user_id()
RETURNS UUID AS $$
BEGIN
    RETURN NULLIF(current_setting('app.current_user_id', true), '')::UUID;
EXCEPTION
    WHEN OTHERS THEN
        RETURN NULL;
END;
$$ LANGUAGE plpgsql STABLE SECURITY DEFINER;

-- Trigger function para updated_at automático
CREATE OR REPLACE FUNCTION trigger_set_updated_at()
RETURNS TRIGGER AS $$
BEGIN
    NEW.updated_at = NOW();
    RETURN NEW;
END;
$$ LANGUAGE plpgsql;

COMMENT ON FUNCTION trigger_set_updated_at() IS 'Actualiza automáticamente updated_at';

-- Trigger function para created_by automático
CREATE OR REPLACE FUNCTION trigger_set_created_by()
RETURNS TRIGGER AS $$
BEGIN
    IF NEW.created_by IS NULL THEN
        NEW.created_by = get_current_user_id();
    END IF;
    RETURN NEW;
END;
$$ LANGUAGE plpgsql;

-- Macro para crear políticas RLS completas
-- Uso: SELECT create_tenant_rls_policies('schema_name', 'table_name');
CREATE OR REPLACE FUNCTION create_tenant_rls_policies(
    p_schema TEXT,
    p_table TEXT,
    p_tenant_column TEXT DEFAULT 'tenant_id'
)
RETURNS VOID AS $$
DECLARE
    v_full_table TEXT;
BEGIN
    v_full_table := p_schema || '.' || p_table;

    -- Habilitar RLS
    EXECUTE format('ALTER TABLE %I.%I ENABLE ROW LEVEL SECURITY', p_schema, p_table);

    -- Política SELECT
    EXECUTE format(
        'CREATE POLICY %I ON %I.%I FOR SELECT USING (%I = get_current_tenant_id())',
        p_table || '_select_policy', p_schema, p_table, p_tenant_column
    );

    -- Política INSERT
    EXECUTE format(
        'CREATE POLICY %I ON %I.%I FOR INSERT WITH CHECK (%I = get_current_tenant_id())',
        p_table || '_insert_policy', p_schema, p_table, p_tenant_column
    );

    -- Política UPDATE
    EXECUTE format(
        'CREATE POLICY %I ON %I.%I FOR UPDATE USING (%I = get_current_tenant_id()) WITH CHECK (%I = get_current_tenant_id())',
        p_table || '_update_policy', p_schema, p_table, p_tenant_column, p_tenant_column
    );

    -- Política DELETE
    EXECUTE format(
        'CREATE POLICY %I ON %I.%I FOR DELETE USING (%I = get_current_tenant_id())',
        p_table || '_delete_policy', p_schema, p_table, p_tenant_column
    );

    RAISE NOTICE 'RLS policies created for %.%', p_schema, p_table;
END;
$$ LANGUAGE plpgsql;

COMMENT ON FUNCTION create_tenant_rls_policies(TEXT, TEXT, TEXT) IS 'Crea políticas RLS completas (SELECT, INSERT, UPDATE, DELETE) para una tabla';
