-- =============================================================
-- ARCHIVO: 31-reports.sql
-- DESCRIPCION: Sistema de Reportes y Analytics
-- VERSION: 1.0.0
-- PROYECTO: ERP-Core
-- FECHA: 2026-01-26
-- MODULO: MGN-009 (Reports)
-- EPIC: EPIC-MGN-009-reports
-- =============================================================

-- =====================
-- SCHEMA: reports
-- =====================
CREATE SCHEMA IF NOT EXISTS reports;

-- =====================
-- ENUMS
-- =====================

-- Tipo de reporte
DO $$ BEGIN
    CREATE TYPE reports.report_type AS ENUM (
        'financial',
        'accounting',
        'tax',
        'management',
        'operational',
        'custom'
    );
EXCEPTION WHEN duplicate_object THEN NULL;
END $$;

-- Estado de ejecucion
DO $$ BEGIN
    CREATE TYPE reports.execution_status AS ENUM (
        'pending',
        'running',
        'completed',
        'failed',
        'cancelled'
    );
EXCEPTION WHEN duplicate_object THEN NULL;
END $$;

-- Formato de exportacion
DO $$ BEGIN
    CREATE TYPE reports.export_format AS ENUM (
        'pdf',
        'excel',
        'csv',
        'json',
        'html'
    );
EXCEPTION WHEN duplicate_object THEN NULL;
END $$;

-- Metodo de entrega
DO $$ BEGIN
    CREATE TYPE reports.delivery_method AS ENUM (
        'none',
        'email',
        'storage',
        'webhook'
    );
EXCEPTION WHEN duplicate_object THEN NULL;
END $$;

-- Tipo de widget
DO $$ BEGIN
    CREATE TYPE reports.widget_type AS ENUM (
        'kpi',
        'bar_chart',
        'line_chart',
        'pie_chart',
        'donut_chart',
        'gauge',
        'table',
        'map',
        'text'
    );
EXCEPTION WHEN duplicate_object THEN NULL;
END $$;

-- Tipo de parametro
DO $$ BEGIN
    CREATE TYPE reports.param_type AS ENUM (
        'string',
        'number',
        'date',
        'daterange',
        'boolean',
        'select',
        'multiselect',
        'entity'
    );
EXCEPTION WHEN duplicate_object THEN NULL;
END $$;

-- Operador de filtro
DO $$ BEGIN
    CREATE TYPE reports.filter_operator AS ENUM (
        'eq',
        'ne',
        'gt',
        'gte',
        'lt',
        'lte',
        'like',
        'ilike',
        'in',
        'not_in',
        'between',
        'is_null',
        'is_not_null'
    );
EXCEPTION WHEN duplicate_object THEN NULL;
END $$;

-- =====================
-- TABLA: reports.report_definitions
-- Definiciones de reportes
-- =====================
CREATE TABLE IF NOT EXISTS reports.report_definitions (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    tenant_id UUID NOT NULL REFERENCES auth.tenants(id) ON DELETE CASCADE,

    -- Identificacion
    code VARCHAR(50) NOT NULL,
    name VARCHAR(255) NOT NULL,
    description TEXT,
    category VARCHAR(100),
    report_type reports.report_type NOT NULL DEFAULT 'custom',

    -- Query
    base_query TEXT,
    query_function VARCHAR(255),
    is_sql_based BOOLEAN NOT NULL DEFAULT true,

    -- Parametros
    parameters_schema JSONB DEFAULT '[]',
    default_parameters JSONB DEFAULT '{}',

    -- Columnas
    columns_config JSONB NOT NULL DEFAULT '[]',
    totals_config JSONB DEFAULT '[]',

    -- Permisos
    required_permissions TEXT[] DEFAULT '{}',
    is_public BOOLEAN NOT NULL DEFAULT false,
    is_active BOOLEAN NOT NULL DEFAULT true,

    -- Audit
    created_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
    created_by UUID REFERENCES auth.users(id),

    UNIQUE(tenant_id, code)
);

