-- =============================================================
-- ARCHIVO: 09-notifications.sql
-- DESCRIPCION: Sistema de notificaciones, templates, preferencias
-- VERSION: 1.0.0
-- PROYECTO: ERP-Core V2
-- FECHA: 2026-01-10
-- EPIC: SAAS-NOTIFICATIONS (EPIC-SAAS-003)
-- HISTORIAS: US-040, US-041, US-042
-- =============================================================

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

-- =====================
-- TABLA: notifications.channels
-- Canales de notificacion disponibles
-- =====================
CREATE TABLE IF NOT EXISTS notifications.channels (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),

    -- Identificacion
    code VARCHAR(30) NOT NULL UNIQUE,
    name VARCHAR(100) NOT NULL,
    description TEXT,

    -- Tipo
    channel_type VARCHAR(30) NOT NULL, -- email, sms, push, whatsapp, in_app, webhook

    -- Configuracion del proveedor
    provider VARCHAR(50), -- sendgrid, twilio, firebase, meta, custom
    provider_config JSONB DEFAULT '{}',

    -- Limites
    rate_limit_per_minute INTEGER DEFAULT 60,
    rate_limit_per_hour INTEGER DEFAULT 1000,
    rate_limit_per_day INTEGER DEFAULT 10000,

    -- Estado
    is_active BOOLEAN DEFAULT TRUE,
    is_default BOOLEAN DEFAULT FALSE,

    -- Metadata
    metadata JSONB DEFAULT '{}',

    created_at TIMESTAMPTZ DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMPTZ DEFAULT CURRENT_TIMESTAMP
);

-- =====================
-- TABLA: notifications.templates
-- Templates de notificaciones
-- =====================
CREATE TABLE IF NOT EXISTS notifications.templates (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    tenant_id UUID REFERENCES auth.tenants(id) ON DELETE CASCADE, -- NULL = global template

    -- Identificacion
    code VARCHAR(100) NOT NULL,
    name VARCHAR(200) NOT NULL,
    description TEXT,
    category VARCHAR(50), -- system, marketing, transactional, alert

    -- Canal objetivo
    channel_type VARCHAR(30) NOT NULL, -- email, sms, push, whatsapp, in_app

    -- Contenido
    subject VARCHAR(500), -- Para email
    body_template TEXT NOT NULL,
    body_html TEXT, -- Para email HTML

    -- Variables disponibles
    available_variables JSONB DEFAULT '[]',
    -- Ejemplo: ["user_name", "company_name", "action_url"]

    -- Configuracion
    default_locale VARCHAR(10) DEFAULT 'es-MX',

    -- Estado
    is_active BOOLEAN DEFAULT TRUE,
    is_system BOOLEAN DEFAULT FALSE, -- Templates del sistema no editables

    -- Versionamiento
    version INTEGER DEFAULT 1,

    created_at TIMESTAMPTZ DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMPTZ DEFAULT CURRENT_TIMESTAMP,
    created_by UUID REFERENCES auth.users(id),
    updated_by UUID REFERENCES auth.users(id),

    UNIQUE(tenant_id, code, channel_type)
);

-- =====================
-- TABLA: notifications.template_translations
-- Traducciones de templates
-- =====================
CREATE TABLE IF NOT EXISTS notifications.template_translations (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    template_id UUID NOT NULL REFERENCES notifications.templates(id) ON DELETE CASCADE,

    -- Idioma
    locale VARCHAR(10) NOT NULL, -- es-MX, en-US, etc.

    -- Contenido traducido
    subject VARCHAR(500),
    body_template TEXT NOT NULL,
    body_html TEXT,

    -- Estado
    is_active BOOLEAN DEFAULT TRUE,

    created_at TIMESTAMPTZ DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMPTZ DEFAULT CURRENT_TIMESTAMP,

    UNIQUE(template_id, locale)
);

