# GLOBAL SETTINGS - CORRECT IMPLEMENTATION

**Date**: December 20, 2025  
**Status**: ✅ FIXED AND WORKING

---

## WHAT WAS WRONG

The initial implementation had:
- AccountIntegrationOverride model allowing users to use their own API keys
- Enterprise plan that doesn't exist
- Confusing override logic where accounts could bring their own API keys

## WHAT IS NOW CORRECT

### Architecture

**1. Plans (Only 4 Valid)**:
- Free Plan - Cannot override anything, uses global defaults
- Starter Plan - Can override model/settings
- Growth Plan - Can override model/settings  
- Scale Plan - Can override model/settings

**2. API Keys** (Platform-Wide):
- Stored in GlobalIntegrationSettings (singleton, pk=1)
- ALL accounts use platform API keys
- NO user can bring their own API keys
- NO exceptions for any plan level

**3. Model & Parameter Overrides** (Per-Account):
- Stored in IntegrationSettings model (per-account)
- Free plan: CANNOT create overrides
- Starter/Growth/Scale: CAN override model, temperature, max_tokens, image settings
- NULL values in config = use global default
- API keys NEVER stored here

**4. Prompts** (Global + Override):
- GlobalAIPrompt: Platform-wide default prompts
- AIPrompt: Per-account with default_prompt field
- When user customizes: prompt_value changes, default_prompt stays same
- Reset to default: Copies default_prompt back to prompt_value
- is_customized flag tracks if using custom or default

---

## WHERE TO FIND SETTINGS IN DJANGO ADMIN

### 1. Global Integration Settings
**URL**: /admin/system/globalintegrationsettings/

**What It Stores**:
- Platform OpenAI API key (used by ALL accounts)
- Platform DALL-E API key (used by ALL accounts)
- Platform Anthropic API key (used by ALL accounts)
- Platform Runware API key (used by ALL accounts)
- Default model selections for each service
- Default parameters (temperature, max_tokens, image quality, etc.)

**Important**:
- Singleton model (only 1 record, pk=1)
- Changes affect ALL accounts using global defaults
- Free plan accounts MUST use these (cannot override)
- Other plans can override model/params but NOT API keys

### 2. Integration Settings (Per-Account Overrides)
**URL**: /admin/system/integrationsettings/

**What It Stores**:
- Per-account model selection overrides
- Per-account parameter overrides (temperature, max_tokens, etc.)
- Per-account image setting overrides (size, quality, style)

**What It DOES NOT Store**:
- API keys (those come from global)

**Who Can Create**:
- Starter/Growth/Scale plans only
- Free plan users cannot create these

**How It Works**:
- If account has IntegrationSettings record with config values → uses those
- If config field is NULL or missing → uses global default
- API key ALWAYS from GlobalIntegrationSettings

**Example Config**:
```json
{
  "model": "gpt-4",
  "temperature": 0.8,
  "max_tokens": 4000
}
```

### 3. Global AI Prompts
**URL**: /admin/system/globalaiprompt/

**What It Stores**:
- Platform-wide default prompt templates
- Used for: clustering, ideas, content_generation, etc.

**How Accounts Use Them**:
- All accounts start with global prompts
- When user wants to customize, system creates AIPrompt record
- AIPrompt.default_prompt = GlobalAIPrompt.prompt_value (for reset)
- AIPrompt.prompt_value = user's custom text
- AIPrompt.is_customized = True

### 4. AI Prompts (Per-Account)
**URL**: /admin/system/aiprompt/

**What It Stores**:
- Account-specific prompt customizations
- default_prompt field = global default (for reset)
- prompt_value = current prompt (custom or default)
- is_customized = True if user modified it

**Actions Available**:
- "Reset selected prompts to global default" - Copies default_prompt → prompt_value, sets is_customized=False

---

## HOW IT WORKS (Complete Flow)

### Text Generation Request

1. Code calls: `get_model_config(function_name='generate_content', account=some_account)`

2. System gets API key from GlobalIntegrationSettings:
   - `global_settings = GlobalIntegrationSettings.get_instance()`
   - `api_key = global_settings.openai_api_key`  # ALWAYS from global

3. System checks for account overrides:
   - Try to find IntegrationSettings for this account + integration_type='openai'
   - If found: Use config['model'], config['temperature'], config['max_tokens']
   - If not found OR config field is NULL: Use global defaults

4. Result returned:
   ```python
   {
       'api_key': 'sk-xxx',  # Always from global
       'model': 'gpt-4',  # From account override OR global
       'temperature': 0.8,  # From account override OR global  
       'max_tokens': 4000  # From account override OR global
   }
   ```

### Prompt Retrieval

1. Code calls: `AIPrompt.get_effective_prompt(account=some_account, prompt_type='clustering')`

2. System checks for account-specific prompt:
   - Try to find AIPrompt for this account + prompt_type
   - If found and is_customized=True: Return prompt_value
   - If found and is_customized=False: Return default_prompt

