# Storage Driver Configuration Guide

## Overview
The Fish E-commerce application now supports **configurable storage drivers** for all image uploads. You can choose between:
- **Cloudinary CDN**: Cloud storage with automatic optimization and CDN delivery
- **Local Storage**: Traditional file system storage in your project's storage folder

## Features Added

### 1. Storage Driver Toggle
- New setting in **Admin → Settings** page
- Radio buttons to switch between Cloudinary and Local storage
- Applies to ALL image types: logo, favicon, products, categories, and blog images

### 2. StorageService Class
**Location**: `app/Services/StorageService.php`

**Methods**:
- `upload($file, $folder, $options)` - Upload file to configured storage
- `delete($path)` - Delete file from storage
- `url($path)` - Get full URL for stored file
- `getDriver()` - Get current storage driver
- `isCloudinary()` - Check if using Cloudinary
- `isLocal()` - Check if using local storage

### 3. Helper Functions
**Location**: `app/helpers.php`

```php
storage_url($path)          // Get full URL for stored file
is_cloudinary_storage()     // Check if using Cloudinary
```

### 4. Updated Controllers
- ✅ `SettingsController` - Logo & favicon uploads
- ✅ `ProductController` - Product image uploads
- ✅ `CategoryController` - Category image uploads

### 5. Database Migration
**File**: `database/migrations/2025_11_15_223657_add_storage_driver_to_site_settings.php`

Adds `storage_driver` setting with default value `local`.

## Setup Instructions

### Step 1: Run Migration
```bash
php artisan migrate
```

This will add the `storage_driver` setting to your database.

### Step 2: Choose Storage Driver

#### Option A: Use Local Storage (Default)
No additional configuration needed. Images will be stored in:
- `storage/app/public/settings/` - Logo and favicon
- `storage/app/public/products/` - Product images
- `storage/app/public/categories/` - Category images

Make sure the storage link is created:
```bash
php artisan storage:link
```

#### Option B: Use Cloudinary
1. Keep your Cloudinary credentials in `.env`:
```env
CLOUDINARY_CLOUD_NAME=your_cloud_name
CLOUDINARY_API_KEY=your_api_key
CLOUDINARY_API_SECRET=your_api_secret
CLOUDINARY_SECURE_URL=true
```

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

### Step 3: Update Existing Views (Optional)

If you have custom views that display images, update them to use the `storage_url()` helper:

**Before:**
```blade
<img src="{{ asset('storage/' . $product->images[0]) }}" alt="Product">
```

**After:**
```blade
<img src="{{ storage_url($product->images[0]) }}" alt="Product">
```

## How It Works

### Upload Process

1. **Admin uploads an image** (logo, product, category, etc.)
2. **System checks** the `storage_driver` setting
3. **Routes to appropriate storage**:
   - If `cloudinary`: Uploads to Cloudinary CDN
   - If `local`: Saves to project storage folder
4. **Stores path/URL** in database

### Display Process

1. **View requests image** using `storage_url($path)`
2. **Helper checks** if path is already a URL (Cloudinary)
3. **Returns**:
   - Cloudinary URL as-is
   - Local path as `asset('storage/' . $path)`

## Benefits

### Cloudinary Storage
✅ Global CDN delivery  
✅ Automatic image optimization  
✅ Responsive image transformations  
✅ No server disk space used  
✅ 25GB storage + 25GB bandwidth free  
✅ Automatic backups  

### Local Storage
✅ No third-party dependencies  
✅ Full control over files  
✅ No API limits  
✅ Works offline  
✅ No external service costs  

## Switching Between Storage Drivers

You can switch storage drivers at any time:

1. Go to **Admin → Settings**
2. Change the **Image Storage Driver** option
3. Click **Update Settings**

**Important Notes:**
- Existing images remain in their original storage
- New uploads use the selected storage driver
- Mixed storage is supported (some images in Cloudinary, others local)
- The `storage_url()` helper handles both automatically

## Migration Strategy

### From Local to Cloudinary
1. Switch storage driver to "Cloudinary"
2. New images will upload to Cloudinary
3. Old images remain in local storage (still work)
4. Optionally manually migrate old images

### From Cloudinary to Local
1. Switch storage driver to "Local"
2. New images will save locally
3. Old Cloudinary images remain accessible (still work)
4. Optionally download old images from Cloudinary

## File Structure

```
app/
├── Services/
│   └── StorageService.php          # Main storage handler
├── Http/Controllers/Admin/
│   ├── SettingsController.php      # Updated to use StorageService
│   ├── ProductController.php       # Updated to use StorageService
│   └── CategoryController.php      # Updated to use StorageService
└── helpers.php                     # Added storage_url() helper

database/migrations/
└── 2025_11_15_223657_add_storage_driver_to_site_settings.php

resources/views/admin/settings/
└── index.blade.php                 # Added storage driver toggle
```

## Troubleshooting

### Images not displaying after switching to Cloudinary
- Check Cloudinary credentials in `.env`
- Run `php artisan config:clear`
- Verify internet connection
- Check Cloudinary dashboard for uploaded files

### Images not displaying after switching to Local
- Run `php artisan storage:link`
- Check file permissions on `storage/app/public`
- Verify files exist in storage directory

### Upload fails with "credentials not configured"
- Ensure Cloudinary settings are in `.env` file
- Run `php artisan config:clear`
- Check API key is correct

### Mixed storage issues
This is normal! The app supports mixed storage:
- Cloudinary URLs: `https://res.cloudinary.com/...`
- Local paths: `settings/logo.png`
- Both work with `storage_url()` helper

## API Reference

### StorageService

```php
// Upload a file
$url = StorageService::upload($file, 'products', [
    'width' => 800,
    'height' => 600
]);

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

// Get URL for a file
$url = StorageService::url($path);

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

### Helper Functions

```php
// Get storage URL
$url = storage_url($product->images[0]);

// Check if Cloudinary
if (is_cloudinary_storage()) {
    echo "Using Cloudinary CDN";
}
```

## Blade Template Examples

```blade
{{-- Display product image --}}
<img src="{{ storage_url($product->images[0]) }}" alt="{{ $product->name }}">

{{-- Display category image --}}
<img src="{{ storage_url($category->image) }}" alt="{{ $category->name }}">

{{-- Display site logo --}}
<img src="{{ storage_url(site_setting('site_logo')) }}" alt="Logo">

{{-- Conditional display --}}
@if(is_cloudinary_storage())
    <span class="badge">CDN Optimized</span>
@endif
```

## Testing

1. **Test Local Storage**:
   - Set storage driver to "Local"
   - Upload a product image
   - Verify file in `storage/app/public/products/`
   - Check image displays on product page

2. **Test Cloudinary**:
   - Set storage driver to "Cloudinary"
   - Upload a product image
   - Verify file in Cloudinary dashboard
   - Check image displays on product page
   - Verify URL contains `res.cloudinary.com`

3. **Test Switching**:
   - Upload image with Local
   - Switch to Cloudinary
   - Upload another image
   - Verify both images display correctly

## Support

For issues or questions:
- Check Laravel logs: `storage/logs/laravel.log`
- Check Cloudinary dashboard: `https://cloudinary.com/console`
- Review error messages in admin panel

## Version History

- **v1.0** (2025-11-15): Initial implementation
  - Added StorageService class
  - Added storage driver toggle in settings
  - Updated all controllers
  - Added helper functions
