-- OCDP 多租户权限系统迁移脚本
-- 版本: v2.0.0
-- 日期: 2026-04-09

-- ===== 1. 修改 users 表 =====
ALTER TABLE users ADD COLUMN IF NOT EXISTS role VARCHAR(20) NOT NULL DEFAULT 'user';
ALTER TABLE users ADD COLUMN IF NOT EXISTS workspace_id VARCHAR(36);
ALTER TABLE users ADD COLUMN IF NOT EXISTS is_active BOOLEAN DEFAULT TRUE;
ALTER TABLE users ADD COLUMN IF NOT EXISTS must_change_password BOOLEAN DEFAULT FALSE;

-- 添加索引
CREATE INDEX IF NOT EXISTS idx_users_role ON users(role);
CREATE INDEX IF NOT EXISTS idx_users_workspace ON users(workspace_id);
CREATE INDEX IF NOT EXISTS idx_users_is_active ON users(is_active);

COMMENT ON COLUMN users.role IS '用户角色: admin, user';
COMMENT ON COLUMN users.workspace_id IS '所属工作空间 ID';
COMMENT ON COLUMN users.is_active IS '账户是否激活';
COMMENT ON COLUMN users.must_change_password IS '首次登录必须修改密码';

-- ===== 2. 创建 workspaces 表 =====
CREATE TABLE IF NOT EXISTS workspaces (
    id VARCHAR(36) PRIMARY KEY,
    name VARCHAR(255) NOT NULL UNIQUE,
    description TEXT,
    created_by VARCHAR(36) REFERENCES users(id),
    created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
);

CREATE INDEX IF NOT EXISTS idx_workspaces_name ON workspaces(name);
CREATE INDEX IF NOT EXISTS idx_workspaces_created_by ON workspaces(created_by);

COMMENT ON TABLE workspaces IS '工作空间/租户表';

-- ===== 3. 创建 workspace_quotas 表 =====
CREATE TABLE IF NOT EXISTS workspace_quotas (
    id VARCHAR(36) PRIMARY KEY,
    workspace_id VARCHAR(36) NOT NULL REFERENCES workspaces(id) ON DELETE CASCADE,
    resource_type VARCHAR(50) NOT NULL,  -- 'cpu', 'gpu', 'gpu_memory'
    hard_limit DECIMAL(10,2) NOT NULL DEFAULT 0,   -- 硬限制（0表示无限制）
    soft_limit DECIMAL(10,2) NOT NULL DEFAULT 0,   -- 软限制（警告阈值）
    used DECIMAL(10,2) DEFAULT 0,                  -- 当前使用量
    created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
    UNIQUE(workspace_id, resource_type)
);

CREATE INDEX IF NOT EXISTS idx_workspace_quotas_workspace ON workspace_quotas(workspace_id);
CREATE INDEX IF NOT EXISTS idx_workspace_quotas_type ON workspace_quotas(resource_type);

COMMENT ON TABLE workspace_quotas IS '工作空间资源配额表';
COMMENT ON COLUMN workspace_quotas.resource_type IS '资源类型: cpu, gpu, gpu_memory';
COMMENT ON COLUMN workspace_quotas.hard_limit IS '硬限制（0表示无限制）';
COMMENT ON COLUMN workspace_quotas.soft_limit IS '软限制（警告阈值）';
COMMENT ON COLUMN workspace_quotas.used IS '当前使用量';

-- ===== 4. 修改 clusters 表 =====
ALTER TABLE clusters ADD COLUMN IF NOT EXISTS workspace_id VARCHAR(36) REFERENCES workspaces(id) ON DELETE SET NULL;
ALTER TABLE clusters ADD COLUMN IF NOT EXISTS owner_id VARCHAR(36) REFERENCES users(id);
ALTER TABLE clusters ADD COLUMN IF NOT EXISTS isolation_mode VARCHAR(20) DEFAULT 'namespace';
ALTER TABLE clusters ADD COLUMN IF NOT EXISTS default_namespace VARCHAR(255);
ALTER TABLE clusters ADD COLUMN IF NOT EXISTS is_shared BOOLEAN DEFAULT FALSE;

