# Cloudinary Integration Setup Guide

## Overview
The Fish E-commerce application now supports **configurable storage drivers**. You can choose to store images either on **Cloudinary CDN** or **Local File System** directly from the admin settings page.

## What Was Integrated
- **Flexible Storage Service**: `app/Services/StorageService.php` handles both Cloudinary and local storage
- **Admin Toggle**: Switch between storage drivers in Settings page
- **Cloudinary Laravel Package**: `cloudinary-labs/cloudinary-laravel` v3.0.2 (for Cloudinary option)
- **Upload Functionality**: All images (logo, favicon, products, categories) respect the selected driver
- **Image Optimization**: Automatic when using Cloudinary
- **CDN Delivery**: All Cloudinary images served via global CDN
- **Backward Compatible**: Existing local storage images continue to work

## Storage Options

### Option 1: Local Storage (Default)
Images are stored in your project's `storage/app/public/` folder.

**Benefits:**
- ✅ No external dependencies
- ✅ Full control over files
- ✅ No API limits
- ✅ Works offline
- ✅ No setup required

### Option 2: Cloudinary CDN
Images are stored on Cloudinary's cloud storage and served via CDN.

**Benefits:**
- ✅ Global CDN delivery
- ✅ Automatic image optimization
- ✅ No server disk space used
- ✅ 25GB storage + 25GB bandwidth free
- ✅ Responsive image transformations
- ✅ Automatic backups

## Setup Instructions

### Prerequisites
The application works out-of-the-box with **Local Storage** (no setup needed).

To use **Cloudinary**, follow these steps:

### 1. Get Cloudinary Credentials

