-- SSO单点登录表结构
-- 创建SSO令牌表
CREATE TABLE IF NOT EXISTS sso_token (
    id BIGSERIAL PRIMARY KEY,
    user_id VARCHAR(50) NOT NULL,
    username VARCHAR(100) NOT NULL,
    token VARCHAR(500) NOT NULL,
    create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    expire_time TIMESTAMP NOT NULL,
    status INTEGER DEFAULT 1,
    last_use_time TIMESTAMP,
    INDEX idx_token (token),
    INDEX idx_user_id (user_id),
    INDEX idx_expire_time (expire_time)
);

-- 创建应用注册表
CREATE TABLE IF NOT EXISTS app_registry (
    id BIGSERIAL PRIMARY KEY,
    app_name VARCHAR(100) NOT NULL UNIQUE,
    app_key VARCHAR(200) NOT NULL UNIQUE,
    app_secret VARCHAR(500) NOT NULL,
    redirect_uri VARCHAR(500) NOT NULL,
    description TEXT,
    status INTEGER DEFAULT 1,
    create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    update_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    admin_user VARCHAR(100),
    INDEX idx_app_key (app_key),
    INDEX idx_status (status)
);

-- 创建SSO访问日志表
CREATE TABLE IF NOT EXISTS sso_access_log (
    id BIGSERIAL PRIMARY KEY,
    user_id VARCHAR(50),
    username VARCHAR(100),
    app_name VARCHAR(100),
    action VARCHAR(50) NOT NULL, -- login, logout, validate, token_exchange
    ip_address VARCHAR(50),
    user_agent TEXT,
    token_used VARCHAR(500),
    status INTEGER DEFAULT 1, -- 1:成功, 0:失败
    error_message TEXT,
    create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    INDEX idx_user_id (user_id),
    INDEX idx_username (username),
    INDEX idx_app_name (app_name),
    INDEX idx_create_time (create_time)
);

-- 创建应用接入记录表
CREATE TABLE IF NOT EXISTS app_access_log (
    id BIGSERIAL PRIMARY KEY,
    app_key VARCHAR(200) NOT NULL,
    app_name VARCHAR(100) NOT NULL,
    client_id VARCHAR(200),
    action VARCHAR(50) NOT NULL, -- register, validate, auth, token_request
    ip_address VARCHAR(50),
    user_agent TEXT,
    request_data TEXT,
    response_data TEXT,
    status INTEGER DEFAULT 1,
    create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    INDEX idx_app_key (app_key),
    INDEX idx_create_time (create_time)
);

-- 创建权限配置表
CREATE TABLE IF NOT EXISTS app_permission (
    id BIGSERIAL PRIMARY KEY,
    app_key VARCHAR(200) NOT NULL,
    permission_name VARCHAR(100) NOT NULL,
    permission_code VARCHAR(200) NOT NULL,
    resource_type VARCHAR(50), -- api, menu, button
    resource_id VARCHAR(200),
    is_enabled INTEGER DEFAULT 1,
    create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    update_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    UNIQUE KEY uk_app_key_permission (app_key, permission_code),
    INDEX idx_app_key (app_key),
    INDEX idx_permission_code (permission_code)
);

-- 创建Token刷新记录表
CREATE TABLE IF NOT EXISTS refresh_token (
    id BIGSERIAL PRIMARY KEY,
    user_id VARCHAR(50) NOT NULL,
    username VARCHAR(100) NOT NULL,
    access_token VARCHAR(500) NOT NULL,
    refresh_token VARCHAR(500) NOT NULL,
    client_id VARCHAR(200) NOT NULL,
    scope VARCHAR(500),
    create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    expire_time TIMESTAMP NOT NULL,
    last_use_time TIMESTAMP,
    is_revoked INTEGER DEFAULT 0,
    INDEX idx_access_token (access_token),
    INDEX idx_refresh_token (refresh_token),
    INDEX idx_user_id (user_id),
    INDEX idx_client_id (client_id)
);

-- 插入默认的OAuth2客户端配置
INSERT INTO app_registry (app_name, app_key, app_secret, redirect_uri, description, admin_user) VALUES
('营收管理前端', 'revenue-frontend', 'revenue-frontend-secret-2026', 'http://localhost:3000/oauth/callback', '营收管理平台前端应用', 'admin'),
('微信网厅', 'wechat-mall', 'wechat-mall-secret-2026', 'http://localhost:8080/wechat/callback', '微信网上营业厅应用', 'admin'),
('移动端应用', 'mobile-app', 'mobile-app-secret-2026', 'http://localhost:4000/auth/callback', '移动端应用', 'admin')
ON CONFLICT (app_name) DO NOTHING;

-- 创建SSO触发器：自动清理过期Token
CREATE OR REPLACE FUNCTION clean_expired_tokens()
RETURNS TRIGGER AS $$
BEGIN
    DELETE FROM sso_token WHERE expire_time < NOW();
    DELETE FROM refresh_token WHERE expire_time < NOW();
    RETURN NEW;
END;
$$ LANGUAGE plpgsql;

-- 创建SSO触发器：当插入token时更新最后使用时间
CREATE OR REPLACE FUNCTION update_last_use_time()
RETURNS TRIGGER AS $$
BEGIN
    IF NEW.status = 1 THEN
        UPDATE sso_token SET last_use_time = NOW() 
        WHERE token = NEW.token AND id != NEW.id;
    END IF;
    RETURN NEW;
END;
$$ LANGUAGE plpgsql;

-- 创建触发器
CREATE TRIGGER trigger_clean_expired_tokens
    BEFORE INSERT OR UPDATE OR DELETE ON sso_token
    EXECUTE FUNCTION clean_expired_tokens();

CREATE TRIGGER trigger_update_last_use_time
    AFTER UPDATE ON sso_token
    FOR EACH ROW
    EXECUTE FUNCTION update_last_use_time();