-- =====================
-- TABLA: notifications.preferences
-- Preferencias de notificacion por usuario
-- =====================
CREATE TABLE IF NOT EXISTS notifications.preferences (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    user_id UUID NOT NULL REFERENCES auth.users(id) ON DELETE CASCADE,
    tenant_id UUID NOT NULL REFERENCES auth.tenants(id) ON DELETE CASCADE,

    -- Preferencias globales
    global_enabled BOOLEAN DEFAULT TRUE,
    quiet_hours_start TIME,
    quiet_hours_end TIME,
    timezone VARCHAR(50) DEFAULT 'America/Mexico_City',

    -- Preferencias por canal
    email_enabled BOOLEAN DEFAULT TRUE,
    sms_enabled BOOLEAN DEFAULT TRUE,
    push_enabled BOOLEAN DEFAULT TRUE,
    whatsapp_enabled BOOLEAN DEFAULT FALSE,
    in_app_enabled BOOLEAN DEFAULT TRUE,

    -- Preferencias por categoria
    category_preferences JSONB DEFAULT '{}',
    -- Ejemplo: {"marketing": false, "alerts": true, "reports": {"email": true, "push": false}}

    -- Frecuencia de digest
    digest_frequency VARCHAR(20) DEFAULT 'instant', -- instant, hourly, daily, weekly
    digest_day INTEGER, -- 0-6 para weekly
    digest_hour INTEGER DEFAULT 9, -- Hora del dia para daily/weekly

    -- Metadata
    metadata JSONB DEFAULT '{}',

    created_at TIMESTAMPTZ DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMPTZ DEFAULT CURRENT_TIMESTAMP,

    UNIQUE(user_id, tenant_id)
);

-- =====================
-- TABLA: notifications.notifications
-- Notificaciones enviadas/pendientes
-- =====================
CREATE TABLE IF NOT EXISTS notifications.notifications (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    tenant_id UUID NOT NULL REFERENCES auth.tenants(id) ON DELETE CASCADE,

    -- Destinatario
    user_id UUID REFERENCES auth.users(id) ON DELETE CASCADE,
    recipient_email VARCHAR(255),
    recipient_phone VARCHAR(20),
    recipient_device_id UUID REFERENCES auth.devices(id),

    -- Template usado
    template_id UUID REFERENCES notifications.templates(id),
    template_code VARCHAR(100),

    -- Canal
    channel_type VARCHAR(30) NOT NULL,
    channel_id UUID REFERENCES notifications.channels(id),

    -- Contenido renderizado
    subject VARCHAR(500),
    body TEXT NOT NULL,
    body_html TEXT,

    -- Variables usadas
    variables JSONB DEFAULT '{}',

    -- Contexto
    context_type VARCHAR(50), -- sale, attendance, inventory, system
    context_id UUID,

    -- Prioridad
    priority VARCHAR(20) DEFAULT 'normal', -- low, normal, high, urgent

    -- Estado
    status VARCHAR(20) NOT NULL DEFAULT 'pending',
    -- pending, queued, sending, sent, delivered, read, failed, cancelled

    -- Tracking
    queued_at TIMESTAMPTZ,
    sent_at TIMESTAMPTZ,
    delivered_at TIMESTAMPTZ,
    read_at TIMESTAMPTZ,
    failed_at TIMESTAMPTZ,

    -- Errores
    error_message TEXT,
    retry_count INTEGER DEFAULT 0,
    max_retries INTEGER DEFAULT 3,
    next_retry_at TIMESTAMPTZ,

    -- Proveedor
    provider_message_id VARCHAR(255),
    provider_response JSONB DEFAULT '{}',

    -- Metadata
    metadata JSONB DEFAULT '{}',

    -- Expiracion
    expires_at TIMESTAMPTZ,

    created_at TIMESTAMPTZ DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMPTZ DEFAULT CURRENT_TIMESTAMP
);

