# Facebook Integration Implementation Guide

**Phase 9A: Facebook Integration** — Complete Multi-Platform Posting  
**Status:** Backend ✅ Complete | Frontend ⏳ Next  
**Date:** June 5, 2026

---

## 🎯 What We Built

### Backend (✅ Completed)
1. **Database Support**
   - Multi-platform post tracking (`post_platforms` table)
   - Facebook account storage (`facebook_page_id`, `facebook_page_token`)
   - Foundation for analytics, webhooks, emails, API keys

2. **Facebook Services**
   - `publishToFacebook()` — Post images to Facebook Pages
   - `getUserPages()` — List user's connected Facebook Pages
   - `getPageInsights()` — Fetch engagement metrics (Phase D)
   - Webhook signature verification (Phase C)

3. **API Endpoints**
   - `/api/facebook/auth-url` — OAuth redirect
   - `/api/facebook/callback` — OAuth callback handler
   - `/api/facebook/status` — Check connection status
   - `/api/facebook/disconnect` — Remove connection
   - `/api/facebook/pages` — List pages
   - `/api/facebook/select-page` — Change active page
   - `/api/facebook/webhook` — Receive real-time events

4. **Multi-Platform Publishing**
   - `publishToMultiplePlatforms()` — Publish to Instagram + Facebook simultaneously
   - Atomic transactions (all succeed or all fail)
   - Per-platform error handling and logging
   - Platform-specific status tracking

---

## 🚀 What's Next: Frontend Implementation

### 1. **Settings Page: Facebook Connection**

**Location:** `frontend/pages/settings.js`

**Add Section:**
```jsx
{/* Facebook Connection */}
<div className="card animate-scale-in">
  <h2 className="card-title flex items-center gap-2">
    <span>📘</span> Facebook Connection
  </h2>
  
  {facebookConnected ? (
    <div>
      <div className="flex items-center gap-3 p-4 bg-blue-600/10 border border-blue-600/30 rounded-lg mb-4">
        <span className="text-2xl">✅</span>
        <div>
          <p className="text-blue-300 font-medium">Facebook Connected</p>
          <p className="text-blue-400/70 text-sm">Page: {facebookPageName}</p>
        </div>
      </div>
      <div className="flex gap-3">
        <button onClick={handleReconnectFacebook} className="btn-secondary text-sm">
          🔄 Reconnect
        </button>
        <button onClick={handleDisconnectFacebook} className="btn-destructive text-sm">
          Disconnect
        </button>
      </div>
    </div>
  ) : (
    <div>
      <div className="flex items-center gap-3 p-4 bg-gray-600/10 border border-gray-600/30 rounded-lg mb-4">
        <span className="text-2xl">📵</span>
        <div>
          <p className="text-gray-300 font-medium">Not Connected</p>
          <p className="text-gray-500 text-sm">Connect Facebook to post to your Pages</p>
        </div>
      </div>
      <button onClick={handleConnectFacebook} className="btn-primary flex items-center gap-2">
        <span>📘</span>
        <span>Connect Facebook Page</span>
      </button>
    </div>
  )}
</div>
```

**API Integration:**
```javascript
const handleConnectFacebook = async () => {
  try {
    const res = await fetch('/api/facebook/auth-url', {
      headers: { Authorization: `Bearer ${token}` }
    });
    const { authUrl } = await res.json();
    window.location.href = authUrl; // Redirect to Facebook OAuth
  } catch (err) {
    toast.error('Failed to get Facebook auth URL');
  }
};

const handleDisconnectFacebook = async () => {
  if (!confirm('Disconnect Facebook?')) return;
  try {
    await fetch('/api/facebook/disconnect', {
      method: 'POST',
      headers: { Authorization: `Bearer ${token}` }
    });
    setFacebookConnected(false);
    toast.success('Facebook disconnected');
  } catch (err) {
    toast.error('Failed to disconnect');
  }
};
```

---

### 2. **Create Post Page: Platform Selector**

**Location:** `frontend/pages/posts/create.js`

**Add Before Action Buttons:**
```jsx
{/* Platform Selection */}
<div className="form-group mb-6">
  <label className="label" htmlFor="platforms">Select Platforms</label>
  <div className="space-y-2">
    <label className="flex items-center gap-3 p-3 border border-gray-700 rounded-lg cursor-pointer hover:bg-dark-800 transition-colors">
      <input
        type="checkbox"
        value="instagram"
        checked={selectedPlatforms.includes('instagram')}
        onChange={(e) => {
          if (e.target.checked) {
            setSelectedPlatforms([...selectedPlatforms, 'instagram']);
          } else {
            setSelectedPlatforms(selectedPlatforms.filter(p => p !== 'instagram'));
          }
        }}
        className="w-4 h-4 rounded"
      />
      <div>
        <p className="font-medium text-gray-200">📸 Instagram</p>
        <p className="text-xs text-gray-500">Post to your Instagram Business account</p>
      </div>
    </label>

    {facebookConnected && (
      <label className="flex items-center gap-3 p-3 border border-gray-700 rounded-lg cursor-pointer hover:bg-dark-800 transition-colors">
        <input
          type="checkbox"
          value="facebook"
          checked={selectedPlatforms.includes('facebook')}
          onChange={(e) => {
            if (e.target.checked) {
              setSelectedPlatforms([...selectedPlatforms, 'facebook']);
            } else {
              setSelectedPlatforms(selectedPlatforms.filter(p => p !== 'facebook'));
            }
          }}
          className="w-4 h-4 rounded"
        />
        <div>
          <p className="font-medium text-gray-200">📘 Facebook</p>
          <p className="text-xs text-gray-500">Post to {facebookPageName}</p>
        </div>
      </label>
    )}
  </div>
  {!facebookConnected && (
    <p className="text-xs text-gray-500 mt-2">
      Connect Facebook in Settings to enable multi-platform posting
    </p>
  )}
</div>
```

