package admin import ( "context" "database/sql" ) func RunAdminMigrations(ctx context.Context, db *sql.DB) error { migrations := []string{ `CREATE TABLE IF NOT EXISTS users ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), email VARCHAR(255) NOT NULL UNIQUE, password_hash VARCHAR(255) NOT NULL, display_name VARCHAR(255) NOT NULL, avatar_url TEXT, role VARCHAR(50) NOT NULL DEFAULT 'user', tier VARCHAR(50) NOT NULL DEFAULT 'free', is_active BOOLEAN NOT NULL DEFAULT true, last_login_at TIMESTAMPTZ, created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW() )`, `CREATE INDEX IF NOT EXISTS idx_users_email ON users(email)`, `CREATE INDEX IF NOT EXISTS idx_users_role ON users(role)`, `CREATE INDEX IF NOT EXISTS idx_users_is_active ON users(is_active)`, `CREATE TABLE IF NOT EXISTS posts ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), title VARCHAR(500) NOT NULL, slug VARCHAR(255) NOT NULL UNIQUE, content TEXT NOT NULL, excerpt TEXT, cover_image TEXT, author_id UUID REFERENCES users(id) ON DELETE SET NULL, category VARCHAR(100) NOT NULL DEFAULT 'general', tags JSONB DEFAULT '[]', status VARCHAR(50) NOT NULL DEFAULT 'draft', view_count INT NOT NULL DEFAULT 0, published_at TIMESTAMPTZ, created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW() )`, `CREATE INDEX IF NOT EXISTS idx_posts_slug ON posts(slug)`, `CREATE INDEX IF NOT EXISTS idx_posts_author ON posts(author_id)`, `CREATE INDEX IF NOT EXISTS idx_posts_status ON posts(status)`, `CREATE INDEX IF NOT EXISTS idx_posts_category ON posts(category)`, `CREATE INDEX IF NOT EXISTS idx_posts_published_at ON posts(published_at DESC)`, `CREATE TABLE IF NOT EXISTS platform_settings ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), site_name VARCHAR(255) NOT NULL DEFAULT 'GooSeek', site_url VARCHAR(500) NOT NULL DEFAULT 'https://gooseek.ru', logo_url TEXT, favicon_url TEXT, description TEXT, support_email VARCHAR(255), features JSONB NOT NULL DEFAULT '{}', llm_settings JSONB NOT NULL DEFAULT '{}', search_settings JSONB NOT NULL DEFAULT '{}', metadata JSONB DEFAULT '{}', updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW() )`, `CREATE TABLE IF NOT EXISTS discover_categories ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), name VARCHAR(100) NOT NULL UNIQUE, name_ru VARCHAR(100) NOT NULL, icon VARCHAR(10) NOT NULL DEFAULT '📰', color VARCHAR(20) NOT NULL DEFAULT '#6B7280', keywords JSONB NOT NULL DEFAULT '[]', regions JSONB NOT NULL DEFAULT '["world"]', is_active BOOLEAN NOT NULL DEFAULT true, sort_order INT NOT NULL DEFAULT 0, created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW() )`, `CREATE INDEX IF NOT EXISTS idx_discover_categories_name ON discover_categories(name)`, `CREATE INDEX IF NOT EXISTS idx_discover_categories_sort ON discover_categories(sort_order)`, `CREATE TABLE IF NOT EXISTS discover_sources ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), name VARCHAR(255) NOT NULL, url VARCHAR(500) NOT NULL UNIQUE, logo_url TEXT, categories JSONB NOT NULL DEFAULT '[]', trust_score DECIMAL(3,2) NOT NULL DEFAULT 0.5, is_active BOOLEAN NOT NULL DEFAULT true, description TEXT, created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW() )`, `CREATE INDEX IF NOT EXISTS idx_discover_sources_url ON discover_sources(url)`, `CREATE INDEX IF NOT EXISTS idx_discover_sources_trust ON discover_sources(trust_score DESC)`, `CREATE TABLE IF NOT EXISTS audit_logs ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), user_id UUID NOT NULL, user_email VARCHAR(255) NOT NULL, action VARCHAR(100) NOT NULL, resource VARCHAR(100) NOT NULL, resource_id VARCHAR(255), details JSONB, ip_address VARCHAR(45), user_agent TEXT, created_at TIMESTAMPTZ NOT NULL DEFAULT NOW() )`, `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)`, `CREATE INDEX IF NOT EXISTS idx_audit_logs_created ON audit_logs(created_at DESC)`, `CREATE TABLE IF NOT EXISTS connectors ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), type VARCHAR(50) NOT NULL, name VARCHAR(255) NOT NULL, config JSONB NOT NULL DEFAULT '{}', is_active BOOLEAN NOT NULL DEFAULT true, last_sync_at TIMESTAMPTZ, status VARCHAR(50) NOT NULL DEFAULT 'pending', error_msg TEXT, created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW() )`, `CREATE INDEX IF NOT EXISTS idx_connectors_type ON connectors(type)`, `CREATE INDEX IF NOT EXISTS idx_connectors_status ON connectors(status)`, `CREATE TABLE IF NOT EXISTS user_files ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), user_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE, filename VARCHAR(500) NOT NULL, original_name VARCHAR(500) NOT NULL, file_type VARCHAR(100) NOT NULL, file_size BIGINT NOT NULL, bucket VARCHAR(100) NOT NULL DEFAULT 'user-files', storage_key TEXT NOT NULL, mime_type VARCHAR(100), metadata JSONB DEFAULT '{}', is_public BOOLEAN NOT NULL DEFAULT false, created_at TIMESTAMPTZ NOT NULL DEFAULT NOW() )`, `CREATE INDEX IF NOT EXISTS idx_user_files_user ON user_files(user_id)`, `CREATE INDEX IF NOT EXISTS idx_user_files_type ON user_files(file_type)`, `CREATE INDEX IF NOT EXISTS idx_user_files_bucket ON user_files(bucket)`, } for _, migration := range migrations { if _, err := db.ExecContext(ctx, migration); err != nil { return err } } return nil }