-- Indices
CREATE INDEX IF NOT EXISTS idx_report_definitions_tenant ON reports.report_definitions(tenant_id);
CREATE INDEX IF NOT EXISTS idx_report_definitions_category ON reports.report_definitions(category);
CREATE INDEX IF NOT EXISTS idx_report_definitions_type ON reports.report_definitions(report_type);
CREATE INDEX IF NOT EXISTS idx_report_definitions_active ON reports.report_definitions(is_active) WHERE is_active = true;

-- =====================
-- TABLA: reports.report_executions
-- Historial de ejecuciones
-- =====================
CREATE TABLE IF NOT EXISTS reports.report_executions (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    tenant_id UUID NOT NULL REFERENCES auth.tenants(id) ON DELETE CASCADE,

    -- Relaciones
    report_definition_id UUID NOT NULL REFERENCES reports.report_definitions(id) ON DELETE CASCADE,
    executed_by UUID NOT NULL REFERENCES auth.users(id),

    -- Ejecucion
    status reports.execution_status NOT NULL DEFAULT 'pending',
    parameters JSONB DEFAULT '{}',

    -- Resultado
    result_data JSONB,
    result_summary JSONB,
    row_count INTEGER,
    export_format reports.export_format,
    file_path TEXT,
    file_size_bytes BIGINT,

    -- Timing
    started_at TIMESTAMPTZ,
    completed_at TIMESTAMPTZ,
    execution_time_ms INTEGER,

    -- Error
    error_message TEXT,
    error_details JSONB,

    -- Audit
    created_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP
);

-- Indices
CREATE INDEX IF NOT EXISTS idx_report_executions_tenant ON reports.report_executions(tenant_id);
CREATE INDEX IF NOT EXISTS idx_report_executions_definition ON reports.report_executions(report_definition_id);
CREATE INDEX IF NOT EXISTS idx_report_executions_user ON reports.report_executions(executed_by);
CREATE INDEX IF NOT EXISTS idx_report_executions_status ON reports.report_executions(status);
CREATE INDEX IF NOT EXISTS idx_report_executions_date ON reports.report_executions(created_at DESC);

-- =====================
-- TABLA: reports.report_schedules
-- Programacion de reportes
-- =====================
CREATE TABLE IF NOT EXISTS reports.report_schedules (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    tenant_id UUID NOT NULL REFERENCES auth.tenants(id) ON DELETE CASCADE,

    -- Relaciones
    report_definition_id UUID NOT NULL REFERENCES reports.report_definitions(id) ON DELETE CASCADE,

    -- Programacion
    name VARCHAR(255) NOT NULL,
    cron_expression VARCHAR(100) NOT NULL,
    timezone VARCHAR(100) NOT NULL DEFAULT 'America/Mexico_City',
    parameters JSONB DEFAULT '{}',

    -- Entrega
    delivery_method reports.delivery_method NOT NULL DEFAULT 'email',
    delivery_config JSONB DEFAULT '{}',
    export_format reports.export_format NOT NULL DEFAULT 'pdf',

    -- Estado
    is_active BOOLEAN NOT NULL DEFAULT true,
    last_run_at TIMESTAMPTZ,
    last_run_status reports.execution_status,
    next_run_at TIMESTAMPTZ,
    run_count INTEGER NOT NULL DEFAULT 0,

    -- Audit
    created_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
    created_by UUID REFERENCES auth.users(id)
);

-- Indices
CREATE INDEX IF NOT EXISTS idx_report_schedules_tenant ON reports.report_schedules(tenant_id);
CREATE INDEX IF NOT EXISTS idx_report_schedules_definition ON reports.report_schedules(report_definition_id);
CREATE INDEX IF NOT EXISTS idx_report_schedules_active ON reports.report_schedules(is_active) WHERE is_active = true;
CREATE INDEX IF NOT EXISTS idx_report_schedules_next_run ON reports.report_schedules(next_run_at) WHERE is_active = true;