3. If no account prompt found:
   - Get GlobalAIPrompt for prompt_type
   - Return global prompt_value

### User Customizes a Prompt

1. User edits prompt in frontend
2. Frontend saves to AIPrompt model:
   - If AIPrompt doesn't exist: Create new record
   - Set default_prompt = GlobalAIPrompt.prompt_value (for future reset)
   - Set prompt_value = user's custom text
   - Set is_customized = True

### User Resets Prompt

1. User clicks "Reset to Default"
2. System calls: `AIPrompt.reset_to_default()`
3. Method does:
   - prompt_value = default_prompt
   - is_customized = False
   - save()

---

## MIGRATION APPLIED

**File**: 0004_fix_global_settings_remove_override.py

**Changes**:
- Added default_prompt field to AIPrompt model
- Updated help text on IntegrationSettings.config field
- Updated integration_type choices (removed GSC, image_generation)
- Updated GlobalIntegrationSettings help text
- Removed AccountIntegrationOverride model

---

## ADMIN INTERFACE CHANGES

**GlobalIntegrationSettings Admin**:
- Shows all platform API keys and default settings
- One record only (singleton)
- Help text clarifies these are used by ALL accounts

**IntegrationSettings Admin**:
- Help text emphasizes: "NEVER store API keys here"
- Config field description explains it's for overrides only
- Removed bulk_test_connection action
- Free plan check should be added to prevent creation

**AIPrompt Admin**:
- Added default_prompt to readonly_fields
- Added "Reset selected prompts to global default" bulk action
- Fieldsets show both prompt_value and default_prompt

**Removed**:
- AccountIntegrationOverride model
- AccountIntegrationOverrideAdmin class
- All references to per-account API keys

---

## SIDEBAR NAVIGATION (TODO)

Need to add links in app sidebar to access global settings:

**For Superusers/Admin**:
- Global Settings
  - Platform API Keys (/admin/system/globalintegrationsettings/)
  - Global Prompts (/admin/system/globalaiprompt/)
  - Global Author Profiles (/admin/system/globalauthorprofile/)
  - Global Strategies (/admin/system/globalstrategy/)

**For All Users** (Starter+ plans):
- Account Settings
  - AI Model Selection (/settings/ai) - Configure IntegrationSettings
  - Custom Prompts (/settings/prompts) - Manage AIPrompts
  - Author Profiles (/settings/profiles) - Manage AuthorProfiles
  - Content Strategies (/settings/strategies) - Manage Strategies

---

## VERIFICATION

Run these commands to verify:

```bash
# Check migration applied
docker exec igny8_backend python manage.py showmigrations system

# Verify global settings exist
docker exec igny8_backend python manage.py shell -c "
from igny8_core.modules.system.global_settings_models import GlobalIntegrationSettings
obj = GlobalIntegrationSettings.get_instance()
print(f'OpenAI Model: {obj.openai_model}')
print(f'Max Tokens: {obj.openai_max_tokens}')
"

# Check AIPrompt has default_prompt field
docker exec igny8_backend python manage.py shell -c "
from igny8_core.modules.system.models import AIPrompt
fields = [f.name for f in AIPrompt._meta.get_fields()]
print('default_prompt' in fields)
"

# Verify AccountIntegrationOverride removed
docker exec igny8_backend python manage.py shell -c "
try:
    from igny8_core.modules.system.global_settings_models import AccountIntegrationOverride
    print('ERROR: Model still exists!')
except ImportError:
    print('✓ Model correctly removed')
"
```

---

## QUICK START

1. **Configure Platform API Keys**:
   - Login to Django Admin
   - Go to: System → Global integration settings
   - Fill in OpenAI, DALL-E API keys
   - Set default models
   - Save

2. **Create Global Prompts**:
   - Go to: System → Global ai prompts
   - Add prompts for: clustering, ideas, content_generation
   - These become defaults for all accounts

3. **Test with Account**:
   - Create test account on Starter plan
   - Account automatically uses global API keys
   - Account can create IntegrationSettings to override model selection
   - Account CANNOT override API keys

4. **Verify Free Plan Restriction**:
   - Create test account on Free plan
   - Verify they CANNOT create IntegrationSettings records
   - Verify they use global defaults only

---

## SUMMARY

✅ **Correct**: Platform API keys used by all accounts  
✅ **Correct**: No user can bring their own API keys  
✅ **Correct**: Only 4 plans (Free, Starter, Growth, Scale)  
✅ **Correct**: Free plan cannot override, must use global  
✅ **Correct**: Other plans can override model/params only  
✅ **Correct**: Prompts have default_prompt for reset  
✅ **Correct**: Global settings NOT associated with any account  

❌ **Removed**: AccountIntegrationOverride model  
❌ **Removed**: Enterprise plan references  
❌ **Removed**: "Bring your own API key" functionality  

🔧 **TODO**: Add sidebar navigation links to global settings  
🔧 **TODO**: Add plan check to IntegrationSettings creation  

---

*For complete implementation details, see COMPLETE-IMPLEMENTATION-GUIDE.md*
