# Virtual Try-On Feature — Deployment Guide

**Branch:** `feature/virtual-tryon`  
**PR:** #5  
**Date:** 2026-04-11

---

## Prerequisites

- SSH access to the production server (`/var/www/html/moro/`)
- DigitalOcean account access
- Face Swap API account (FaceMint recommended, Segmind also supported)

---

## Step 1: Face Swap API Setup

The system supports multiple face swap providers. Set `FACESWAP_DRIVER` in `.env` to switch.

### Option A: FaceMint (Recommended — $0.002/call)

1. **Register** at https://facemint.io/
2. Get your API key from the dashboard
3. Add to `.env`:

```bash
FACESWAP_DRIVER=facemint
FACEMINT_API_KEY=your-api-key-here
FACEMINT_BASE_URL=https://api.facemint.io
FACEMINT_TIMEOUT=120
```

**Cost:** $0.002/call (~¥0.32). Only charged on success. Monthly estimate: 500 calls = ~$1/month.

### Option B: Segmind ($0.05–$0.12/call)

1. **Register** at https://www.segmind.com/
2. Go to **Settings → API Keys** and create a new key
3. Add to `.env`:

```bash
FACESWAP_DRIVER=segmind
SEGMIND_API_KEY=your-api-key-here
SEGMIND_API_URL=https://api.segmind.com/v1/faceswap-v4
SEGMIND_TIMEOUT=90
```

**Cost:** ~$0.12/call for v4, ~$0.05/call for v5. Monthly estimate: 500 calls = $25–$60/month.

### Mock Mode (Development)

```bash
FACESWAP_DRIVER=mock
```

Returns the product image as-is. No API key required.

---

## Step 2: DigitalOcean Spaces Setup

### 2.1 Create Space

1. Go to **DigitalOcean → Spaces Object Storage**
2. Create a new Space:
   - **Region:** `sgp1` (Singapore) — closest to Japan
   - **Name:** `kirei-tryon` (or your preferred name)
   - **File listing:** Restricted
3. Enable **CDN** for the Space

### 2.2 Create API Keys

1. Go to **API → Spaces Keys**
2. Generate a new key pair
3. Copy both **Key** and **Secret**

### 2.3 Configure CORS

In the Space settings → CORS Configuration, add:

```json
[
  {
    "AllowedOrigins": ["https://moro.gxo.co.jp", "https://trans.gxo.co.jp"],
    "AllowedMethods": ["GET"],
    "AllowedHeaders": ["*"],
    "MaxAgeSeconds": 3600
  }
]
```

### 2.4 Add to `.env`:
```bash
DO_SPACES_KEY=your-spaces-key
DO_SPACES_SECRET=your-spaces-secret
DO_SPACES_REGION=sgp1
DO_SPACES_BUCKET=kirei-tryon
DO_SPACES_ENDPOINT=https://sgp1.digitaloceanspaces.com
DO_SPACES_CDN_URL=https://kirei-tryon.sgp1.cdn.digitaloceanspaces.com
```

**Cost:** $5/month for 250GB storage + 1TB transfer.

---

## Step 3: Database Migration

```bash
cd /var/www/html/moro
php artisan migrate
```

This creates 3 new tables:
- `user_face_photos` — Stores user face photo references
- `virtual_tryon_results` — Stores try-on processing results
- Adds `tryon_consent_at` column to `users` table

### Verify:
```bash
php artisan migrate:status | grep -E "face_photos|tryon|consent"
```

All 3 should show `Ran`.

---

## Step 4: Redis Queue Worker

The virtual try-on uses the existing Redis queue. Verify the queue worker is running:

```bash
# Check if queue worker is running
ps aux | grep "queue:work"

# If not running, start it (or check supervisor/pm2 config).
# The queue name must include REDIS_QUEUE from .env (for Docker this is "moro";
# older production environments may use "trans"). Keep timeout above
# ProcessVirtualTryon::$timeout (300s).
php artisan queue:work redis --queue=${REDIS_QUEUE:-default},default --timeout=360 --tries=3
```

