# YouTube Service - Repair Video Integration

## Overview

The YouTube service searches YouTube for repair videos and extracts transcripts. It uses **MODEL-level caching** to conserve API quota and provides quota tracking to prevent exhaustion.

## Setup

### 1. Get YouTube Data API v3 Key

1. Go to [Google Cloud Console](https://console.cloud.google.com/)
2. Create a new project or select existing
3. Enable **YouTube Data API v3**
4. Create credentials (API key)
5. Restrict key to YouTube Data API v3 (recommended)

### 2. Configure Environment

Add to your `.env` file:

```bash
YOUTUBE_API_KEY=your_api_key_here
```

### 3. Install Dependencies

Already installed via:
```bash
npm install youtube-transcript googleapis
```

## Usage

### Get Videos for a Model

```javascript
import youtubeService from './services/youtubeService.js';

const videos = await youtubeService.getVideosForModel('A2338');

console.log(videos);
// [
//   {
//     id: '507f1f77bcf86cd799439011',
//     source: 'youtube',
//     title: 'MacBook Air M1 Screen Replacement',
//     url: 'https://www.youtube.com/watch?v=...',
//     summary: 'In this video we show you how to...',
//     difficulty: 'Moderate',
//     attribution: 'Video from iFixit on YouTube',
//     fetchedAt: '2025-02-03T10:30:00.000Z'
//   },
//   ...
// ]
```

### Check Quota Usage

```javascript
const quota = await youtubeService.getQuotaUsage();

console.log(quota);
// {
//   used: 101,
//   limit: 10000,
//   remaining: 9899,
//   percentUsed: 1,
//   warning: false,
//   exhausted: false
// }
```

### Reset Quota Counter (Testing Only)

```javascript
youtubeService.resetQuota();
// Note: Actual YouTube quota resets at midnight Pacific Time
```

## Quota Management

### Daily Limits

- **Total quota**: 10,000 units/day
- **Resets**: Midnight Pacific Time (automatic)
- **Warning threshold**: 8,000 units (80%)

### Operation Costs

| Operation | Cost | Notes |
|-----------|------|-------|
| Search videos | 100 units | Most expensive |
| Get video details | 1 unit | Batch request |
| Extract transcript | 0 units | Uses youtube-transcript package |
| **Total per model** | **101 units** | ~99 models/day max |

### Quota Tracking

The service tracks quota usage in-memory:

```javascript
// Automatic tracking on each API call
const videos = await youtubeService.getVideosForModel('A2338');
// Quota used: 101 units

// Check current usage
const quota = await youtubeService.getQuotaUsage();
console.log(`Used: ${quota.used}/${quota.limit}`);
```

### Quota Warnings

- **80% usage**: Warning logged automatically
- **100% usage**: Throws error with reset time info

```javascript
// At 80% usage:
// ⚠️ YouTube API quota at 80% (8000/10000)

// At 100% usage:
// ❌ YouTube API quota exhausted. Resets at midnight Pacific Time.
```

## Caching Strategy

### MODEL-Level Caching

Videos are cached at the **MODEL level** (not per-diagnosis) to maximize cache hits and minimize API calls.

```javascript
// First call: Fetches from YouTube API (costs 101 units)
const videos1 = await youtubeService.getVideosForModel('A2338');

// Second call: Returns from cache (costs 0 units)
const videos2 = await youtubeService.getVideosForModel('A2338');
```

### Cache TTL

- **Duration**: 7 days
- **Auto-refresh**: Expired cache is automatically refreshed on next request
- **Storage**: MongoDB using Tutorial model with source: 'youtube'

### Cache Structure

```javascript
{
  modelId: ObjectId('...'),
  source: 'youtube',
  title: 'MacBook Air M1 Screen Replacement',
  url: 'https://www.youtube.com/watch?v=...',
  summary: 'In this video we show you how to...',
  difficulty: 'Moderate',
  tools: [],
  steps: 0,
  attribution: 'Video from iFixit on YouTube',
  fetchedAt: Date,
  expiresAt: Date
}
```

## Video Selection

### Preferred Channels

Videos from these channels are ranked higher:

1. **Louis Rossmann** - Expert MacBook repairs
2. **iFixit** - Official repair guides
3. **JerryRigEverything** - Teardowns and repairs

### Filtering

- **Duration**: Medium videos (4-20 minutes)
- **Max results**: 5 videos per model
- **Sorting**: Preferred channels first, then by view count

### Search Query

Built from model brand + name:

```javascript
// For model "A2338" with brand "Apple"
const searchQuery = "Apple A2338 repair";
```

## Transcript Extraction

### How It Works

1. Fetch video captions using `youtube-transcript` package
2. Combine all transcript text
3. Summarize to first 500 characters
4. Store in `summary` field

### No Quota Cost

Transcript extraction uses the `youtube-transcript` package, which **does not consume YouTube API quota**.

### Fallback

If transcript is unavailable:
- Falls back to video description
- Logs warning but continues
- Does not break main flow

## Testing

### Run Test Script

```bash
node Backend/test/test_youtube_service.js
```

### Expected Output

```
🧪 Starting YouTube service test
✅ Connected to MongoDB

=== Test 1: First fetch (should call YouTube API) ===
📹 Searching YouTube: "Apple A2338 repair"
✅ Found 5 videos in 2341ms
📹 First video: "MacBook Air M1 Screen Replacement"
🔗 URL: https://www.youtube.com/watch?v=...
ℹ️ Attribution: Video from iFixit on YouTube

=== Test 2: Second fetch (should use cache) ===
⚡ Returning 5 cached YouTube videos for model: A2338
✅ Found 5 videos in 6ms
🚀 Cache speedup: 390x faster

=== Test 3: Quota usage ===
📊 YouTube API quota: 101/10000 (1%)
ℹ️ Remaining: 9899 units

=== Test 4: Verify cache structure ===
ℹ️ Videos have required fields:
ℹ️ - id: true
ℹ️ - title: true
ℹ️ - url: true
ℹ️ - source: true
ℹ️ - attribution: true

✅ All tests passed!
🎉 YouTube service is working correctly
```

### Manual Testing

```javascript
import youtubeService from './services/youtubeService.js';

// Test 1: Get videos
const videos = await youtubeService.getVideosForModel('A2338');
console.log(`Found ${videos.length} videos`);

// Test 2: Check quota
const quota = await youtubeService.getQuotaUsage();
console.log(`Quota: ${quota.used}/${quota.limit}`);

// Test 3: Verify cache
const cached = await youtubeService.getVideosForModel('A2338');
console.log(`Cache hit: ${cached.length > 0}`);
```

## Error Handling

### Quota Exhausted

```javascript
try {
  const videos = await youtubeService.getVideosForModel('A2338');
} catch (error) {
  // Error: YouTube API quota exhausted. Resets at midnight Pacific Time.
}
```

### Model Not Found

```javascript
const videos = await youtubeService.getVideosForModel('INVALID');
// Returns: []
// Logs: ⚠️ Model not found: INVALID
```

### API Failure

```javascript
try {
  const videos = await youtubeService.getVideosForModel('A2338');
} catch (error) {
  // Error: YouTube search failed: [API error message]
}
```

### Transcript Failure

```javascript
// Non-blocking: transcript failures don't break main flow
const videos = await youtubeService.getVideosForModel('A2338');
// Logs: ⚠️ Failed to fetch transcript for video XYZ: [error]
// Returns: Videos with empty summary or description fallback
```

## Integration

### With AI Diagnosis Tools (Task 8)

```javascript
import youtubeService from './services/youtubeService.js';

const videos = await youtubeService.getVideosForModel(ticket.model.name);

const aiPrompt = `
Repair videos available:
${videos.map(v => `- ${v.title}: ${v.url}`).join('\n')}

Provide repair guidance based on these resources.
`;
```

### With Tutorial Service (Task 4)

Both services use the same Tutorial model:

```javascript
// Get all tutorials (iFixit + YouTube)
const tutorials = await Tutorial.find({ modelId: model._id });

// Filter by source
const ifixitGuides = tutorials.filter(t => t.source === 'ifixit');
const youtubeVideos = tutorials.filter(t => t.source === 'youtube');
```

## Best Practices

### 1. Check Quota Before Bulk Operations

```javascript
const quota = await youtubeService.getQuotaUsage();

if (quota.remaining < 500) {
  console.warn('Low quota remaining, skipping bulk operation');
  return;
}

// Proceed with bulk operation
```

### 2. Use Cache Whenever Possible

```javascript
// Good: Reuses cache for same model
const videos = await youtubeService.getVideosForModel('A2338');

// Bad: Bypassing cache (not supported - always uses cache)
```

### 3. Monitor Quota Usage

```javascript
// Log quota after operations
const videos = await youtubeService.getVideosForModel('A2338');
const quota = await youtubeService.getQuotaUsage();
console.log(`Quota: ${quota.percentUsed}%`);
```

### 4. Handle Quota Exhaustion Gracefully

```javascript
try {
  const videos = await youtubeService.getVideosForModel('A2338');
} catch (error) {
  if (error.message.includes('quota exhausted')) {
    // Fall back to cached data or iFixit only
    const cached = await Tutorial.find({ 
      modelId: model._id, 
      source: 'youtube' 
    });
    return cached;
  }
  throw error;
}
```

## Troubleshooting

### "API key not configured"

**Problem**: `YOUTUBE_API_KEY` not set in `.env`

**Solution**:
1. Get API key from Google Cloud Console
2. Add to `.env`: `YOUTUBE_API_KEY=your_key_here`
3. Restart backend

### "Quota exhausted"

**Problem**: Daily quota limit reached (10,000 units)

**Solution**:
1. Wait until midnight Pacific Time for automatic reset
2. Use cached data in the meantime
3. Consider requesting quota increase from Google

### "No videos found"

**Problem**: No YouTube videos match the search query

**Solution**:
1. Check model name is correct
2. Try broader search terms
3. Fall back to iFixit tutorials

### "Transcript unavailable"

**Problem**: Video doesn't have captions

**Solution**:
- Service automatically falls back to video description
- Non-blocking: other videos still work
- No action needed

## Monitoring

### Quota Usage Dashboard

```javascript
const quota = await youtubeService.getQuotaUsage();

console.log(`
YouTube API Quota Status:
- Used: ${quota.used}/${quota.limit} (${quota.percentUsed}%)
- Remaining: ${quota.remaining} units
- Warning: ${quota.warning ? 'YES' : 'NO'}
- Exhausted: ${quota.exhausted ? 'YES' : 'NO'}
`);
```

### Cache Hit Rate

```javascript
// Track cache hits vs API calls
let cacheHits = 0;
let apiCalls = 0;

const videos = await youtubeService.getVideosForModel('A2338');
// Check logs for "Returning cached" vs "Fetching from YouTube"

console.log(`Cache hit rate: ${(cacheHits / (cacheHits + apiCalls)) * 100}%`);
```

## Future Enhancements

### Planned Features

1. **MeiliSearch indexing** - Typo-tolerant video search
2. **AI transcript analysis** - Extract tools/steps from transcripts
3. **Video quality scoring** - Rank by repair success indicators
4. **Playlist support** - Fetch entire repair playlists
5. **Thumbnail caching** - Store thumbnails locally

### Quota Optimization

1. **Batch requests** - Fetch videos for multiple models in one call
2. **Longer TTL** - Increase cache duration for stable content
3. **Selective refresh** - Only refresh expired entries, not all
4. **Quota pooling** - Share quota across multiple API keys

## References

- [YouTube Data API v3 Documentation](https://developers.google.com/youtube/v3)
- [Quota Calculator](https://developers.google.com/youtube/v3/determine_quota_cost)
- [youtube-transcript Package](https://www.npmjs.com/package/youtube-transcript)
- [googleapis Package](https://www.npmjs.com/package/googleapis)