CREATE INDEX IF NOT EXISTS idx_clusters_workspace ON clusters(workspace_id);
CREATE INDEX IF NOT EXISTS idx_clusters_owner ON clusters(owner_id);
CREATE INDEX IF NOT EXISTS idx_clusters_is_shared ON clusters(is_shared);

-- 删除旧的唯一约束，添加新的（允许同一workspace内名称唯一）
ALTER TABLE clusters DROP CONSTRAINT IF EXISTS clusters_name_key;

COMMENT ON COLUMN clusters.workspace_id IS '所属工作空间 ID';
COMMENT ON COLUMN clusters.owner_id IS '创建者用户 ID';
COMMENT ON COLUMN clusters.isolation_mode IS '隔离模式: namespace(共享集群) 或 cluster(独立集群)';
COMMENT ON COLUMN clusters.default_namespace IS '默认命名空间前缀';
COMMENT ON COLUMN clusters.is_shared IS '是否为共享集群';

-- ===== 5. 修改 registries 表 =====
ALTER TABLE registries ADD COLUMN IF NOT EXISTS workspace_id VARCHAR(36) REFERENCES workspaces(id) ON DELETE SET NULL;
ALTER TABLE registries ADD COLUMN IF NOT EXISTS owner_id VARCHAR(36) REFERENCES users(id);
ALTER TABLE registries ADD COLUMN IF NOT EXISTS is_shared BOOLEAN DEFAULT FALSE;

CREATE INDEX IF NOT EXISTS idx_registries_workspace ON registries(workspace_id);
CREATE INDEX IF NOT EXISTS idx_registries_owner ON registries(owner_id);
CREATE INDEX IF NOT EXISTS idx_registries_is_shared ON registries(is_shared);

-- 删除旧的唯一约束
ALTER TABLE registries DROP CONSTRAINT IF EXISTS registries_name_key;

COMMENT ON COLUMN registries.workspace_id IS '所属工作空间 ID';
COMMENT ON COLUMN registries.owner_id IS '创建者用户 ID';
COMMENT ON COLUMN registries.is_shared IS '是否为共享注册表';

-- ===== 6. 创建 storage_backends 表 =====
CREATE TABLE IF NOT EXISTS storage_backends (
    id VARCHAR(36) PRIMARY KEY,
    workspace_id VARCHAR(36) REFERENCES workspaces(id) ON DELETE CASCADE,
    owner_id VARCHAR(36) REFERENCES users(id),
    name VARCHAR(255) NOT NULL,
    type VARCHAR(50) NOT NULL,  -- 'nfs', 'pv', 'hostPath'
    config JSONB NOT NULL,      -- 存储配置
    description TEXT,
    is_default BOOLEAN DEFAULT FALSE,
    is_shared BOOLEAN DEFAULT FALSE,
    created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
    UNIQUE(workspace_id, name)
);

CREATE INDEX IF NOT EXISTS idx_storage_backends_workspace ON storage_backends(workspace_id);
CREATE INDEX IF NOT EXISTS idx_storage_backends_owner ON storage_backends(owner_id);
CREATE INDEX IF NOT EXISTS idx_storage_backends_type ON storage_backends(type);

COMMENT ON TABLE storage_backends IS '存储后端表 (NFS/PV/HostPath)';
COMMENT ON COLUMN storage_backends.type IS '存储类型: nfs, pv, hostPath';
COMMENT ON COLUMN storage_backends.config IS '存储配置 (JSON)';

-- ===== 7. 创建 chart_references 表 =====
CREATE TABLE IF NOT EXISTS chart_references (
    id VARCHAR(36) PRIMARY KEY,
    workspace_id VARCHAR(36) REFERENCES workspaces(id) ON DELETE CASCADE,
    registry_id VARCHAR(36) REFERENCES registries(id) ON DELETE CASCADE,
    repository VARCHAR(500) NOT NULL,  -- OCI repository path
    chart_name VARCHAR(255) NOT NULL,
    description TEXT,
    is_enabled BOOLEAN DEFAULT TRUE,
    created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
    UNIQUE(workspace_id, registry_id, repository)
);

