-- Contexts represent conditions under which rules apply, implemented as callable predicates

CREATE TABLE morbac.contexts (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    name TEXT NOT NULL UNIQUE,
    description TEXT,
    evaluator REGPROC NOT NULL,
    created_at TIMESTAMPTZ NOT NULL DEFAULT now()
);

CREATE INDEX idx_contexts_name ON morbac.contexts(name);

COMMENT ON TABLE morbac.contexts IS 'Contexts - conditions under which rules apply (callable predicates)';
COMMENT ON COLUMN morbac.contexts.evaluator IS 'Function that evaluates this context (returns boolean)';

-- Default context that always evaluates to true

CREATE OR REPLACE FUNCTION morbac.context_always()
RETURNS BOOLEAN
LANGUAGE plpgsql
STABLE
AS $$
BEGIN
    RETURN TRUE;
END;
$$;

COMMENT ON FUNCTION morbac.context_always() IS 'Default context evaluator - always returns true';

INSERT INTO morbac.contexts (name, description, evaluator)
VALUES (
    'always',
    'Default context - always evaluates to true',
    'morbac.context_always'::regproc
);

CREATE OR REPLACE FUNCTION morbac.eval_context(p_context_id UUID)
RETURNS BOOLEAN
LANGUAGE plpgsql
STABLE
SECURITY DEFINER
AS $$
DECLARE
    v_evaluator REGPROC;
    v_result BOOLEAN;
BEGIN
    SELECT evaluator INTO v_evaluator
    FROM morbac.contexts
    WHERE id = p_context_id;

    IF v_evaluator IS NULL THEN
        RAISE EXCEPTION 'Context % not found', p_context_id;
    END IF;

    EXECUTE format('SELECT %s()', v_evaluator::text) INTO v_result;

    RETURN COALESCE(v_result, FALSE);
END;
$$;

COMMENT ON FUNCTION morbac.eval_context(UUID) IS 'Evaluates a context by calling its evaluator function';
