-- ============================================================================
-- Schema: core_shared
-- Descripcion: Funciones y tipos compartidos entre todos los modulos
-- Proyecto: ERP Core
-- Autor: Database-Agent
-- Fecha: 2025-12-06
-- ============================================================================

-- Crear schema
CREATE SCHEMA IF NOT EXISTS core_shared;

COMMENT ON SCHEMA core_shared IS 'Funciones, tipos y utilidades compartidas entre modulos';

-- ============================================================================
-- FUNCIONES DE AUDITORIA
-- ============================================================================

-- Funcion para actualizar updated_at automaticamente
CREATE OR REPLACE FUNCTION core_shared.set_updated_at()
RETURNS TRIGGER AS $$
BEGIN
    NEW.updated_at = NOW();
    RETURN NEW;
END;
$$ LANGUAGE plpgsql;

COMMENT ON FUNCTION core_shared.set_updated_at() IS
'Trigger function para actualizar automaticamente el campo updated_at en cada UPDATE';

-- Funcion para establecer tenant_id desde contexto
CREATE OR REPLACE FUNCTION core_shared.set_tenant_id()
RETURNS TRIGGER AS $$
BEGIN
    IF NEW.tenant_id IS NULL THEN
        NEW.tenant_id = current_setting('app.current_tenant_id', true)::uuid;
    END IF;
    RETURN NEW;
END;
$$ LANGUAGE plpgsql;

COMMENT ON FUNCTION core_shared.set_tenant_id() IS
'Trigger function para establecer tenant_id automaticamente desde el contexto de sesion';

-- Funcion para establecer created_by desde contexto
CREATE OR REPLACE FUNCTION core_shared.set_created_by()
RETURNS TRIGGER AS $$
BEGIN
    IF NEW.created_by IS NULL THEN
        NEW.created_by = current_setting('app.current_user_id', true)::uuid;
    END IF;
    RETURN NEW;
END;
$$ LANGUAGE plpgsql;

COMMENT ON FUNCTION core_shared.set_created_by() IS
'Trigger function para establecer created_by automaticamente desde el contexto de sesion';

-- Funcion para establecer updated_by desde contexto
CREATE OR REPLACE FUNCTION core_shared.set_updated_by()
RETURNS TRIGGER AS $$
BEGIN
    NEW.updated_by = current_setting('app.current_user_id', true)::uuid;
    RETURN NEW;
END;
$$ LANGUAGE plpgsql;

COMMENT ON FUNCTION core_shared.set_updated_by() IS
'Trigger function para establecer updated_by automaticamente desde el contexto de sesion';

-- ============================================================================
-- FUNCIONES DE CONTEXTO
-- ============================================================================

-- Obtener tenant_id actual del contexto
CREATE OR REPLACE FUNCTION core_shared.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;

COMMENT ON FUNCTION core_shared.get_current_tenant_id() IS
'Obtiene el ID del tenant actual desde el contexto de sesion';

-- Obtener user_id actual del contexto
CREATE OR REPLACE FUNCTION core_shared.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;

COMMENT ON FUNCTION core_shared.get_current_user_id() IS
'Obtiene el ID del usuario actual desde el contexto de sesion';

-- ============================================================================
-- FUNCIONES DE UTILIDAD
-- ============================================================================

-- Generar slug desde texto
CREATE OR REPLACE FUNCTION core_shared.generate_slug(input_text TEXT)
RETURNS TEXT AS $$
BEGIN
    RETURN LOWER(
        REGEXP_REPLACE(
            REGEXP_REPLACE(
                TRIM(input_text),
                '[^a-zA-Z0-9\s-]', '', 'g'
            ),
            '\s+', '-', 'g'
        )
    );
END;
$$ LANGUAGE plpgsql IMMUTABLE;

COMMENT ON FUNCTION core_shared.generate_slug(TEXT) IS
'Genera un slug URL-friendly desde un texto';

-- Validar formato de email
CREATE OR REPLACE FUNCTION core_shared.is_valid_email(email TEXT)
RETURNS BOOLEAN AS $$
BEGIN
    RETURN email ~* '^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}$';
END;
$$ LANGUAGE plpgsql IMMUTABLE;

COMMENT ON FUNCTION core_shared.is_valid_email(TEXT) IS
'Valida si un texto tiene formato de email valido';

-- Validar formato de RFC mexicano
CREATE OR REPLACE FUNCTION core_shared.is_valid_rfc(rfc TEXT)
RETURNS BOOLEAN AS $$
BEGIN
    -- RFC persona moral: 3 letras + 6 digitos + 3 caracteres
    -- RFC persona fisica: 4 letras + 6 digitos + 3 caracteres
    RETURN rfc ~* '^[A-Z&Ñ]{3,4}[0-9]{6}[A-Z0-9]{3}$';
END;
$$ LANGUAGE plpgsql IMMUTABLE;

COMMENT ON FUNCTION core_shared.is_valid_rfc(TEXT) IS
'Valida si un texto tiene formato de RFC mexicano valido';

-- ============================================================================
-- GRANT PERMISOS
-- ============================================================================

-- Permitir uso del schema a todos los roles de la aplicacion
GRANT USAGE ON SCHEMA core_shared TO PUBLIC;
GRANT EXECUTE ON ALL FUNCTIONS IN SCHEMA core_shared TO PUBLIC;

-- ============================================================================
-- FIN
-- ============================================================================