-- =====================
-- TABLA: reports.report_recipients
-- Destinatarios de reportes programados
-- =====================
CREATE TABLE IF NOT EXISTS reports.report_recipients (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),

    -- Relaciones
    schedule_id UUID NOT NULL REFERENCES reports.report_schedules(id) ON DELETE CASCADE,
    user_id UUID REFERENCES auth.users(id) ON DELETE CASCADE,

    -- Destinatario externo
    email VARCHAR(255),
    name VARCHAR(255),

    -- Estado
    is_active BOOLEAN NOT NULL DEFAULT true,

    -- Audit
    created_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP
);

-- Indices
CREATE INDEX IF NOT EXISTS idx_report_recipients_schedule ON reports.report_recipients(schedule_id);
CREATE INDEX IF NOT EXISTS idx_report_recipients_user ON reports.report_recipients(user_id);

-- =====================
-- TABLA: reports.schedule_executions
-- Historial de ejecuciones programadas
-- =====================
CREATE TABLE IF NOT EXISTS reports.schedule_executions (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),

    -- Relaciones
    schedule_id UUID NOT NULL REFERENCES reports.report_schedules(id) ON DELETE CASCADE,
    execution_id UUID REFERENCES reports.report_executions(id) ON DELETE SET NULL,

    -- Resultado
    status reports.execution_status NOT NULL,
    recipients_notified INTEGER DEFAULT 0,
    delivery_status JSONB DEFAULT '{}',

    -- Error
    error_message TEXT,

    -- Audit
    executed_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP
);

-- Indices
CREATE INDEX IF NOT EXISTS idx_schedule_executions_schedule ON reports.schedule_executions(schedule_id);
CREATE INDEX IF NOT EXISTS idx_schedule_executions_date ON reports.schedule_executions(executed_at DESC);

-- =====================
-- TABLA: reports.dashboards
-- Dashboards personalizados
-- =====================
CREATE TABLE IF NOT EXISTS reports.dashboards (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    tenant_id UUID NOT NULL REFERENCES auth.tenants(id) ON DELETE CASCADE,

    -- Identificacion
    name VARCHAR(255) NOT NULL,
    description TEXT,
    slug VARCHAR(100),
    icon VARCHAR(50),

    -- Layout
    layout_config JSONB DEFAULT '{"columns": 12, "rowHeight": 80}',

    -- Estado
    is_default BOOLEAN NOT NULL DEFAULT false,
    is_public BOOLEAN NOT NULL DEFAULT false,
    is_active BOOLEAN NOT NULL DEFAULT true,

    -- Permisos
    owner_id UUID NOT NULL REFERENCES auth.users(id),
    allowed_roles TEXT[] DEFAULT '{}',

    -- Audit
    created_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP
);

-- Indices
CREATE INDEX IF NOT EXISTS idx_dashboards_tenant ON reports.dashboards(tenant_id);
CREATE INDEX IF NOT EXISTS idx_dashboards_owner ON reports.dashboards(owner_id);
CREATE INDEX IF NOT EXISTS idx_dashboards_default ON reports.dashboards(tenant_id, is_default) WHERE is_default = true;

-- =====================
-- TABLA: reports.dashboard_widgets
-- Widgets de dashboards
-- =====================
CREATE TABLE IF NOT EXISTS reports.dashboard_widgets (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),

    -- Relaciones
    dashboard_id UUID NOT NULL REFERENCES reports.dashboards(id) ON DELETE CASCADE,

    -- Identificacion
    title VARCHAR(255) NOT NULL,
    widget_type reports.widget_type NOT NULL,

    -- Posicion
    position_x INTEGER NOT NULL DEFAULT 0,
    position_y INTEGER NOT NULL DEFAULT 0,
    width INTEGER NOT NULL DEFAULT 3,
    height INTEGER NOT NULL DEFAULT 2,

    -- Configuracion
    config JSONB NOT NULL DEFAULT '{}',
    refresh_interval_seconds INTEGER DEFAULT 300,

    -- Estado
    is_active BOOLEAN NOT NULL DEFAULT true,
    sort_order INTEGER NOT NULL DEFAULT 0,

    -- Audit
    created_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP
);

