# Settings System Documentation

## Overview

The Settings system provides a centralized, type-safe way to manage application configuration. It features enums for keys, groups, and types, caching for performance, and a clean API for accessing settings.

---

## Table of Contents

1. [Architecture](#architecture)
2. [Enums](#enums)
3. [Service](#service)
4. [Usage Examples](#usage-examples)
5. [API Endpoints](#api-endpoints)
6. [Helper Functions](#helper-functions)
7. [Adding New Settings](#adding-new-settings)

---

## Architecture

```
┌─────────────────────────────────────────────────────────────────┐
│                      Settings Architecture                       │
├─────────────────────────────────────────────────────────────────┤
│                                                                  │
│   ┌──────────────┐    ┌──────────────┐    ┌──────────────┐     │
│   │SettingKeyEnum│    │SettingGroup  │    │SettingType   │     │
│   │              │    │    Enum      │    │    Enum      │     │
│   │ - Keys       │    │ - Groups     │    │ - Types      │     │
│   │ - Defaults   │    │ - Labels     │    │ - Validation │     │
│   │ - Labels     │    │ - Icons      │    │ - Casting    │     │
│   └──────┬───────┘    └──────┬───────┘    └──────┬───────┘     │
│          │                   │                   │              │
│          └───────────────────┼───────────────────┘              │
│                              ▼                                   │
│                    ┌──────────────────┐                         │
│                    │  SettingService  │                         │
│                    │  - get()         │                         │
│                    │  - set()         │                         │
│                    │  - cache         │                         │
│                    └────────┬─────────┘                         │
│                             │                                    │
│                             ▼                                    │
│                    ┌──────────────────┐                         │
│                    │   Setting Model  │                         │
│                    │   (Database)     │                         │
│                    └──────────────────┘                         │
│                                                                  │
└─────────────────────────────────────────────────────────────────┘
```

---

## Enums

### SettingKeyEnum

Location: `app/Enums/SettingKeyEnum.php`

Defines all available setting keys with their properties.

```php
use App\Enums\SettingKeyEnum;

// Available keys
SettingKeyEnum::AppName          // 'app_name'
SettingKeyEnum::Phone            // 'phone'
SettingKeyEnum::Logo             // 'logo'
SettingKeyEnum::MaintenanceMode  // 'maintenance_mode'
// ... and many more

// Key properties
$key = SettingKeyEnum::AppName;
$key->value;          // 'app_name'
$key->group();        // SettingGroupEnum::General
$key->type();         // SettingTypeEnum::String
$key->defaultValue(); // config('app.name')
$key->isPublic();     // true
$key->label();        // 'App Name'
$key->isTranslatable(); // false
```

#### Setting Categories

| Group | Keys |
|-------|------|
| **General** | app_name, timezone, currency, date_format, etc. |
| **Contact** | phone, email, address, location, working_hours |
| **Social** | whats_app, facebook, twitter, instagram, etc. |
| **Appearance** | logo, favicon, colors, footer |
| **SEO** | meta_title, meta_description, og_image |
| **Notifications** | enable_email, enable_sms, enable_push |
| **Payment** | enable_cash, enable_online, tax_percentage |
| **Shipping** | free_shipping, shipping_cost |
| **System** | maintenance_mode, app_version, force_update |

### SettingGroupEnum

Location: `app/Enums/SettingGroupEnum.php`

```php
use App\Enums\SettingGroupEnum;

SettingGroupEnum::General       // 'general'
SettingGroupEnum::Contact       // 'contact'
SettingGroupEnum::Social        // 'social'
SettingGroupEnum::Appearance    // 'appearance'
SettingGroupEnum::Notifications // 'notifications'
SettingGroupEnum::Payment       // 'payment'
SettingGroupEnum::Shipping      // 'shipping'
SettingGroupEnum::Seo           // 'seo'
SettingGroupEnum::System        // 'system'

// Properties
$group = SettingGroupEnum::General;
$group->label(); // 'General Settings'
$group->icon();  // 'settings'
```

### SettingTypeEnum

Location: `app/Enums/SettingTypeEnum.php`

```php
use App\Enums\SettingTypeEnum;

SettingTypeEnum::String   // Basic text
SettingTypeEnum::Text     // Long text
SettingTypeEnum::Integer  // Numbers
SettingTypeEnum::Float    // Decimal numbers
SettingTypeEnum::Boolean  // true/false
SettingTypeEnum::Json     // JSON data
SettingTypeEnum::Image    // Image upload
SettingTypeEnum::Email    // Email address
SettingTypeEnum::Url      // URL
SettingTypeEnum::Phone    // Phone number
SettingTypeEnum::Color    // Hex color
SettingTypeEnum::Date     // Date
SettingTypeEnum::DateTime // DateTime

// Properties
$type = SettingTypeEnum::Email;
$type->cast($value);        // Cast value to proper type
$type->validationRule();    // 'email:dns'
$type->inputType();         // 'email'
```

---

## Service

### SettingService

Location: `app/Services/Setting/SettingService.php`

The main service for managing settings.

```php
use App\Services\Setting\SettingService;
use App\Enums\SettingKeyEnum;

$service = app(SettingService::class);

// Get a setting
$appName = $service->get(SettingKeyEnum::AppName);
$appName = $service->get('app_name');
$appName = $service->get('app_name', 'Default Name');

// Set a setting
$service->set(SettingKeyEnum::AppName, 'My App');
$service->set('app_name', 'My App');

// Set multiple settings
$service->setMany([
    'app_name' => 'My App',
    'phone' => '+966500000000',
    'email' => 'info@example.com',
]);

// Get by group
$contactSettings = $service->byGroup(SettingGroupEnum::Contact);

// Get public settings only
$publicSettings = $service->publicSettings();

// Check if exists
if ($service->has(SettingKeyEnum::Logo)) {
    // ...
}

// Delete a setting
$service->delete('custom_setting');

// Cache operations
$service->clearCache();
$service->refreshCache();

// Initialize defaults from enum
$service->initializeDefaults();

// Get metadata for building forms
$metadata = $service->getMetadata(SettingKeyEnum::AppName);
$allMetadata = $service->getAllMetadata();

// Upload image
$service->uploadImage(SettingKeyEnum::Logo, $request->file('logo'));
```

---

## Usage Examples

### Using Helper Functions

```php
// Get setting
$appName = settings('app_name');
$appName = settings(SettingKeyEnum::AppName);
$appName = settings('app_name', 'Default Name');

// Alias
$appName = setting('app_name');

// Set setting
set_setting('app_name', 'My App');
set_setting(SettingKeyEnum::AppName, 'My App');
```

### Using Static Methods

```php
use App\Models\Setting;
use App\Enums\SettingKeyEnum;

// Get value
$value = Setting::getValue('app_name');
$value = Setting::getValue(SettingKeyEnum::AppName);
$value = Setting::getValue('app_name', 'default');

// Set value
Setting::setValue('app_name', 'My App');
Setting::setValue(SettingKeyEnum::AppName, 'My App');

// Get by group
$settings = Setting::getByGroup('contact');
$settings = Setting::getByGroup(SettingGroupEnum::Contact);

// Get public settings
$public = Setting::getPublic();

// Clear cache
Setting::clearSettingsCache();
```

### In Controllers

```php
use App\Enums\SettingKeyEnum;
use App\Services\Setting\SettingService;

class SomeController extends Controller
{
    public function __construct(
        protected SettingService $settings
    ) {}

    public function index()
    {
        // Check maintenance mode
        if ($this->settings->get(SettingKeyEnum::MaintenanceMode)) {
            return response()->json(['message' => 'Under maintenance'], 503);
        }

        $appName = $this->settings->get(SettingKeyEnum::AppName);
        // ...
    }
}
```

### In Blade Templates

```blade
{{-- Get setting --}}
<h1>{{ settings('app_name') }}</h1>

{{-- With default --}}
<p>{{ settings('phone', 'N/A') }}</p>

{{-- Using enum --}}
<img src="{{ settings(\App\Enums\SettingKeyEnum::Logo) }}" alt="Logo">

{{-- Check boolean setting --}}
@if(settings('maintenance_mode'))
    <div class="alert">Site is under maintenance</div>
@endif
```

### Type-Safe Usage

```php
use App\Enums\SettingKeyEnum;

// Recommended: Use enum for type safety
$phone = settings(SettingKeyEnum::Phone);
$isMaintenanceMode = settings(SettingKeyEnum::MaintenanceMode); // Returns boolean

// Get with proper typing
$taxRate = settings(SettingKeyEnum::TaxPercentage); // Returns float
$enableTax = settings(SettingKeyEnum::EnableTax);   // Returns boolean
```

---

## API Endpoints

### Admin Endpoints

| Method | Endpoint | Description |
|--------|----------|-------------|
| GET | `/api/admin/settings` | Get all settings |
| GET | `/api/admin/settings/grouped` | Get settings grouped by group |
| GET | `/api/admin/settings/metadata` | Get form metadata for all settings |
| GET | `/api/admin/settings/groups` | Get available groups |
| GET | `/api/admin/settings/{key}` | Get single setting |
| POST | `/api/admin/settings` | Update settings |
| POST | `/api/admin/settings/group/{group}` | Update settings by group |
| POST | `/api/admin/settings/{key}/upload` | Upload image setting |
| POST | `/api/admin/settings/init-defaults` | Initialize default settings |
| POST | `/api/admin/settings/clear-cache` | Clear settings cache |
| DELETE | `/api/admin/settings/{key}` | Delete a setting |

### Request Examples

#### Get All Settings
```http
GET /api/admin/settings
Authorization: Bearer {token}
```

#### Get Settings by Group
```http
GET /api/admin/settings?group=contact
Authorization: Bearer {token}
```

#### Update Settings
```http
POST /api/admin/settings
Authorization: Bearer {token}
Content-Type: application/json

{
    "app_name": "My Application",
    "phone": "+966500000000",
    "email": "info@example.com",
    "maintenance_mode": false
}
```

#### Upload Logo
```http
POST /api/admin/settings/logo/upload
Authorization: Bearer {token}
Content-Type: multipart/form-data

image: [file]
```

### Response Examples

#### Settings List
```json
{
    "status": "success",
    "data": [
        {
            "key": "app_name",
            "value": "My Application",
            "group": "general",
            "type": "string",
            "label": "App Name",
            "is_public": true,
            "input_type": "text"
        },
        {
            "key": "phone",
            "value": "+966500000000",
            "group": "contact",
            "type": "phone",
            "label": "Phone",
            "is_public": true,
            "input_type": "text"
        }
    ]
}
```

#### Grouped Settings
```json
{
    "status": "success",
    "data": {
        "general": {
            "label": "General Settings",
            "icon": "settings",
            "settings": [...]
        },
        "contact": {
            "label": "Contact Information",
            "icon": "phone",
            "settings": [...]
        }
    }
}
```

---

## Helper Functions

| Function | Description |
|----------|-------------|
| `settings($key, $default, $locale)` | Get a setting value |
| `setting($key, $default, $locale)` | Alias for settings() |
| `set_setting($key, $value, $locale)` | Set a setting value |

```php
// Get settings
$name = settings('app_name');
$name = settings(SettingKeyEnum::AppName);
$name = settings('app_name', 'Default');
$name = settings('app_name', null, 'ar'); // With locale

// Set settings
set_setting('app_name', 'My App');
set_setting(SettingKeyEnum::AppName, 'My App');
set_setting('app_name', 'My App', 'ar'); // With locale
```

---

## Adding New Settings

### Step 1: Add to SettingKeyEnum

```php
// In app/Enums/SettingKeyEnum.php

enum SettingKeyEnum: string
{
    // Add your new key
    case MyNewSetting = 'my_new_setting';

    public function group(): SettingGroupEnum
    {
        return match ($this) {
            // ... existing cases
            self::MyNewSetting => SettingGroupEnum::General,
        };
    }

    public function type(): SettingTypeEnum
    {
        return match ($this) {
            // ... existing cases
            self::MyNewSetting => SettingTypeEnum::String,
        };
    }

    public function defaultValue(): mixed
    {
        return match ($this) {
            // ... existing cases
            self::MyNewSetting => 'default value',
        };
    }

    public function isPublic(): bool
    {
        return match ($this) {
            // ... existing cases
            self::MyNewSetting => true,
        };
    }

    public function label(): string
    {
        return match ($this) {
            // ... existing cases
            self::MyNewSetting => __('My New Setting'),
        };
    }
}
```

### Step 2: Add Validation (Optional)

```php
// In app/Http/Requests/Api/Dashboard/Admin/Settings/SettingRequest.php

public function rules(): array
{
    return [
        // ... existing rules
        'my_new_setting' => 'nullable|string|max:255',
    ];
}
```

### Step 3: Add to Seeder (Optional)

```php
// In database/seeders/SettingSeeder.php

protected function seedGeneralSettings(): void
{
    // ... existing settings
    $this->settingService->set(SettingKeyEnum::MyNewSetting, 'initial value');
}
```

### Step 4: Use It

```php
// Get value
$value = settings(SettingKeyEnum::MyNewSetting);

// Set value
set_setting(SettingKeyEnum::MyNewSetting, 'new value');
```

---

## Database Schema

### settings table

| Column | Type | Description |
|--------|------|-------------|
| id | bigint | Primary key |
| key | string | Setting key (unique with locale) |
| group | string | Group name (nullable) |
| type | string | Data type (default: 'string') |
| value | longText | Setting value (nullable) |
| locale | string | Locale code (nullable) |
| is_public | boolean | Public visibility (default: false) |
| description | text | Description (nullable) |
| options | json | Additional options (nullable) |
| sort_order | integer | Display order (default: 0) |
| is_system | boolean | System setting flag (default: false) |
| created_at | timestamp | Creation time |
| updated_at | timestamp | Last update |

---

## Caching

Settings are cached for 24 hours by default.

```php
// Cache is automatically cleared when:
// - A setting is saved
// - A setting is deleted
// - clearCache() is called

// Manual cache operations
$service = app(SettingService::class);
$service->clearCache();    // Clear cache
$service->refreshCache();  // Clear and rebuild cache

// Via artisan (if you create the command)
php artisan settings:clear-cache
```

---

## Files Reference

| File | Purpose |
|------|---------|
| `app/Enums/SettingKeyEnum.php` | All setting keys with metadata |
| `app/Enums/SettingGroupEnum.php` | Setting groups |
| `app/Enums/SettingTypeEnum.php` | Setting data types |
| `app/Models/Setting.php` | Setting model |
| `app/Services/Setting/SettingService.php` | Main service |
| `app/Http/Controllers/.../SettingsController.php` | API controller |
| `app/Http/Resources/.../SettingResource.php` | API resource |
| `app/Http/Requests/.../SettingRequest.php` | Validation |
| `database/migrations/..._add_improvements_to_settings_table.php` | Migration |
| `database/seeders/SettingSeeder.php` | Seeder |
| `app/Helpers/Helpers.php` | Helper functions |

---

## Migration

To apply the improvements:

```bash
php artisan migrate

# Optional: Seed default settings
php artisan db:seed --class=SettingSeeder
```