-- =====================
-- TABLA: notifications.notification_batches
-- Lotes de notificaciones masivas
-- =====================
CREATE TABLE IF NOT EXISTS notifications.notification_batches (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    tenant_id UUID NOT NULL REFERENCES auth.tenants(id) ON DELETE CASCADE,

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

    -- Template
    template_id UUID REFERENCES notifications.templates(id),
    channel_type VARCHAR(30) NOT NULL,

    -- Audiencia
    audience_type VARCHAR(30) NOT NULL, -- all_users, segment, custom
    audience_filter JSONB DEFAULT '{}',

    -- Contenido
    variables JSONB DEFAULT '{}',

    -- Programacion
    scheduled_at TIMESTAMPTZ,

    -- Estado
    status VARCHAR(20) NOT NULL DEFAULT 'draft',
    -- draft, scheduled, processing, completed, failed, cancelled

    -- Estadisticas
    total_recipients INTEGER DEFAULT 0,
    sent_count INTEGER DEFAULT 0,
    delivered_count INTEGER DEFAULT 0,
    failed_count INTEGER DEFAULT 0,
    read_count INTEGER DEFAULT 0,

    -- Tiempos
    started_at TIMESTAMPTZ,
    completed_at TIMESTAMPTZ,

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

-- =====================
-- TABLA: notifications.in_app_notifications
-- Notificaciones in-app (centro de notificaciones)
-- =====================
CREATE TABLE IF NOT EXISTS notifications.in_app_notifications (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    tenant_id UUID NOT NULL REFERENCES auth.tenants(id) ON DELETE CASCADE,
    user_id UUID NOT NULL REFERENCES auth.users(id) ON DELETE CASCADE,

    -- Contenido
    title VARCHAR(200) NOT NULL,
    message TEXT NOT NULL,
    icon VARCHAR(50),
    color VARCHAR(20),

    -- Accion
    action_type VARCHAR(30), -- link, modal, function
    action_url TEXT,
    action_data JSONB DEFAULT '{}',

    -- Categoria
    category VARCHAR(50), -- info, success, warning, error, task

    -- Contexto
    context_type VARCHAR(50),
    context_id UUID,

    -- Estado
    is_read BOOLEAN DEFAULT FALSE,
    read_at TIMESTAMPTZ,
    is_archived BOOLEAN DEFAULT FALSE,
    archived_at TIMESTAMPTZ,

    -- Prioridad y expiracion
    priority VARCHAR(20) DEFAULT 'normal',
    expires_at TIMESTAMPTZ,

    created_at TIMESTAMPTZ DEFAULT CURRENT_TIMESTAMP
);

-- =====================
-- INDICES
-- =====================

-- Indices para channels
CREATE INDEX IF NOT EXISTS idx_channels_type ON notifications.channels(channel_type);
CREATE INDEX IF NOT EXISTS idx_channels_active ON notifications.channels(is_active) WHERE is_active = TRUE;

-- Indices para templates
CREATE INDEX IF NOT EXISTS idx_templates_tenant ON notifications.templates(tenant_id);
CREATE INDEX IF NOT EXISTS idx_templates_code ON notifications.templates(code);
CREATE INDEX IF NOT EXISTS idx_templates_channel ON notifications.templates(channel_type);
CREATE INDEX IF NOT EXISTS idx_templates_active ON notifications.templates(is_active) WHERE is_active = TRUE;

-- Indices para template_translations
CREATE INDEX IF NOT EXISTS idx_template_trans_template ON notifications.template_translations(template_id);
CREATE INDEX IF NOT EXISTS idx_template_trans_locale ON notifications.template_translations(locale);

-- Indices para preferences
CREATE INDEX IF NOT EXISTS idx_preferences_user ON notifications.preferences(user_id);
CREATE INDEX IF NOT EXISTS idx_preferences_tenant ON notifications.preferences(tenant_id);

-- Indices para notifications
CREATE INDEX IF NOT EXISTS idx_notifications_tenant ON notifications.notifications(tenant_id);
CREATE INDEX IF NOT EXISTS idx_notifications_user ON notifications.notifications(user_id);
CREATE INDEX IF NOT EXISTS idx_notifications_status ON notifications.notifications(status);
CREATE INDEX IF NOT EXISTS idx_notifications_channel ON notifications.notifications(channel_type);
CREATE INDEX IF NOT EXISTS idx_notifications_context ON notifications.notifications(context_type, context_id);
CREATE INDEX IF NOT EXISTS idx_notifications_pending ON notifications.notifications(status, next_retry_at)
    WHERE status IN ('pending', 'queued');
CREATE INDEX IF NOT EXISTS idx_notifications_created ON notifications.notifications(created_at DESC);

-- Indices para notification_batches
CREATE INDEX IF NOT EXISTS idx_batches_tenant ON notifications.notification_batches(tenant_id);
CREATE INDEX IF NOT EXISTS idx_batches_status ON notifications.notification_batches(status);
CREATE INDEX IF NOT EXISTS idx_batches_scheduled ON notifications.notification_batches(scheduled_at)
    WHERE status = 'scheduled';

-- Indices para in_app_notifications
CREATE INDEX IF NOT EXISTS idx_in_app_user ON notifications.in_app_notifications(user_id);
CREATE INDEX IF NOT EXISTS idx_in_app_tenant ON notifications.in_app_notifications(tenant_id);
CREATE INDEX IF NOT EXISTS idx_in_app_unread ON notifications.in_app_notifications(user_id, is_read)
    WHERE is_read = FALSE;
CREATE INDEX IF NOT EXISTS idx_in_app_created ON notifications.in_app_notifications(created_at DESC);

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

-- Channels son globales (lectura publica, escritura admin)
ALTER TABLE notifications.channels ENABLE ROW LEVEL SECURITY;
CREATE POLICY public_read_channels ON notifications.channels
    FOR SELECT USING (true);

-- Templates: globales (tenant_id NULL) o por tenant
ALTER TABLE notifications.templates ENABLE ROW LEVEL SECURITY;
CREATE POLICY tenant_or_global_templates ON notifications.templates
    FOR SELECT USING (
        tenant_id IS NULL
        OR tenant_id = current_setting('app.current_tenant_id', true)::uuid
    );

ALTER TABLE notifications.template_translations ENABLE ROW LEVEL SECURITY;
CREATE POLICY template_trans_access ON notifications.template_translations
    FOR SELECT USING (
        template_id IN (
            SELECT id FROM notifications.templates
            WHERE tenant_id IS NULL
            OR tenant_id = current_setting('app.current_tenant_id', true)::uuid
        )
    );

-- Preferences por tenant
ALTER TABLE notifications.preferences ENABLE ROW LEVEL SECURITY;
CREATE POLICY tenant_isolation_preferences ON notifications.preferences
    USING (tenant_id = current_setting('app.current_tenant_id', true)::uuid);

-- Notifications por tenant
ALTER TABLE notifications.notifications ENABLE ROW LEVEL SECURITY;
CREATE POLICY tenant_isolation_notifications ON notifications.notifications
    USING (tenant_id = current_setting('app.current_tenant_id', true)::uuid);

-- Batches por tenant
ALTER TABLE notifications.notification_batches ENABLE ROW LEVEL SECURITY;
CREATE POLICY tenant_isolation_batches ON notifications.notification_batches
    USING (tenant_id = current_setting('app.current_tenant_id', true)::uuid);

-- In-app notifications por tenant
ALTER TABLE notifications.in_app_notifications ENABLE ROW LEVEL SECURITY;
CREATE POLICY tenant_isolation_in_app ON notifications.in_app_notifications
    USING (tenant_id = current_setting('app.current_tenant_id', true)::uuid);

-- =====================
-- FUNCIONES
-- =====================

-- Funcion para obtener template con fallback a global
CREATE OR REPLACE FUNCTION notifications.get_template(
    p_tenant_id UUID,
    p_code VARCHAR(100),
    p_channel_type VARCHAR(30),
    p_locale VARCHAR(10) DEFAULT 'es-MX'
)
RETURNS TABLE (
    template_id UUID,
    subject VARCHAR(500),
    body_template TEXT,
    body_html TEXT,
    available_variables JSONB
) AS $$
BEGIN
    RETURN QUERY
    SELECT
        t.id as template_id,
        COALESCE(tt.subject, t.subject) as subject,
        COALESCE(tt.body_template, t.body_template) as body_template,
        COALESCE(tt.body_html, t.body_html) as body_html,
        t.available_variables
    FROM notifications.templates t
    LEFT JOIN notifications.template_translations tt
        ON tt.template_id = t.id AND tt.locale = p_locale AND tt.is_active = TRUE
    WHERE t.code = p_code
    AND t.channel_type = p_channel_type
    AND t.is_active = TRUE
    AND (t.tenant_id = p_tenant_id OR t.tenant_id IS NULL)
    ORDER BY t.tenant_id NULLS LAST -- Priorizar template del tenant
    LIMIT 1;
END;
$$ LANGUAGE plpgsql STABLE;

-- Funcion para verificar preferencias de usuario
CREATE OR REPLACE FUNCTION notifications.should_send(
    p_user_id UUID,
    p_tenant_id UUID,
    p_channel_type VARCHAR(30),
    p_category VARCHAR(50) DEFAULT NULL
)
RETURNS BOOLEAN AS $$
DECLARE
    v_prefs RECORD;
    v_channel_enabled BOOLEAN;
    v_category_enabled BOOLEAN;
    v_in_quiet_hours BOOLEAN;
BEGIN
    -- Obtener preferencias
    SELECT * INTO v_prefs
    FROM notifications.preferences
    WHERE user_id = p_user_id AND tenant_id = p_tenant_id;

    -- Si no hay preferencias, permitir por defecto
    IF NOT FOUND THEN
        RETURN TRUE;
    END IF;

    -- Verificar si las notificaciones estan habilitadas globalmente
    IF NOT v_prefs.global_enabled THEN
        RETURN FALSE;
    END IF;

    -- Verificar canal especifico
    v_channel_enabled := CASE p_channel_type
        WHEN 'email' THEN v_prefs.email_enabled
        WHEN 'sms' THEN v_prefs.sms_enabled
        WHEN 'push' THEN v_prefs.push_enabled
        WHEN 'whatsapp' THEN v_prefs.whatsapp_enabled
        WHEN 'in_app' THEN v_prefs.in_app_enabled
        ELSE TRUE
    END;

    IF NOT v_channel_enabled THEN
        RETURN FALSE;
    END IF;

    -- Verificar categoria si se proporciona
    IF p_category IS NOT NULL AND v_prefs.category_preferences ? p_category THEN
        v_category_enabled := (v_prefs.category_preferences->>p_category)::boolean;
        IF NOT v_category_enabled THEN
            RETURN FALSE;
        END IF;
    END IF;

    -- Verificar horas de silencio
    IF v_prefs.quiet_hours_start IS NOT NULL AND v_prefs.quiet_hours_end IS NOT NULL THEN
        v_in_quiet_hours := CURRENT_TIME BETWEEN v_prefs.quiet_hours_start AND v_prefs.quiet_hours_end;
        IF v_in_quiet_hours AND p_channel_type IN ('push', 'sms') THEN
            RETURN FALSE;
        END IF;
    END IF;

    RETURN TRUE;
END;
$$ LANGUAGE plpgsql STABLE;

-- Funcion para encolar notificacion
CREATE OR REPLACE FUNCTION notifications.enqueue_notification(
    p_tenant_id UUID,
    p_user_id UUID,
    p_template_code VARCHAR(100),
    p_channel_type VARCHAR(30),
    p_variables JSONB DEFAULT '{}',
    p_context_type VARCHAR(50) DEFAULT NULL,
    p_context_id UUID DEFAULT NULL,
    p_priority VARCHAR(20) DEFAULT 'normal'
)
RETURNS UUID AS $$
DECLARE
    v_template RECORD;
    v_notification_id UUID;
    v_subject VARCHAR(500);
    v_body TEXT;
    v_body_html TEXT;
BEGIN
    -- Verificar preferencias
    IF NOT notifications.should_send(p_user_id, p_tenant_id, p_channel_type) THEN
        RETURN NULL;
    END IF;

    -- Obtener template
    SELECT * INTO v_template
    FROM notifications.get_template(p_tenant_id, p_template_code, p_channel_type);

    IF v_template.template_id IS NULL THEN
        RAISE EXCEPTION 'Template not found: %', p_template_code;
    END IF;

    -- TODO: Renderizar template con variables (se hara en el backend)
    v_subject := v_template.subject;
    v_body := v_template.body_template;
    v_body_html := v_template.body_html;

    -- Crear notificacion
    INSERT INTO notifications.notifications (
        tenant_id, user_id, template_id, template_code,
        channel_type, subject, body, body_html,
        variables, context_type, context_id, priority,
        status, queued_at
    ) VALUES (
        p_tenant_id, p_user_id, v_template.template_id, p_template_code,
        p_channel_type, v_subject, v_body, v_body_html,
        p_variables, p_context_type, p_context_id, p_priority,
        'queued', CURRENT_TIMESTAMP
    ) RETURNING id INTO v_notification_id;

    RETURN v_notification_id;
END;
$$ LANGUAGE plpgsql;

-- Funcion para marcar notificacion como leida
CREATE OR REPLACE FUNCTION notifications.mark_as_read(p_notification_id UUID)
RETURNS BOOLEAN AS $$
BEGIN
    UPDATE notifications.in_app_notifications
    SET is_read = TRUE, read_at = CURRENT_TIMESTAMP
    WHERE id = p_notification_id AND is_read = FALSE;

    RETURN FOUND;
END;
$$ LANGUAGE plpgsql;

-- Funcion para obtener conteo de no leidas
CREATE OR REPLACE FUNCTION notifications.get_unread_count(p_user_id UUID, p_tenant_id UUID)
RETURNS INTEGER AS $$
BEGIN
    RETURN (
        SELECT COUNT(*)::INTEGER
        FROM notifications.in_app_notifications
        WHERE user_id = p_user_id
        AND tenant_id = p_tenant_id
        AND is_read = FALSE
        AND is_archived = FALSE
        AND (expires_at IS NULL OR expires_at > CURRENT_TIMESTAMP)
    );
END;
$$ LANGUAGE plpgsql STABLE;

-- Funcion para limpiar notificaciones antiguas
CREATE OR REPLACE FUNCTION notifications.cleanup_old_notifications(p_days INTEGER DEFAULT 90)
RETURNS INTEGER AS $$
DECLARE
    deleted_count INTEGER;
BEGIN
    -- Eliminar notificaciones enviadas antiguas
    DELETE FROM notifications.notifications
    WHERE created_at < CURRENT_TIMESTAMP - (p_days || ' days')::INTERVAL
    AND status IN ('sent', 'delivered', 'read', 'failed', 'cancelled');

    GET DIAGNOSTICS deleted_count = ROW_COUNT;

    -- Eliminar in-app archivadas antiguas
    DELETE FROM notifications.in_app_notifications
    WHERE archived_at IS NOT NULL
    AND archived_at < CURRENT_TIMESTAMP - (p_days || ' days')::INTERVAL;

    RETURN deleted_count;
END;
$$ LANGUAGE plpgsql;

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

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

CREATE TRIGGER trg_channels_updated_at
    BEFORE UPDATE ON notifications.channels
    FOR EACH ROW EXECUTE FUNCTION notifications.update_timestamp();

CREATE TRIGGER trg_templates_updated_at
    BEFORE UPDATE ON notifications.templates
    FOR EACH ROW EXECUTE FUNCTION notifications.update_timestamp();

CREATE TRIGGER trg_preferences_updated_at
    BEFORE UPDATE ON notifications.preferences
    FOR EACH ROW EXECUTE FUNCTION notifications.update_timestamp();

CREATE TRIGGER trg_notifications_updated_at
    BEFORE UPDATE ON notifications.notifications
    FOR EACH ROW EXECUTE FUNCTION notifications.update_timestamp();

CREATE TRIGGER trg_batches_updated_at
    BEFORE UPDATE ON notifications.notification_batches
    FOR EACH ROW EXECUTE FUNCTION notifications.update_timestamp();

-- =====================
-- SEED DATA: Canales
-- =====================
INSERT INTO notifications.channels (code, name, channel_type, provider, is_active, is_default) VALUES
('email_sendgrid', 'Email (SendGrid)', 'email', 'sendgrid', TRUE, TRUE),
('email_smtp', 'Email (SMTP)', 'email', 'smtp', TRUE, FALSE),
('sms_twilio', 'SMS (Twilio)', 'sms', 'twilio', TRUE, TRUE),
('push_firebase', 'Push (Firebase)', 'push', 'firebase', TRUE, TRUE),
('whatsapp_meta', 'WhatsApp (Meta)', 'whatsapp', 'meta', FALSE, FALSE),
('in_app', 'In-App', 'in_app', 'internal', TRUE, TRUE)
ON CONFLICT (code) DO NOTHING;

-- =====================
-- SEED DATA: Templates del Sistema
-- =====================
INSERT INTO notifications.templates (code, name, channel_type, subject, body_template, category, is_system, available_variables) VALUES
-- Email templates
('welcome', 'Bienvenida', 'email', 'Bienvenido a {{company_name}}',
 'Hola {{user_name}},\n\nBienvenido a {{company_name}}. Tu cuenta ha sido creada exitosamente.\n\nPuedes acceder desde: {{login_url}}\n\nSaludos,\nEl equipo de {{company_name}}',
 'system', TRUE, '["user_name", "company_name", "login_url"]'),

('password_reset', 'Recuperar Contraseña', 'email', 'Recupera tu contraseña - {{company_name}}',
 'Hola {{user_name}},\n\nHemos recibido una solicitud para recuperar tu contraseña.\n\nHaz clic aquí para restablecerla: {{reset_url}}\n\nEste enlace expira en {{expiry_hours}} horas.\n\nSi no solicitaste esto, ignora este correo.',
 'system', TRUE, '["user_name", "reset_url", "expiry_hours", "company_name"]'),

('invitation', 'Invitación', 'email', 'Has sido invitado a {{company_name}}',
 'Hola,\n\n{{inviter_name}} te ha invitado a unirte a {{company_name}} con el rol de {{role_name}}.\n\nAcepta la invitación aquí: {{invitation_url}}\n\nEsta invitación expira el {{expiry_date}}.',
 'system', TRUE, '["inviter_name", "company_name", "role_name", "invitation_url", "expiry_date"]'),

('mfa_code', 'Código de Verificación', 'email', 'Tu código de verificación: {{code}}',
 'Tu código de verificación es: {{code}}\n\nEste código expira en {{expiry_minutes}} minutos.\n\nSi no solicitaste esto, cambia tu contraseña inmediatamente.',
 'system', TRUE, '["code", "expiry_minutes"]'),

-- Push templates
('attendance_reminder', 'Recordatorio de Asistencia', 'push', NULL,
 '{{user_name}}, no olvides registrar tu {{attendance_type}} de hoy.',
 'transactional', TRUE, '["user_name", "attendance_type"]'),

('low_stock_alert', 'Alerta de Stock Bajo', 'push', NULL,
 'Stock bajo: {{product_name}} tiene solo {{quantity}} unidades en {{branch_name}}.',
 'alert', TRUE, '["product_name", "quantity", "branch_name"]'),

-- In-app templates
('task_assigned', 'Tarea Asignada', 'in_app', NULL,
 '{{assigner_name}} te ha asignado una nueva tarea: {{task_title}}',
 'transactional', TRUE, '["assigner_name", "task_title"]'),

('payment_received', 'Pago Recibido', 'in_app', NULL,
 'Se ha recibido un pago de ${{amount}} {{currency}} de {{customer_name}}.',
 'transactional', TRUE, '["amount", "currency", "customer_name"]')

ON CONFLICT (tenant_id, code, channel_type) DO NOTHING;

-- =====================
-- COMENTARIOS
-- =====================
COMMENT ON TABLE notifications.channels IS 'Canales de notificacion disponibles (email, sms, push, etc.)';
COMMENT ON TABLE notifications.templates IS 'Templates de notificaciones con soporte multi-idioma';
COMMENT ON TABLE notifications.template_translations IS 'Traducciones de templates de notificaciones';
COMMENT ON TABLE notifications.preferences IS 'Preferencias de notificacion por usuario';
COMMENT ON TABLE notifications.notifications IS 'Cola y log de notificaciones';
COMMENT ON TABLE notifications.notification_batches IS 'Lotes de notificaciones masivas';
COMMENT ON TABLE notifications.in_app_notifications IS 'Notificaciones in-app para centro de notificaciones';

COMMENT ON FUNCTION notifications.get_template IS 'Obtiene template con fallback a template global';
COMMENT ON FUNCTION notifications.should_send IS 'Verifica si se debe enviar notificacion segun preferencias';
COMMENT ON FUNCTION notifications.enqueue_notification IS 'Encola una notificacion para envio';
COMMENT ON FUNCTION notifications.get_unread_count IS 'Obtiene conteo de notificaciones no leidas';
