-- ============================================
-- TEMPLATE-SAAS: Roles & Permissions
-- Schema: users
-- Version: 1.0.0
-- ============================================

-- Roles table
CREATE TABLE users.roles (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    tenant_id UUID NOT NULL REFERENCES tenants.tenants(id) ON DELETE CASCADE,

    name VARCHAR(100) NOT NULL,
    code VARCHAR(50) NOT NULL,  -- Short code for programmatic use
    slug VARCHAR(100) NOT NULL,
    description TEXT,

    -- System role (cannot be deleted)
    is_system BOOLEAN DEFAULT FALSE,
    is_active BOOLEAN DEFAULT TRUE,

    -- Permissions (JSONB array)
    permissions JSONB DEFAULT '[]'::jsonb,
    -- Example: ["users:read", "users:write", "billing:read"]

    -- Hierarchy
    parent_role_id UUID REFERENCES users.roles(id),
    level INT DEFAULT 0,  -- 0 = lowest, higher = more permissions

    -- Metadata
    metadata JSONB DEFAULT '{}'::jsonb,

    -- Audit
    created_at TIMESTAMPTZ DEFAULT NOW() NOT NULL,
    updated_at TIMESTAMPTZ DEFAULT NOW() NOT NULL,
    created_by UUID,

    -- Constraints
    CONSTRAINT unique_role_code_per_tenant UNIQUE (tenant_id, code),
    CONSTRAINT unique_role_slug_per_tenant UNIQUE (tenant_id, slug),
    CONSTRAINT valid_role_code CHECK (code ~ '^[A-Z][A-Z0-9_]*$'),
    CONSTRAINT valid_role_slug CHECK (slug ~ '^[a-z][a-z0-9_]*$')
);

-- User-Role junction
CREATE TABLE users.user_roles (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    tenant_id UUID NOT NULL REFERENCES tenants.tenants(id) ON DELETE CASCADE,
    user_id UUID NOT NULL REFERENCES users.users(id) ON DELETE CASCADE,
    role_id UUID NOT NULL REFERENCES users.roles(id) ON DELETE CASCADE,

    -- Optional expiration
    expires_at TIMESTAMPTZ,

    -- Audit
    created_at TIMESTAMPTZ DEFAULT NOW() NOT NULL,
    created_by UUID,

    -- Constraints
    CONSTRAINT unique_user_role UNIQUE (user_id, role_id)
);

-- Permissions reference table (optional, for UI)
CREATE TABLE users.permissions (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),

    -- Permission definition
    code VARCHAR(100) UNIQUE NOT NULL,  -- e.g., "users:write"
    name VARCHAR(200) NOT NULL,
    description TEXT,
    category VARCHAR(100),  -- e.g., "users", "billing", "settings"

    -- Metadata
    is_sensitive BOOLEAN DEFAULT FALSE,  -- Requires extra confirmation
    requires_owner BOOLEAN DEFAULT FALSE,  -- Only tenant owner

    created_at TIMESTAMPTZ DEFAULT NOW() NOT NULL
);

-- Indexes
CREATE INDEX idx_roles_tenant ON users.roles(tenant_id);
CREATE INDEX idx_roles_code ON users.roles(tenant_id, code);
CREATE INDEX idx_roles_slug ON users.roles(tenant_id, slug);
CREATE INDEX idx_roles_active ON users.roles(tenant_id, is_active) WHERE is_active = TRUE;
CREATE INDEX idx_user_roles_user ON users.user_roles(user_id);
CREATE INDEX idx_user_roles_role ON users.user_roles(role_id);
CREATE INDEX idx_user_roles_tenant ON users.user_roles(tenant_id);

-- RLS for roles
ALTER TABLE users.roles ENABLE ROW LEVEL SECURITY;

CREATE POLICY roles_tenant_isolation ON users.roles
    USING (tenant_id = current_setting('app.current_tenant_id', true)::UUID);

-- RLS for user_roles
ALTER TABLE users.user_roles ENABLE ROW LEVEL SECURITY;

CREATE POLICY user_roles_tenant_isolation ON users.user_roles
    USING (tenant_id = current_setting('app.current_tenant_id', true)::UUID);

-- Triggers
CREATE TRIGGER trg_roles_updated_at
    BEFORE UPDATE ON users.roles
    FOR EACH ROW
    EXECUTE FUNCTION users.update_updated_at();

-- Comments
COMMENT ON TABLE users.roles IS 'Role definitions per tenant';
COMMENT ON TABLE users.user_roles IS 'User-Role assignments';
COMMENT ON TABLE users.permissions IS 'Permission registry (global reference)';
COMMENT ON COLUMN users.roles.permissions IS 'Array of permission codes';
COMMENT ON COLUMN users.roles.is_system IS 'System roles cannot be modified or deleted';
