# DeepSeek API Integration with PocketBase React Apps

## Pattern

React frontend → nginx `/deepseek/` proxy → `https://api.deepseek.com/` with API key.

## Server Proxy (nginx)

```nginx
location /deepseek/ {
    proxy_pass https://api.deepseek.com/;
    proxy_ssl_server_name on;
    proxy_ssl_name api.deepseek.com;
    proxy_http_version 1.1;
    proxy_set_header Host api.deepseek.com;
    proxy_set_header Authorization "Bearer sk-...";
    proxy_set_header Content-Type "application/json";
    proxy_buffering off;
    proxy_read_timeout 120s;
}
```

## Client Module (`src/lib/ai.ts`)

Core fetch helper — all AI calls go through this:

```typescript
async function callDeepSeek(
  systemPrompt: string,
  userContent: string,
  maxTokens = 500,
  temperature = 0,
): Promise<string | null> {
  const res = await fetch('/deepseek/v1/chat/completions', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({
      model: 'deepseek-v4-flash',
      messages: [
        { role: 'system', content: systemPrompt },
        { role: 'user', content: userContent },
      ],
      temperature,
      thinking: { type: 'disabled' as const },
      max_tokens: maxTokens,
    }),
  });
  if (!res.ok) return null;
  const data = await res.json();
  return data?.choices?.[0]?.message?.content || null;
}
```

**Critical:** Set `thinking: { type: 'disabled' }` — without it, `deepseek-v4-flash` spends all token budget on reasoning content and returns empty `content`.

## Three Functions We Built

### 1. AI Write Explanation — generates professional customer-facing service descriptions

```typescript
export async function aiWriteExplanation(
  params: ExplanationParams,
): Promise<ExplanationResult | null>
```

Takes `serviceName`, `recommendation`, optional `technicianNotes`, `vehicleInfo`, `mileage`, `maintenanceInterval`. Returns `{level: 'CRITICAL'|'RECOMMENDED'|'OPTIONAL'|'PREVENTIVE'|'MAINTENANCE', explanation: string}`.

Parses `LEVEL:` and `EXPLANATION:` from the AI response.

### 2. Generate Priorities — ranks services by safety criticality

```typescript
export async function getPriorityAnalysis(
  services: ServiceItem[],
): Promise<PriorityResult[] | null>
```

Returns `{name, rank, priority_reason}[]` sorted by rank. AI prompt forces safety-first ordering: CRITICAL_SAFETY > SAFETY_CONCERN > RECOMMENDED > MAINTENANCE > OPTIONAL.

### 3. AI Suggest Services — recommends services from catalog based on vehicle + mileage

```typescript
export async function aiSuggestServices(
  vehicle: SuggestVehicle,
  selectedServices: string[],
  catalog: CatalogItem[],
): Promise<SuggestResult[] | null>
```

Only returns services that exist in the provided catalog (cross-references by name). Uses mileage-based maintenance intervals.

## Response Parsing Safety

Always strip markdown code blocks before JSON parsing:

```typescript
function stripCodeBlocks(text: string): string {
  return text.trim().replace(/```json\s*/gi, '').replace(/```\s*/g, '').trim();
}
```

All functions return `null` on failure (not throwing) so callers can handle gracefully with toast notifications.

## Fallback: Local Ollama

If the DeepSeek API is unavailable, proxy to Ollama instead. Change the proxy URL and model name:

```nginx
location /deepseek/ {
    proxy_pass http://127.0.0.1:11434/;
    ...
}
```

```typescript
// In ai.ts
model: 'qwen2.5:14b',  // or llava:13b
```

## UI Integration

Add Sparkles/ListOrdered/Lightbulb buttons to the service management UI. Each button:
1. Sets loading state (disables button, shows spinner)
2. Calls the AI function
3. On success: updates the service/quote state, shows success toast
4. On failure: shows error toast, re-enables button
5. Always: re-enables button in finally block