CREATE INDEX IF NOT EXISTS idx_chart_references_workspace ON chart_references(workspace_id);
CREATE INDEX IF NOT EXISTS idx_chart_references_registry ON chart_references(registry_id);

COMMENT ON TABLE chart_references IS 'Helm Chart 引用表';

-- ===== 8. 创建 values_templates 表 =====
CREATE TABLE IF NOT EXISTS values_templates (
    id VARCHAR(36) PRIMARY KEY,
    workspace_id VARCHAR(36) REFERENCES workspaces(id) ON DELETE CASCADE,
    owner_id VARCHAR(36) REFERENCES users(id),
    chart_reference_id VARCHAR(36) REFERENCES chart_references(id) ON DELETE CASCADE,
    name VARCHAR(255) NOT NULL,
    description TEXT,
    values_yaml TEXT NOT NULL,
    version INTEGER NOT NULL DEFAULT 1,
    is_default BOOLEAN DEFAULT FALSE,
    created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
    UNIQUE(workspace_id, chart_reference_id, name, version)
);

CREATE INDEX IF NOT EXISTS idx_values_templates_workspace ON values_templates(workspace_id);
CREATE INDEX IF NOT EXISTS idx_values_templates_chart ON values_templates(chart_reference_id);
CREATE INDEX IF NOT EXISTS idx_values_templates_name ON values_templates(name);

COMMENT ON TABLE values_templates IS 'Values 模板表（带版本管理）';
COMMENT ON COLUMN values_templates.version IS '模板版本号';

-- ===== 9. 创建 user_config_overrides 表 =====
CREATE TABLE IF NOT EXISTS user_config_overrides (
    id VARCHAR(36) PRIMARY KEY,
    workspace_id VARCHAR(36) REFERENCES workspaces(id) ON DELETE CASCADE,
    user_id VARCHAR(36) REFERENCES users(id),
    target_type VARCHAR(50) NOT NULL,  -- 'storage', 'template', 'global'
    target_id VARCHAR(36),
    config JSONB NOT NULL,             -- 覆盖配置
    priority INTEGER DEFAULT 0,        -- 优先级
    is_active BOOLEAN DEFAULT TRUE,
    created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
);

CREATE INDEX IF NOT EXISTS idx_user_config_overrides_workspace ON user_config_overrides(workspace_id);
CREATE INDEX IF NOT EXISTS idx_user_config_overrides_user ON user_config_overrides(user_id);
CREATE INDEX IF NOT EXISTS idx_user_config_overrides_target ON user_config_overrides(target_type, target_id);

COMMENT ON TABLE user_config_overrides IS '用户配置覆盖表';
COMMENT ON COLUMN user_config_overrides.target_type IS '目标类型: storage, template, global';
COMMENT ON COLUMN user_config_overrides.priority IS '优先级（越高越优先）';

-- ===== 10. 修改 instances 表 =====
ALTER TABLE instances ADD COLUMN IF NOT EXISTS workspace_id VARCHAR(36) REFERENCES workspaces(id) ON DELETE SET NULL;
ALTER TABLE instances ADD COLUMN IF NOT EXISTS owner_id VARCHAR(36) REFERENCES users(id);
ALTER TABLE instances ADD COLUMN IF NOT EXISTS chart_reference_id VARCHAR(36) REFERENCES chart_references(id) ON DELETE SET NULL;
ALTER TABLE instances ADD COLUMN IF NOT EXISTS values_template_id VARCHAR(36) REFERENCES values_templates(id) ON DELETE SET NULL;
ALTER TABLE instances ADD COLUMN IF NOT EXISTS user_override_yaml TEXT;
ALTER TABLE instances ADD COLUMN IF NOT EXISTS cpu_requested DECIMAL(10,2) DEFAULT 0;
ALTER TABLE instances ADD COLUMN IF NOT EXISTS memory_requested VARCHAR(50) DEFAULT '0Mi';
ALTER TABLE instances ADD COLUMN IF NOT EXISTS gpu_requested DECIMAL(10,2) DEFAULT 0;
ALTER TABLE instances ADD COLUMN IF NOT EXISTS gpu_memory_requested VARCHAR(50) DEFAULT '0Mi';