-- Indices
CREATE INDEX IF NOT EXISTS idx_dashboard_widgets_dashboard ON reports.dashboard_widgets(dashboard_id);
CREATE INDEX IF NOT EXISTS idx_dashboard_widgets_type ON reports.dashboard_widgets(widget_type);

-- =====================
-- TABLA: reports.widget_queries
-- Queries de widgets
-- =====================
CREATE TABLE IF NOT EXISTS reports.widget_queries (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),

    -- Relaciones
    widget_id UUID NOT NULL REFERENCES reports.dashboard_widgets(id) ON DELETE CASCADE,

    -- Query
    name VARCHAR(100) NOT NULL,
    query_text TEXT,
    query_function VARCHAR(255),
    parameters JSONB DEFAULT '{}',

    -- Resultado
    result_mapping JSONB DEFAULT '{}',

    -- Cache
    cache_ttl_seconds INTEGER DEFAULT 300,
    last_cached_at TIMESTAMPTZ,

    -- Audit
    created_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP
);

-- Indices
CREATE INDEX IF NOT EXISTS idx_widget_queries_widget ON reports.widget_queries(widget_id);

-- =====================
-- TABLA: reports.custom_reports
-- Reportes personalizados por usuario
-- =====================
CREATE TABLE IF NOT EXISTS reports.custom_reports (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    tenant_id UUID NOT NULL REFERENCES auth.tenants(id) ON DELETE CASCADE,

    -- Propietario
    owner_id UUID NOT NULL REFERENCES auth.users(id) ON DELETE CASCADE,

    -- Base
    base_definition_id UUID REFERENCES reports.report_definitions(id) ON DELETE SET NULL,

    -- Identificacion
    name VARCHAR(255) NOT NULL,
    description TEXT,

    -- Configuracion personalizada
    custom_columns JSONB DEFAULT '[]',
    custom_filters JSONB DEFAULT '[]',
    custom_grouping JSONB DEFAULT '[]',
    custom_sorting JSONB DEFAULT '[]',

    -- Estado
    is_favorite BOOLEAN NOT NULL DEFAULT false,

    -- Audit
    created_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP
);

-- Indices
CREATE INDEX IF NOT EXISTS idx_custom_reports_tenant ON reports.custom_reports(tenant_id);
CREATE INDEX IF NOT EXISTS idx_custom_reports_owner ON reports.custom_reports(owner_id);
CREATE INDEX IF NOT EXISTS idx_custom_reports_favorite ON reports.custom_reports(owner_id, is_favorite) WHERE is_favorite = true;

-- =====================
-- TABLA: reports.data_model_entities
-- Modelo de datos para report builder
-- =====================
CREATE TABLE IF NOT EXISTS reports.data_model_entities (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),

    -- Identificacion
    name VARCHAR(100) NOT NULL UNIQUE,
    display_name VARCHAR(255) NOT NULL,
    description TEXT,

    -- Schema
    schema_name VARCHAR(100) NOT NULL,
    table_name VARCHAR(100) NOT NULL,

    -- Configuracion
    primary_key_column VARCHAR(100) NOT NULL DEFAULT 'id',
    tenant_column VARCHAR(100) DEFAULT 'tenant_id',
    is_multi_tenant BOOLEAN NOT NULL DEFAULT true,

    -- Estado
    is_active BOOLEAN NOT NULL DEFAULT true,

    -- Audit
    created_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP
);

-- Indices
CREATE INDEX IF NOT EXISTS idx_data_model_entities_name ON reports.data_model_entities(name);
CREATE INDEX IF NOT EXISTS idx_data_model_entities_schema ON reports.data_model_entities(schema_name, table_name);