The `ProcessVirtualTryon` job dispatches to the same queue as the existing `ProcessFaceSwapInsightface` job.

---

## Step 5: Watermark Image

Place the KIREI logo watermark file at:
```
public/images/watermark-kirei.png
```

**Requirements:**
- PNG format with transparency
- Recommended size: 200-400px width
- Semi-transparent (the code applies 50% opacity)

If the file doesn't exist, downloads will work but without watermark.

---

## Step 6: Cron Schedule

The `tryon:clean-expired` command runs daily at 3:00 AM to delete expired results (90-day retention).

Verify cron is configured:
```bash
crontab -l | grep schedule
# Should show: * * * * * cd /var/www/html/moro && php artisan schedule:run >> /dev/null 2>&1
```

### Test manually:
```bash
php artisan tryon:clean-expired
```

---

## Step 7: Deploy

After merging PR #5 into `develop`:

```bash
# The GitHub Actions workflow will auto-deploy on push to develop
# Or manually:
cd /var/www/html/moro
git pull origin develop
composer install --no-dev --optimize-autoloader
php artisan migrate
php artisan config:cache
php artisan route:cache

# Rebuild frontend
npm install
npm run production
```

---

## Step 8: Verification Checklist

After deployment, verify each feature works:

| # | Test | Expected |
|---|------|----------|
| 1 | Visit product detail page | "バーチャル試着する" button visible |
| 2 | Click button (not logged in) | Redirect to login page |
| 3 | Click button (logged in) | Photo selection dialog opens |
| 4 | Upload face photo | Photo saved, appears in list |
| 5 | Upload 3 photos, try 4th | Error: max 3 photos |
| 6 | Select photo → "この写真で試着する" | Processing screen appears |
| 7 | Wait 3-5 seconds | Result comparison view shown |
| 8 | Click "保存" | Success message |
| 9 | Click "ダウンロード" | JPEG downloaded with watermark |
| 10 | Visit /mypage/tryon-history | Saved results shown in grid |
| 11 | Visit /virtual-fitting | Updated landing page with new steps |

---

## API Endpoints Reference

All endpoints require `Authorization: Bearer {token}` header.

| Method | Endpoint | Description |
|--------|----------|-------------|
| GET | `/api/user/face-photos` | List user's face photos |
| POST | `/api/user/face-photos` | Upload face photo (multipart) |
| DELETE | `/api/user/face-photos/{id}` | Delete face photo |
| POST | `/api/virtual-tryon/start` | Start try-on processing |
| GET | `/api/virtual-tryon/{code}/status` | Poll processing status |
| POST | `/api/virtual-tryon/{id}/save` | Save result to history |
| GET | `/api/virtual-tryon/history` | Get saved history |
| GET | `/api/virtual-tryon/{id}/download` | Download with watermark |

---

## Troubleshooting

### Face Swap API returns error
```bash
# Check logs
tail -f storage/logs/laravel.log | grep -i "faceswap\|facemint\|segmind\|virtual.*tryon"
```

### Queue jobs not processing
```bash
# Check failed jobs
php artisan queue:failed

# Retry failed jobs
php artisan queue:retry all
```

### Storage permission issues
```bash
# Ensure storage directories are writable
chmod -R 775 storage bootstrap/cache
chown -R gxo:www-data storage bootstrap/cache
```

---

## Monthly Cost Summary

### With FaceMint (Recommended)
| Item | Cost |
|------|------|
| FaceMint API (500 calls) | ~$1 (~¥160) |
| DigitalOcean Spaces | $5 (~¥750) |
| **Total** | **~$6 (~¥910)** |

### With Segmind v4
| Item | Cost |
|------|------|
| Segmind API (500 calls) | ~$60 (~¥9,600) |
| DigitalOcean Spaces | $5 (~¥750) |
| **Total** | **~$65 (~¥10,350)** |

### Switching Providers

To switch providers, change `FACESWAP_DRIVER` in `.env` and restart the queue worker:
```bash
# Edit .env: FACESWAP_DRIVER=facemint
php artisan config:cache
php artisan queue:restart
```