CREATE INDEX IF NOT EXISTS idx_instances_workspace ON instances(workspace_id);
CREATE INDEX IF NOT EXISTS idx_instances_owner ON instances(owner_id);

COMMENT ON COLUMN instances.workspace_id IS '所属工作空间 ID';
COMMENT ON COLUMN instances.owner_id IS '创建者用户 ID';
COMMENT ON COLUMN instances.chart_reference_id IS 'Chart 引用 ID';
COMMENT ON COLUMN instances.values_template_id IS 'Values 模板 ID';
COMMENT ON COLUMN instances.user_override_yaml IS '用户覆盖配置';
COMMENT ON COLUMN instances.cpu_requested IS '请求的 CPU 核数';
COMMENT ON COLUMN instances.memory_requested IS '请求的内存';
COMMENT ON COLUMN instances.gpu_requested IS '请求的 GPU 卡数';
COMMENT ON COLUMN instances.gpu_memory_requested IS '请求的 GPU 内存';

-- ===== 11. 创建 audit_logs 表 =====
CREATE TABLE IF NOT EXISTS audit_logs (
    id VARCHAR(36) PRIMARY KEY,
    workspace_id VARCHAR(36),
    user_id VARCHAR(36) REFERENCES users(id),
    action VARCHAR(100) NOT NULL,       -- 'create', 'update', 'delete', 'deploy', 'scale'
    resource_type VARCHAR(50) NOT NULL, -- 'cluster', 'registry', 'instance', 'quota', 'user', 'workspace'
    resource_id VARCHAR(36),
    resource_name VARCHAR(255),
    details JSONB,
    ip_address VARCHAR(50),
    user_agent TEXT,
    created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
);

CREATE INDEX IF NOT EXISTS idx_audit_logs_workspace ON audit_logs(workspace_id);
CREATE INDEX IF NOT EXISTS idx_audit_logs_user ON audit_logs(user_id);
CREATE INDEX IF NOT EXISTS idx_audit_logs_action ON audit_logs(action);
CREATE INDEX IF NOT EXISTS idx_audit_logs_resource ON audit_logs(resource_type, resource_id);
CREATE INDEX IF NOT EXISTS idx_audit_logs_created ON audit_logs(created_at);

COMMENT ON TABLE audit_logs IS '审计日志表';
COMMENT ON COLUMN audit_logs.action IS '操作类型: create, update, delete, deploy, scale';
COMMENT ON COLUMN audit_logs.resource_type IS '资源类型: cluster, registry, instance, quota, user, workspace';

-- ===== 12. 插入迁移版本 =====
INSERT INTO schema_migrations (version) VALUES ('v2.0.0')
ON CONFLICT (version) DO NOTHING;

-- ===== 13. 更新现有 admin 用户为 admin 角色 =====
UPDATE users SET role = 'admin', workspace_id = NULL WHERE username = 'admin' AND role = 'user';

-- ===== 14. 创建默认 workspace（可选，用于旧数据兼容）=====
-- 如果需要将现有数据迁移到默认 workspace，取消下面注释
-- INSERT INTO workspaces (id, name, description)
-- VALUES (gen_random_uuid(), 'default', '默认工作空间')
-- ON CONFLICT (name) DO NOTHING;
--
-- UPDATE clusters SET workspace_id = (SELECT id FROM workspaces WHERE name = 'default')
-- WHERE workspace_id IS NULL;
--
-- UPDATE registries SET workspace_id = (SELECT id FROM workspaces WHERE name = 'default')
-- WHERE workspace_id IS NULL;
--
-- UPDATE instances SET workspace_id = (SELECT id FROM workspaces WHERE name = 'default')
-- WHERE workspace_id IS NULL;

-- ===== 迁移完成 =====
DO $$
BEGIN
    RAISE NOTICE 'Migration v2.0.0 completed successfully!';
END $$;