-- =====================
-- TABLA: reports.data_model_fields
-- Campos del modelo de datos
-- =====================
CREATE TABLE IF NOT EXISTS reports.data_model_fields (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),

    -- Relaciones
    entity_id UUID NOT NULL REFERENCES reports.data_model_entities(id) ON DELETE CASCADE,

    -- Identificacion
    name VARCHAR(100) NOT NULL,
    display_name VARCHAR(255) NOT NULL,
    description TEXT,

    -- Tipo
    data_type VARCHAR(50) NOT NULL,
    is_nullable BOOLEAN NOT NULL DEFAULT true,

    -- Configuracion UI
    is_filterable BOOLEAN NOT NULL DEFAULT true,
    is_sortable BOOLEAN NOT NULL DEFAULT true,
    is_groupable BOOLEAN NOT NULL DEFAULT false,
    is_aggregatable BOOLEAN NOT NULL DEFAULT false,
    aggregation_functions TEXT[] DEFAULT '{}',

    -- Formato
    format_pattern VARCHAR(100),
    display_format VARCHAR(50),

    -- Estado
    is_active BOOLEAN NOT NULL DEFAULT true,
    sort_order INTEGER NOT NULL DEFAULT 0,

    -- Audit
    created_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,

    UNIQUE(entity_id, name)
);

-- Indices
CREATE INDEX IF NOT EXISTS idx_data_model_fields_entity ON reports.data_model_fields(entity_id);

-- =====================
-- TABLA: reports.data_model_relationships
-- Relaciones entre entidades del modelo
-- =====================
CREATE TABLE IF NOT EXISTS reports.data_model_relationships (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),

    -- Entidades
    source_entity_id UUID NOT NULL REFERENCES reports.data_model_entities(id) ON DELETE CASCADE,
    target_entity_id UUID NOT NULL REFERENCES reports.data_model_entities(id) ON DELETE CASCADE,

    -- Relacion
    name VARCHAR(100) NOT NULL,
    relationship_type VARCHAR(20) NOT NULL CHECK (relationship_type IN ('one_to_one', 'one_to_many', 'many_to_one', 'many_to_many')),

    -- Join
    source_column VARCHAR(100) NOT NULL,
    target_column VARCHAR(100) NOT NULL,
    join_condition TEXT,

    -- Estado
    is_active BOOLEAN NOT NULL DEFAULT true,

    -- Audit
    created_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,

    UNIQUE(source_entity_id, target_entity_id, name)
);

-- Indices
CREATE INDEX IF NOT EXISTS idx_data_model_relationships_source ON reports.data_model_relationships(source_entity_id);
CREATE INDEX IF NOT EXISTS idx_data_model_relationships_target ON reports.data_model_relationships(target_entity_id);

-- =====================
-- RLS POLICIES
-- =====================

-- Report Definitions
ALTER TABLE reports.report_definitions ENABLE ROW LEVEL SECURITY;
DROP POLICY IF EXISTS tenant_isolation_definitions ON reports.report_definitions;
CREATE POLICY tenant_isolation_definitions ON reports.report_definitions
    FOR ALL USING (tenant_id = current_setting('app.current_tenant_id', true)::uuid);

-- Report Executions
ALTER TABLE reports.report_executions ENABLE ROW LEVEL SECURITY;
DROP POLICY IF EXISTS tenant_isolation_executions ON reports.report_executions;
CREATE POLICY tenant_isolation_executions ON reports.report_executions
    FOR ALL USING (tenant_id = current_setting('app.current_tenant_id', true)::uuid);

-- Report Schedules
ALTER TABLE reports.report_schedules ENABLE ROW LEVEL SECURITY;
DROP POLICY IF EXISTS tenant_isolation_schedules ON reports.report_schedules;
CREATE POLICY tenant_isolation_schedules ON reports.report_schedules
    FOR ALL USING (tenant_id = current_setting('app.current_tenant_id', true)::uuid);

-- Dashboards
ALTER TABLE reports.dashboards ENABLE ROW LEVEL SECURITY;
DROP POLICY IF EXISTS tenant_isolation_dashboards ON reports.dashboards;
CREATE POLICY tenant_isolation_dashboards ON reports.dashboards
    FOR ALL USING (tenant_id = current_setting('app.current_tenant_id', true)::uuid);

-- Custom Reports
ALTER TABLE reports.custom_reports ENABLE ROW LEVEL SECURITY;
DROP POLICY IF EXISTS tenant_isolation_custom_reports ON reports.custom_reports;
CREATE POLICY tenant_isolation_custom_reports ON reports.custom_reports
    FOR ALL USING (tenant_id = current_setting('app.current_tenant_id', true)::uuid);

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