1. Go to [Cloudinary.com](https://cloudinary.com) and create a free account
2. After logging in, go to your Dashboard
3. You'll find your credentials:
   - **Cloud Name**: Your unique cloud name
   - **API Key**: Your API key
   - **API Secret**: Your API secret

### 2. Configure Environment Variables

Open your `.env` file and update the Cloudinary credentials:

```env
# Cloudinary Configuration
CLOUDINARY_CLOUD_NAME=your_actual_cloud_name
CLOUDINARY_API_KEY=your_actual_api_key
CLOUDINARY_API_SECRET=your_actual_api_secret
CLOUDINARY_UPLOAD_PRESET=
CLOUDINARY_SECURE_URL=true
```

**Important**: Replace the placeholder values with your actual Cloudinary credentials!

### 3. Clear Configuration Cache

After updating the `.env` file, clear the configuration cache:

```bash
php artisan config:clear
php artisan cache:clear
```

### 4. Select Storage Driver in Admin

1. Go to **Admin Dashboard → Settings**
2. Scroll to **"Image Storage Driver"** section
3. Select **"Cloudinary CDN"** radio button
4. Click **"Update Settings"**

### 5. Test the Integration

1. Still in **Admin Dashboard → Settings**
2. Upload a new Site Logo or Favicon
3. The image will be uploaded to Cloudinary in the folder: `fish-ecommerce/settings`
4. The image will be displayed from Cloudinary's CDN (URL will contain `res.cloudinary.com`)

You can now upload products, categories, and other images - they will all use Cloudinary!

## Switching Between Storage Drivers

### Switch to Cloudinary
1. Go to **Admin → Settings**
2. Select **"Cloudinary CDN"** under Image Storage Driver
3. Click **"Update Settings"**
4. All new uploads will go to Cloudinary

### Switch to Local Storage
1. Go to **Admin → Settings**
2. Select **"Local Storage"** under Image Storage Driver
3. Click **"Update Settings"**
4. All new uploads will save to `storage/app/public/`

**Important Notes:**
- ✅ Existing images remain in their original storage location
- ✅ Both storage types work simultaneously (mixed storage)
- ✅ The app automatically detects and displays images correctly
- ✅ You can switch back and forth anytime

## How It Works

### Storage Service Architecture

The application uses `StorageService` class to handle all image uploads:

1. **Admin uploads an image** (logo, product, category, blog)
2. **System checks** `storage_driver` setting from database
3. **Routes to appropriate storage**:
   - If `cloudinary`: Uses Cloudinary API
   - If `local`: Uses Laravel's file system
4. **Saves path/URL** in database
5. **Display** works automatically via `storage_url()` helper

### Upload Process

When you upload an image through any admin page:

**With Cloudinary:**
- Uploaded to: `fish-ecommerce/{folder}/` folder on Cloudinary
- Automatic transformation: Optimized quality and size
- Format: Auto-detected (JPG, PNG, GIF, SVG)
- Returns: Full Cloudinary URL (e.g., `https://res.cloudinary.com/...`)

**With Local Storage:**
- Uploaded to: `storage/app/public/{folder}/`
- Format: Original format preserved
- Returns: Storage path (e.g., `products/image_123.jpg`)

### Image Display

All layouts and views display images using the `storage_url()` helper:
- Automatically detects if path is a Cloudinary URL or local path
- Returns appropriate full URL for display
- Works with both storage types seamlessly

### Image Transformations

Cloudinary automatically applies these transformations:

**Logo**:
```php
[
    'width' => 500,
    'height' => 500,
    'crop' => 'limit',
    'quality' => 'auto:good'
]
```

**Favicon**:
```php
[
    'width' => 64,
    'height' => 64,
    'crop' => 'limit',
    'quality' => 'auto:good'
]
```

## Files Modified

### Core Service
- `app/Services/StorageService.php` - ✨ NEW: Handles both storage types

### Controllers
- `app/Http/Controllers/Admin/SettingsController.php` - Uses StorageService
- `app/Http/Controllers/Admin/ProductController.php` - Uses StorageService
- `app/Http/Controllers/Admin/CategoryController.php` - Uses StorageService

### Views
- `resources/views/admin/settings/index.blade.php` - Added storage driver toggle

### Helpers
- `app/helpers.php` - Added `storage_url()` and `is_cloudinary_storage()` helpers

### Database
- `database/migrations/2025_11_15_223657_add_storage_driver_to_site_settings.php` - ✨ NEW

### Configuration
- `config/cloudinary.php` - Cloudinary configuration file (already exists)
- `.env` - Cloudinary credentials (optional, only if using Cloudinary)

## Benefits

### Using Cloudinary
1. **CDN Delivery**: Images served from global CDN for faster loading
2. **Auto Optimization**: Images automatically optimized for web
3. **Responsive Images**: Can easily add responsive transformations
4. **Bandwidth Savings**: No need to serve images from your server
5. **Storage Freedom**: No local storage or server disk space used
6. **Automatic Backups**: Images safely stored on Cloudinary
7. **Free Tier**: 25 GB storage and 25 GB bandwidth per month free

### Using Local Storage
1. **No Dependencies**: Works without internet or external services
2. **Full Control**: Complete control over files
3. **No Limits**: No API rate limits or bandwidth restrictions
4. **Privacy**: Files stay on your server
5. **Offline**: Works in offline/local development
6. **Cost**: No external service costs

### Hybrid Approach
You can use both! Some images on Cloudinary, some local:
- ✅ Automatically handled by the app
- ✅ No configuration needed
- ✅ Switch between drivers anytime

## Cloudinary Dashboard

Access your Cloudinary dashboard to:
- View all uploaded images
- See storage and bandwidth usage
- Manage image transformations
- Set up custom presets
- Monitor API usage

URL: `https://cloudinary.com/console`

## Troubleshooting

### Error: "Invalid credentials" (Cloudinary)
- Check your `.env` file has correct Cloudinary credentials
- Run `php artisan config:clear`
- Verify credentials at https://cloudinary.com/console

### Error: "File not found" or upload fails (Local)
- Run `php artisan storage:link`
- Check permissions: `chmod -R 775 storage/`
- Verify `storage/app/public/` directory exists

### Error: "File not found" or upload fails (Cloudinary)
- Verify Cloudinary credentials are set in `.env`
- Run `php artisan config:clear`
- Check internet connection
- Ensure file size is within limits (2MB for logo, 1MB for favicon)

### Images not displaying (Cloudinary)
- Check that Cloudinary URLs are being returned correctly
- Verify CLOUDINARY_SECURE_URL is set to `true`
- Clear browser cache
- Check Cloudinary dashboard for uploaded files

### Images not displaying (Local)
- Run `php artisan storage:link`
- Check symbolic link exists: `public/storage` → `storage/app/public`
- Verify file permissions
- Check files exist in `storage/app/public/`

### Switching storage drivers doesn't work
- Clear cache: `php artisan config:clear`
- Check `site_settings` table has `storage_driver` entry
- Verify migration was run: `php artisan migrate`

### Mixed storage issues
This is **normal behavior**! The app supports:
- ✅ Some images on Cloudinary (full URLs)
- ✅ Some images on local storage (paths)
- ✅ Both display correctly using `storage_url()` helper

## Support

For more information:
- **Full Documentation**: See `STORAGE_CONFIGURATION.md`
- **Implementation Details**: See `IMPLEMENTATION_SUMMARY.md`
- **View Updates**: See `BLADE_VIEWS_UPDATE.md`

External resources:
- [Cloudinary Laravel Documentation](https://github.com/cloudinary-labs/cloudinary-laravel)
- [Cloudinary PHP SDK Documentation](https://cloudinary.com/documentation/php_integration)
- [Image Transformation Guide](https://cloudinary.com/documentation/image_transformations)

## Quick Start Guide

### Using Local Storage (Default)
```bash
# 1. Ensure storage link exists
php artisan storage:link

# 2. Start uploading images - that's it!
# All images will be stored in storage/app/public/
```

### Using Cloudinary
```bash
# 1. Add credentials to .env
CLOUDINARY_CLOUD_NAME=your_cloud_name
CLOUDINARY_API_KEY=your_api_key
CLOUDINARY_API_SECRET=your_api_secret

# 2. Clear cache
php artisan config:clear

# 3. Go to Admin → Settings
# 4. Select "Cloudinary CDN"
# 5. Save and start uploading!
```

## API Usage Examples

### In Controllers
```php
use App\Services\StorageService;

// Upload a file
$url = StorageService::upload($request->file('image'), 'products');

// Delete a file
StorageService::delete($imageUrl);

// Get URL for display
$displayUrl = StorageService::url($storedPath);

// Check driver
if (StorageService::isCloudinary()) {
    // Using Cloudinary
}
```

### In Blade Views
```blade
{{-- Display any image --}}
<img src="{{ storage_url($product->images[0]) }}" alt="Product">

{{-- Check storage driver --}}
@if(is_cloudinary_storage())
    <span class="badge">CDN Optimized ⚡</span>
@endif
```

### In PHP Helpers
```php
// Get storage URL
$url = storage_url($path);

// Check if Cloudinary
if (is_cloudinary_storage()) {
    // Do something specific for Cloudinary
}
```

## Free Tier Limits

Cloudinary's free tier includes:
- 25 GB storage
- 25 GB monthly bandwidth
- 25,000 transformations per month
- Basic image transformations
- CDN delivery

This is more than sufficient for most small to medium e-commerce sites.