**Update Post Creation Handler:**
```javascript
const handleSchedulePost = async () => {
  if (selectedPlatforms.length === 0) {
    toast.error('Select at least one platform');
    return;
  }

  const formData = new FormData();
  formData.append('caption', buildFullCaption());
  formData.append('platforms', JSON.stringify(selectedPlatforms)); // Pass array
  if (image) formData.append('image', image);
  else if (generatedPoster) formData.append('imageUrl', generatedPoster);

  // ... rest of post creation
};
```

---

### 3. **Dashboard: Platform Indicators**

**Location:** `frontend/pages/dashboard.js`

**Update Post Card to Show Platform Status:**
```jsx
{posts.map((post) => (
  <div key={post.id} className="card">
    {/* ... existing post info ... */}
    
    {/* Platform Status */}
    <div className="mt-3 pt-3 border-t border-gray-700/50 flex gap-2">
      {post.platforms?.includes('instagram') && (
        <span className="text-xs px-2 py-1 rounded-full bg-pink-600/20 text-pink-300 border border-pink-600/30">
          📸 Instagram
        </span>
      )}
      {post.platforms?.includes('facebook') && (
        <span className="text-xs px-2 py-1 rounded-full bg-blue-600/20 text-blue-300 border border-blue-600/30">
          📘 Facebook
        </span>
      )}
    </div>
  </div>
))}
```

---

### 4. **Quick Post: Multi-Platform Support**

**Location:** `frontend/pages/quick-post.js`

**Add After Template Selection:**
```jsx
{/* Platform Selection for Quick Post */}
<div className="card animate-scale-in" style={{ animationDelay: '150ms' }}>
  <h3 className="card-title flex items-center gap-2">🌍 Publish To</h3>
  
  <div className="flex gap-3 mt-4">
    <label className="flex items-center gap-2 p-3 flex-1 border border-gray-700 rounded-lg cursor-pointer hover:bg-dark-800">
      <input
        type="checkbox"
        checked={quickPostPlatforms.includes('instagram')}
        onChange={(e) => {
          if (e.target.checked) {
            setQuickPostPlatforms([...quickPostPlatforms, 'instagram']);
          } else {
            setQuickPostPlatforms(quickPostPlatforms.filter(p => p !== 'instagram'));
          }
        }}
        className="w-4 h-4"
      />
      <span className="text-sm font-medium">📸 Instagram</span>
    </label>

    {facebookConnected && (
      <label className="flex items-center gap-2 p-3 flex-1 border border-gray-700 rounded-lg cursor-pointer hover:bg-dark-800">
        <input
          type="checkbox"
          checked={quickPostPlatforms.includes('facebook')}
          onChange={(e) => {
            if (e.target.checked) {
              setQuickPostPlatforms([...quickPostPlatforms, 'facebook']);
            } else {
              setQuickPostPlatforms(quickPostPlatforms.filter(p => p !== 'facebook'));
            }
          }}
          className="w-4 h-4"
        />
        <span className="text-sm font-medium">📘 Facebook</span>
      </label>
    )}
  </div>
</div>
```

---

## 🧪 Testing Checklist

### API Testing (Backend)
- [ ] Run migrations: `psql -U postgres haznox_prod -f migrations/004_add_facebook_support.sql`
- [ ] Install new deps: `npm install` (bull, qrcode, speakeasy, nodemailer, handlebars)
- [ ] Test Facebook OAuth: Visit `/api/facebook/auth-url` → should redirect to Facebook
- [ ] Test callback: After OAuth approval → should store in social_accounts
- [ ] Test disconnect: POST `/api/facebook/disconnect` → should remove record
- [ ] Test multi-platform publish: Send post with `platforms: ["instagram", "facebook"]`

### Manual Testing (UI)
- [ ] Click "Connect Facebook" in Settings
- [ ] Authorize with test Facebook account
- [ ] Verify page name displays in Settings
- [ ] Create post with both platforms selected
- [ ] Verify post appears on both Instagram and Facebook
- [ ] Test publishing only to Facebook
- [ ] Test disconnecting Facebook

### Error Scenarios
- [ ] Facebook token expired — should give clear error
- [ ] Instagram only connected, try to post to both — should still post to IG
- [ ] Facebook only connected, try to post to both — should still post to FB
- [ ] Invalid image URL — should fail gracefully