CREATE OR REPLACE FUNCTION reports.update_timestamp()
RETURNS TRIGGER AS $$
BEGIN
    NEW.updated_at = CURRENT_TIMESTAMP;
    RETURN NEW;
END;
$$ LANGUAGE plpgsql;

CREATE TRIGGER trg_report_definitions_updated_at
    BEFORE UPDATE ON reports.report_definitions
    FOR EACH ROW EXECUTE FUNCTION reports.update_timestamp();

CREATE TRIGGER trg_report_schedules_updated_at
    BEFORE UPDATE ON reports.report_schedules
    FOR EACH ROW EXECUTE FUNCTION reports.update_timestamp();

CREATE TRIGGER trg_dashboards_updated_at
    BEFORE UPDATE ON reports.dashboards
    FOR EACH ROW EXECUTE FUNCTION reports.update_timestamp();

CREATE TRIGGER trg_dashboard_widgets_updated_at
    BEFORE UPDATE ON reports.dashboard_widgets
    FOR EACH ROW EXECUTE FUNCTION reports.update_timestamp();

CREATE TRIGGER trg_custom_reports_updated_at
    BEFORE UPDATE ON reports.custom_reports
    FOR EACH ROW EXECUTE FUNCTION reports.update_timestamp();

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

-- Funcion para obtener reportes activos de un tenant
CREATE OR REPLACE FUNCTION reports.get_active_reports(p_tenant_id UUID)
RETURNS TABLE (
    id UUID,
    code VARCHAR(50),
    name VARCHAR(255),
    category VARCHAR(100),
    report_type reports.report_type
) AS $$
BEGIN
    RETURN QUERY
    SELECT rd.id, rd.code, rd.name, rd.category, rd.report_type
    FROM reports.report_definitions rd
    WHERE rd.tenant_id = p_tenant_id
    AND rd.is_active = true
    ORDER BY rd.category, rd.name;
END;
$$ LANGUAGE plpgsql STABLE;

-- Funcion para obtener historial de ejecuciones recientes
CREATE OR REPLACE FUNCTION reports.get_recent_executions(
    p_tenant_id UUID,
    p_limit INTEGER DEFAULT 10
)
RETURNS TABLE (
    id UUID,
    report_name VARCHAR(255),
    status reports.execution_status,
    executed_at TIMESTAMPTZ,
    execution_time_ms INTEGER
) AS $$
BEGIN
    RETURN QUERY
    SELECT re.id, rd.name, re.status, re.created_at, re.execution_time_ms
    FROM reports.report_executions re
    JOIN reports.report_definitions rd ON rd.id = re.report_definition_id
    WHERE re.tenant_id = p_tenant_id
    ORDER BY re.created_at DESC
    LIMIT p_limit;
END;
$$ LANGUAGE plpgsql STABLE;

-- =====================
-- COMENTARIOS
-- =====================
COMMENT ON SCHEMA reports IS 'Schema para sistema de reportes y analytics';
COMMENT ON TABLE reports.report_definitions IS 'Definiciones de reportes';
COMMENT ON TABLE reports.report_executions IS 'Historial de ejecuciones de reportes';
COMMENT ON TABLE reports.report_schedules IS 'Programacion de reportes automaticos';
COMMENT ON TABLE reports.report_recipients IS 'Destinatarios de reportes programados';
COMMENT ON TABLE reports.dashboards IS 'Dashboards personalizados';
COMMENT ON TABLE reports.dashboard_widgets IS 'Widgets de dashboards';
COMMENT ON TABLE reports.custom_reports IS 'Reportes personalizados por usuario';
COMMENT ON TABLE reports.data_model_entities IS 'Modelo de datos para report builder';
COMMENT ON TABLE reports.data_model_fields IS 'Campos del modelo de datos';
COMMENT ON TABLE reports.data_model_relationships IS 'Relaciones entre entidades';
