-- ============================================
-- TEMPLATE-SAAS: Core Functions
-- Version: 1.0.0
-- ============================================

-- ============================================
-- TENANT CONTEXT FUNCTIONS
-- ============================================

-- Set current tenant for RLS
CREATE OR REPLACE FUNCTION auth.set_current_tenant(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;

-- Get current tenant
CREATE OR REPLACE FUNCTION auth.get_current_tenant()
RETURNS UUID AS $$
BEGIN
    RETURN current_setting('app.current_tenant_id', TRUE)::UUID;
EXCEPTION
    WHEN OTHERS THEN
        RETURN NULL;
END;
$$ LANGUAGE plpgsql STABLE;

-- Set current user
CREATE OR REPLACE FUNCTION auth.set_current_user(p_user_id UUID)
RETURNS VOID AS $$
BEGIN
    PERFORM set_config('app.current_user_id', p_user_id::TEXT, FALSE);
END;
$$ LANGUAGE plpgsql SECURITY DEFINER;

-- Get current user
CREATE OR REPLACE FUNCTION auth.get_current_user()
RETURNS UUID AS $$
BEGIN
    RETURN current_setting('app.current_user_id', TRUE)::UUID;
EXCEPTION
    WHEN OTHERS THEN
        RETURN NULL;
END;
$$ LANGUAGE plpgsql STABLE;

-- Clear context
CREATE OR REPLACE FUNCTION auth.clear_context()
RETURNS VOID AS $$
BEGIN
    PERFORM set_config('app.current_tenant_id', '', FALSE);
    PERFORM set_config('app.current_user_id', '', FALSE);
END;
$$ LANGUAGE plpgsql SECURITY DEFINER;

-- ============================================
-- PLAN & LIMITS FUNCTIONS
-- ============================================

-- Get tenant's current plan limits
CREATE OR REPLACE FUNCTION plans.get_tenant_limits(p_tenant_id UUID)
RETURNS JSONB AS $$
DECLARE
    v_limits JSONB;
BEGIN
    SELECT p.limits INTO v_limits
    FROM tenants.tenants t
    JOIN plans.plans p ON t.plan_id = p.id
    WHERE t.id = p_tenant_id;

    RETURN COALESCE(v_limits, '{}'::jsonb);
END;
$$ LANGUAGE plpgsql STABLE;

-- Check if tenant can perform action based on limits
CREATE OR REPLACE FUNCTION plans.check_limit(
    p_tenant_id UUID,
    p_limit_key VARCHAR,
    p_current_count INT
)
RETURNS BOOLEAN AS $$
DECLARE
    v_limit INT;
BEGIN
    SELECT (plans.get_tenant_limits(p_tenant_id)->>p_limit_key)::INT INTO v_limit;

    IF v_limit IS NULL THEN
        RETURN TRUE;  -- No limit defined
    END IF;

    RETURN p_current_count < v_limit;
END;
$$ LANGUAGE plpgsql STABLE;

-- Get tenant's feature flags
CREATE OR REPLACE FUNCTION plans.get_tenant_features(p_tenant_id UUID)
RETURNS JSONB AS $$
DECLARE
    v_features JSONB;
BEGIN
    SELECT p.included_features INTO v_features
    FROM tenants.tenants t
    JOIN plans.plans p ON t.plan_id = p.id
    WHERE t.id = p_tenant_id;

    RETURN COALESCE(v_features, '[]'::jsonb);
END;
$$ LANGUAGE plpgsql STABLE;

-- Check if tenant has feature
CREATE OR REPLACE FUNCTION plans.has_feature(
    p_tenant_id UUID,
    p_feature_code VARCHAR
)
RETURNS BOOLEAN AS $$
BEGIN
    RETURN plans.get_tenant_features(p_tenant_id) ? p_feature_code;
END;
$$ LANGUAGE plpgsql STABLE;

-- ============================================
-- USER COUNT FUNCTIONS
-- ============================================

-- Count active users in tenant
CREATE OR REPLACE FUNCTION users.count_active_users(p_tenant_id UUID)
RETURNS INT AS $$
BEGIN
    RETURN (
        SELECT COUNT(*)
        FROM users.users
        WHERE tenant_id = p_tenant_id
        AND status = 'active'
        AND deleted_at IS NULL
    );
END;
$$ LANGUAGE plpgsql STABLE;

-- Check if tenant can add more users
CREATE OR REPLACE FUNCTION users.can_add_user(p_tenant_id UUID)
RETURNS BOOLEAN AS $$
BEGIN
    RETURN plans.check_limit(
        p_tenant_id,
        'max_users',
        users.count_active_users(p_tenant_id)
    );
END;
$$ LANGUAGE plpgsql STABLE;

-- ============================================
-- UTILITY FUNCTIONS
-- ============================================

-- Generate slug from name
CREATE OR REPLACE FUNCTION public.slugify(p_text VARCHAR)
RETURNS VARCHAR AS $$
BEGIN
    RETURN LOWER(
        REGEXP_REPLACE(
            REGEXP_REPLACE(
                TRIM(p_text),
                '[^a-zA-Z0-9\s-]', '', 'g'
            ),
            '\s+', '-', 'g'
        )
    );
END;
$$ LANGUAGE plpgsql IMMUTABLE;

-- Generate random token
CREATE OR REPLACE FUNCTION public.generate_token(p_length INT DEFAULT 32)
RETURNS VARCHAR AS $$
BEGIN
    RETURN encode(gen_random_bytes(p_length), 'hex');
END;
$$ LANGUAGE plpgsql;

-- Hash token
CREATE OR REPLACE FUNCTION public.hash_token(p_token VARCHAR)
RETURNS VARCHAR AS $$
BEGIN
    RETURN encode(digest(p_token, 'sha256'), 'hex');
END;
$$ LANGUAGE plpgsql IMMUTABLE;

-- Comments
COMMENT ON FUNCTION auth.set_current_tenant IS 'Set tenant context for RLS policies';
COMMENT ON FUNCTION auth.get_current_tenant IS 'Get current tenant from context';
COMMENT ON FUNCTION plans.check_limit IS 'Check if action is within plan limits';
COMMENT ON FUNCTION plans.has_feature IS 'Check if tenant has access to feature';