---

## 📊 Database Verification

After migration, verify the new tables:

```sql
-- Check post_platforms table
SELECT * FROM post_platforms;

-- Check social_accounts for Facebook data
SELECT user_id, platform, facebook_page_id, facebook_page_name FROM social_accounts WHERE platform = 'facebook';

-- Check post_analytics table exists
SELECT COUNT(*) FROM post_analytics;

-- Check webhook tables
SELECT COUNT(*) FROM webhooks;
SELECT COUNT(*) FROM webhook_logs;

-- Check email and notification tables
SELECT COUNT(*) FROM email_logs;
SELECT COUNT(*) FROM notifications;

-- Check API keys table
SELECT COUNT(*) FROM api_keys;
```

---

## 🔄 Deployment Steps

### Step 1: Backend
```bash
cd backend
npm install  # Install new dependencies
pm2 restart haznox-api  # Or: node app.js
```

### Step 2: Database
```bash
# Login to your database
psql -U postgres haznox_prod

# Run migration
\i migrations/004_add_facebook_support.sql

# Verify tables created
\dt  # List all tables
```

### Step 3: Environment Variables
Update your `.env`:
```env
# Already set from Instagram setup
META_APP_ID=your_app_id
META_APP_SECRET=your_app_secret
META_REDIRECT_URI=https://api.yourdomain.com/api/facebook/callback

# For webhook verification (Phase C)
FACEBOOK_WEBHOOK_VERIFY_TOKEN=your_webhook_verify_token
```

### Step 4: Frontend
```bash
cd frontend
npm run dev  # Test locally
npm run build  # Production build
```

### Step 5: Test Flow
1. Go to Settings → Facebook Connection
2. Click "Connect Facebook Page"
3. Authorize with Facebook account
4. Should see page name displayed
5. Create post → select both platforms
6. Publish → should appear on both IG and FB

---

## 🐛 Troubleshooting

### "No Facebook Pages found"
- **Cause:** User is not admin of any Facebook Pages
- **Fix:** Create a Facebook Page or make user an admin

### "Failed to publish to Facebook"
- **Cause:** Page token expired or insufficient permissions
- **Fix:** Disconnect and reconnect Facebook account

### "Instagram published but Facebook failed"
- **Cause:** Facebook Page token may have different permissions
- **Fix:** Check page token has `pages_manage_posts` permission

### "Webhook not receiving events"
- **Cause:** Webhook URL not set in Facebook App settings
- **Fix:** Go to Facebook Developer App → Settings → Webhooks
  - Callback URL: `https://api.yourdomain.com/api/facebook/webhook`
  - Verify Token: Your `FACEBOOK_WEBHOOK_VERIFY_TOKEN`
  - Subscribe to: `feed`, `instagram_comment`

---

## 📈 Phase A Progress

**What's Complete:**
- ✅ Database schema for 6 phases
- ✅ Facebook service layer
- ✅ Multi-platform publishing logic
- ✅ API routes for OAuth & management
- ✅ Package.json dependencies updated
- ✅ App.js integration

**What's Next:**
- ⏳ Frontend components (Settings, Create Post, Dashboard)
- ⏳ Facebook API testing
- ⏳ E2E testing with real Facebook account
- ⏳ Phase B: Two-Factor Authentication
- ⏳ Phase C: Webhooks
- ⏳ Phase D: Analytics
- ⏳ Phase E: Email Notifications
- ⏳ Phase F: API Keys

---

## 🎓 Architecture Overview

```
User Flow:
1. User clicks "Connect Facebook" in Settings
2. Redirects to /api/facebook/auth-url
3. Facebook OAuth dialog opens
4. User authorizes → redirects to callback
5. Callback stores page token in social_accounts
6. User creates post and selects both platforms
7. publishToMultiplePlatforms() called
8. Posts simultaneously to Instagram + Facebook
9. Platform-specific status tracked in post_platforms table

Database:
social_accounts
├─ instagram_id + access_token (Instagram)
└─ facebook_page_id + facebook_page_token (Facebook)

posts
├─ caption, image_url (shared)
└─ platforms: ["instagram", "facebook"]

post_platforms (new)
├─ post_id + platform (unique)
├─ media_id (platform-specific post ID)
├─ status (draft/scheduled/published/failed)
└─ error_message
```

---

## 📞 Support

### Common Questions

**Q: Can users have multiple Facebook Pages?**  
A: Yes! The UI currently selects the first page, but users can switch with POST `/api/facebook/select-page`

**Q: What if Instagram publish succeeds but Facebook fails?**  
A: Post status shows as "partially published". Admin can retry Facebook separately.

**Q: Does this work with Facebook Business Accounts?**  
A: Yes! Works with any Page the user has admin access to.

**Q: How often are webhooks processed?**  
A: Real-time when Meta sends them. If missed, Phase D analytics will sync on schedule.

---

**Status:** Phase 9A Backend Complete ✅  
**Next:** Implement frontend components, test E2E, move to Phase B (2FA)

