# Generated by Django 5.2.7 on 2025-10-04 07:17

import django.db.models.deletion
import uuid
from decimal import Decimal
from django.conf import settings
from django.db import migrations, models


class Migration(migrations.Migration):

    initial = True

    dependencies = [
        migrations.swappable_dependency(settings.AUTH_USER_MODEL),
    ]

    operations = [
        migrations.CreateModel(
            name='AvailableTool',
            fields=[
                ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
                ('created_at', models.DateTimeField(auto_now_add=True)),
                ('updated_at', models.DateTimeField(auto_now=True)),
                ('tool_name', models.CharField(help_text='Internal tool name (matches code implementation)', max_length=100, unique=True)),
                ('display_name', models.CharField(help_text='Human-readable name', max_length=255)),
                ('description', models.TextField(help_text='Detailed description of tool functionality')),
                ('icon', models.CharField(blank=True, help_text='Icon class or emoji for UI', max_length=50, null=True)),
                ('category', models.CharField(choices=[('search', 'Search & Retrieval'), ('code', 'Code Execution'), ('data', 'Data Processing'), ('integration', 'External Integration'), ('utility', 'Utility'), ('custom', 'Custom')], default='general', help_text='Tool category', max_length=50)),
                ('is_active', models.BooleanField(default=True, help_text='Whether this tool is available for use')),
                ('is_public', models.BooleanField(default=True, help_text='Whether all users can access this tool')),
                ('requires_admin_approval', models.BooleanField(default=False, help_text='Whether enabling this tool requires admin approval')),
                ('config_schema', models.JSONField(blank=True, default=dict, help_text='JSON schema for tool configuration')),
                ('default_config', models.JSONField(blank=True, default=dict, help_text='Default configuration values')),
                ('total_users', models.IntegerField(default=0, help_text='Number of users who have enabled this tool')),
            ],
            options={
                'verbose_name': 'Available Tool',
                'verbose_name_plural': 'Available Tools',
                'ordering': ['category', 'display_name'],
            },
        ),
        migrations.CreateModel(
            name='ChatSession',
            fields=[
                ('created_at', models.DateTimeField(auto_now_add=True)),
                ('updated_at', models.DateTimeField(auto_now=True)),
                ('id', models.UUIDField(default=uuid.uuid4, editable=False, help_text='UUID that also serves as LangGraph thread_id', primary_key=True, serialize=False)),
                ('title', models.CharField(default='New Conversation', help_text='User-defined or auto-generated conversation title', max_length=255)),
                ('description', models.TextField(blank=True, help_text='Optional description or summary of the conversation', null=True)),
                ('model_name', models.CharField(default='gpt-5-mini', help_text='AI model used for this session', max_length=100)),
                ('temperature', models.FloatField(default=0.7, help_text='Model temperature (0.0 to 2.0)')),
                ('enable_summarization', models.BooleanField(default=True, help_text='Enable automatic conversation summarization')),
                ('summarization_threshold', models.IntegerField(default=384, help_text='Token count to trigger summarization')),
                ('is_active', models.BooleanField(default=True, help_text='Whether this session is active')),
                ('is_archived', models.BooleanField(default=False, help_text='Whether this session is archived')),
                ('is_pinned', models.BooleanField(default=False, help_text='Whether this session is pinned to top')),
                ('tags', models.JSONField(blank=True, default=list, help_text='User-defined tags for organization')),
                ('metadata', models.JSONField(blank=True, default=dict, help_text='Additional session metadata')),
                ('message_count', models.IntegerField(default=0, help_text='Total messages in this session (updated via signals)')),
                ('total_tokens_used', models.IntegerField(default=0, help_text='Total tokens used in this session')),
                ('last_message_at', models.DateTimeField(blank=True, help_text='Timestamp of last message in this session', null=True)),
                ('user', models.ForeignKey(help_text='User who owns this chat session', on_delete=django.db.models.deletion.CASCADE, related_name='chat_sessions', to=settings.AUTH_USER_MODEL)),
            ],
            options={
                'verbose_name': 'Chat Session',
                'verbose_name_plural': 'Chat Sessions',
                'ordering': ['-is_pinned', '-last_message_at', '-updated_at'],
            },
        ),
        migrations.CreateModel(
            name='MessageFeedback',
            fields=[
                ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
                ('created_at', models.DateTimeField(auto_now_add=True)),
                ('updated_at', models.DateTimeField(auto_now=True)),
                ('checkpoint_id', models.CharField(help_text='LangGraph checkpoint ID containing the message', max_length=255)),
                ('message_index', models.IntegerField(help_text='Index of the message in the checkpoint')),
                ('rating', models.CharField(choices=[('thumbs_up', 'Thumbs Up 👍'), ('thumbs_down', 'Thumbs Down 👎'), ('excellent', 'Excellent'), ('good', 'Good'), ('neutral', 'Neutral'), ('poor', 'Poor'), ('very_poor', 'Very Poor')], help_text='User rating for the message', max_length=20)),
                ('feedback_categories', models.JSONField(blank=True, default=list, help_text='Categories of feedback (e.g., ["incorrect", "helpful", "creative"])')),
                ('feedback_text', models.TextField(blank=True, help_text='Optional detailed feedback from user', null=True)),
                ('reported_issue', models.CharField(blank=True, choices=[('incorrect', 'Incorrect Information'), ('harmful', 'Harmful Content'), ('biased', 'Biased Response'), ('off_topic', 'Off Topic'), ('incomplete', 'Incomplete Answer'), ('technical_error', 'Technical Error'), ('other', 'Other')], help_text='Type of issue if reporting a problem', max_length=50, null=True)),
                ('message_preview', models.TextField(blank=True, help_text='Preview of the message (for admin review)', null=True)),
                ('model_used', models.CharField(blank=True, help_text='AI model that generated the message', max_length=100, null=True)),
                ('reviewed', models.BooleanField(default=False, help_text='Whether admin has reviewed this feedback')),
                ('reviewed_at', models.DateTimeField(blank=True, help_text='When this feedback was reviewed', null=True)),
                ('admin_notes', models.TextField(blank=True, help_text='Internal notes from admin review', null=True)),
                ('action_taken', models.CharField(blank=True, choices=[('none', 'No Action'), ('noted', 'Noted for Training'), ('fixed', 'Issue Fixed'), ('escalated', 'Escalated'), ('user_notified', 'User Notified')], help_text='Action taken based on this feedback', max_length=50, null=True)),
                ('chat_session', models.ForeignKey(help_text='Chat session this feedback belongs to', on_delete=django.db.models.deletion.CASCADE, related_name='message_feedback', to='chatbot.chatsession')),
                ('reviewed_by', models.ForeignKey(blank=True, help_text='Admin who reviewed this feedback', null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='reviewed_feedback', to=settings.AUTH_USER_MODEL)),
                ('user', models.ForeignKey(help_text='User who provided feedback', on_delete=django.db.models.deletion.CASCADE, related_name='message_feedback', to=settings.AUTH_USER_MODEL)),
            ],
            options={
                'verbose_name': 'Message Feedback',
                'verbose_name_plural': 'Message Feedback',
                'ordering': ['-created_at'],
            },
        ),
        migrations.CreateModel(
            name='SystemPromptTemplate',
            fields=[
                ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
                ('created_at', models.DateTimeField(auto_now_add=True)),
                ('updated_at', models.DateTimeField(auto_now=True)),
                ('name', models.CharField(help_text='Unique name for this prompt template', max_length=255, unique=True)),
                ('slug', models.SlugField(help_text='URL-friendly slug', max_length=255, unique=True)),
                ('content', models.TextField(help_text='The system prompt content')),
                ('description', models.TextField(blank=True, help_text='Description of what this prompt does', null=True)),
                ('category', models.CharField(choices=[('general', 'General Purpose'), ('coding', 'Coding Assistant'), ('writing', 'Writing Helper'), ('research', 'Research Assistant'), ('education', 'Educational'), ('business', 'Business/Professional'), ('creative', 'Creative Writing'), ('analysis', 'Data Analysis'), ('custom', 'Custom')], default='general', help_text='Category of this prompt template', max_length=50)),
                ('tags', models.JSONField(blank=True, default=list, help_text='Tags for organization and search')),
                ('is_default', models.BooleanField(default=False, help_text='Whether this is the default system prompt')),
                ('is_active', models.BooleanField(default=True, help_text='Whether this template is active and available')),
                ('is_public', models.BooleanField(default=False, help_text='Whether this template is publicly available to all users')),
                ('variables', models.JSONField(blank=True, default=list, help_text='List of variables that can be replaced in the prompt (e.g., {user_name}, {topic})')),
                ('example_variables', models.JSONField(blank=True, default=dict, help_text='Example values for variables')),
                ('recommended_model', models.CharField(blank=True, help_text='Recommended AI model for this prompt', max_length=100, null=True)),
                ('recommended_temperature', models.FloatField(blank=True, help_text='Recommended temperature setting', null=True)),
                ('usage_count', models.IntegerField(default=0, help_text='Number of times this template has been used')),
                ('rating_sum', models.IntegerField(default=0, help_text='Sum of all ratings')),
                ('rating_count', models.IntegerField(default=0, help_text='Number of ratings')),
            ],
            options={
                'verbose_name': 'System Prompt Template',
                'verbose_name_plural': 'System Prompt Templates',
                'ordering': ['-is_default', '-usage_count', 'name'],
                'indexes': [models.Index(fields=['category', 'is_active'], name='sysprompt_cat_active_idx'), models.Index(fields=['is_default'], name='sysprompt_default_idx'), models.Index(fields=['-usage_count'], name='sysprompt_usage_idx')],
            },
        ),
        migrations.CreateModel(
            name='TokenUsage',
            fields=[
                ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
                ('created_at', models.DateTimeField(auto_now_add=True)),
                ('updated_at', models.DateTimeField(auto_now=True)),
                ('model_name', models.CharField(help_text='AI model used (e.g., gpt-4o, gpt-4o-mini)', max_length=100)),
                ('prompt_tokens', models.IntegerField(default=0, help_text='Tokens in the prompt/input')),
                ('completion_tokens', models.IntegerField(default=0, help_text='Tokens in the completion/output')),
                ('total_tokens', models.IntegerField(default=0, help_text='Total tokens (prompt + completion)')),
                ('reasoning_tokens', models.IntegerField(blank=True, default=0, help_text='Reasoning tokens (for models that support it)', null=True)),
                ('prompt_cost', models.DecimalField(decimal_places=6, default=Decimal('0.000000'), help_text='Cost for prompt tokens in USD', max_digits=10)),
                ('completion_cost', models.DecimalField(decimal_places=6, default=Decimal('0.000000'), help_text='Cost for completion tokens in USD', max_digits=10)),
                ('total_cost', models.DecimalField(decimal_places=6, default=Decimal('0.000000'), help_text='Total cost in USD', max_digits=10)),
                ('request_type', models.CharField(choices=[('chat', 'Chat Completion'), ('summarization', 'Conversation Summarization'), ('embedding', 'Text Embedding'), ('tool_call', 'Tool/Function Call'), ('vision', 'Vision Analysis')], default='chat', help_text='Type of API request', max_length=50)),
                ('endpoint', models.CharField(blank=True, help_text='API endpoint used', max_length=255, null=True)),
                ('response_time_ms', models.IntegerField(blank=True, help_text='Response time in milliseconds', null=True)),
                ('was_cached', models.BooleanField(default=False, help_text='Whether response was served from cache')),
                ('had_error', models.BooleanField(default=False, help_text='Whether this request had an error')),
                ('error_message', models.TextField(blank=True, help_text='Error message if request failed', null=True)),
                ('metadata', models.JSONField(blank=True, default=dict, help_text='Additional usage metadata')),
                ('chat_session', models.ForeignKey(blank=True, help_text='Chat session this usage belongs to', null=True, on_delete=django.db.models.deletion.CASCADE, related_name='token_usage', to='chatbot.chatsession')),
                ('user', models.ForeignKey(help_text='User who incurred this usage', on_delete=django.db.models.deletion.CASCADE, related_name='token_usage', to=settings.AUTH_USER_MODEL)),
            ],
            options={
                'verbose_name': 'Token Usage',
                'verbose_name_plural': 'Token Usage',
                'ordering': ['-created_at'],
            },
        ),
        migrations.CreateModel(
            name='UserAPIKey',
            fields=[
                ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
                ('created_at', models.DateTimeField(auto_now_add=True)),
                ('updated_at', models.DateTimeField(auto_now=True)),
                ('provider', models.CharField(choices=[('openai', 'OpenAI'), ('anthropic', 'Anthropic (Claude)'), ('google', 'Google AI'), ('cohere', 'Cohere'), ('huggingface', 'HuggingFace'), ('azure', 'Azure OpenAI'), ('custom', 'Custom Provider')], help_text='AI provider for this key', max_length=50)),
                ('provider_display_name', models.CharField(blank=True, help_text='Custom display name for provider', max_length=100, null=True)),
                ('encrypted_key', models.BinaryField(help_text='Encrypted API key (stored securely)')),
                ('key_name', models.CharField(help_text='User-friendly name for this key', max_length=255)),
                ('key_prefix', models.CharField(blank=True, help_text='First few characters of key (for identification)', max_length=20, null=True)),
                ('is_active', models.BooleanField(default=True, help_text='Whether this key is active and usable')),
                ('is_default', models.BooleanField(default=False, help_text='Whether this is the default key for this provider')),
                ('is_validated', models.BooleanField(default=False, help_text='Whether key has been validated with provider')),
                ('last_validated_at', models.DateTimeField(blank=True, help_text='When key was last validated', null=True)),
                ('validation_error', models.TextField(blank=True, help_text='Error message from last validation attempt', null=True)),
                ('usage_count', models.IntegerField(default=0, help_text='Number of times this key has been used')),
                ('last_used_at', models.DateTimeField(blank=True, help_text='When this key was last used', null=True)),
                ('total_tokens_used', models.BigIntegerField(default=0, help_text='Total tokens used with this key')),
                ('daily_limit', models.IntegerField(blank=True, help_text='Daily usage limit (in tokens, null = unlimited)', null=True)),
                ('monthly_limit', models.IntegerField(blank=True, help_text='Monthly usage limit (in tokens, null = unlimited)', null=True)),
                ('custom_config', models.JSONField(blank=True, default=dict, help_text='Provider-specific configuration')),
                ('user', models.ForeignKey(help_text='User who owns this API key', on_delete=django.db.models.deletion.CASCADE, related_name='api_keys', to=settings.AUTH_USER_MODEL)),
            ],
            options={
                'verbose_name': 'User API Key',
                'verbose_name_plural': 'User API Keys',
                'ordering': ['-is_default', '-last_used_at'],
            },
        ),
        migrations.CreateModel(
            name='UserDocument',
            fields=[
                ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
                ('created_at', models.DateTimeField(auto_now_add=True)),
                ('updated_at', models.DateTimeField(auto_now=True)),
                ('file', models.FileField(help_text='Uploaded document file', upload_to='user_documents/%Y/%m/%d/')),
                ('file_name', models.CharField(help_text='Original filename', max_length=255)),
                ('file_size', models.BigIntegerField(help_text='File size in bytes')),
                ('file_type', models.CharField(help_text='MIME type of the file', max_length=100)),
                ('file_extension', models.CharField(help_text='File extension (e.g., .pdf, .docx)', max_length=10)),
                ('processing_status', models.CharField(choices=[('pending', 'Pending Processing'), ('processing', 'Processing'), ('completed', 'Completed'), ('failed', 'Failed')], default='pending', help_text='Document processing status', max_length=20)),
                ('processed_at', models.DateTimeField(blank=True, help_text='When processing completed', null=True)),
                ('vector_collection_name', models.CharField(blank=True, db_index=True, help_text='PGVector collection name where embeddings are stored (REQUIRED for vector operations)', max_length=255, null=True)),
                ('vector_collection_metadata', models.JSONField(blank=True, default=dict, help_text='Optional metadata for the PGVector collection itself')),
                ('vector_store_ids', models.JSONField(blank=True, default=list, help_text="List of pgvector document IDs for this file's chunks")),
                ('chunk_count', models.IntegerField(default=0, help_text='Number of chunks/embeddings created')),
                ('title', models.CharField(blank=True, help_text='User-defined or extracted document title', max_length=255, null=True)),
                ('description', models.TextField(blank=True, help_text='User description or summary of document', null=True)),
                ('tags', models.JSONField(blank=True, default=list, help_text='User-defined tags for organization')),
                ('extracted_metadata', models.JSONField(blank=True, default=dict, help_text='Metadata extracted from document (author, date, pages, etc.)')),
                ('vector_metadata', models.JSONField(blank=True, default=dict, help_text="Searchable metadata for pgvector filtering (e.g., {'user_id': '123', 'category': 'research', 'date': '2025-01'})")),
                ('page_count', models.IntegerField(blank=True, help_text='Number of pages (for PDFs, documents)', null=True)),
                ('word_count', models.IntegerField(blank=True, help_text='Approximate word count', null=True)),
                ('is_active', models.BooleanField(default=True, help_text='Whether this document is active and searchable')),
                ('is_shared', models.BooleanField(default=False, help_text='Whether document is shared with other users')),
                ('share_settings', models.JSONField(blank=True, default=dict, help_text='Document sharing configuration')),
                ('processing_error', models.TextField(blank=True, help_text='Error message if processing failed', null=True)),
                ('retry_count', models.IntegerField(default=0, help_text='Number of processing retries')),
                ('chat_session', models.ForeignKey(blank=True, help_text='Chat session this document is associated with', null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='documents', to='chatbot.chatsession')),
                ('user', models.ForeignKey(help_text='User who uploaded this document', on_delete=django.db.models.deletion.CASCADE, related_name='documents', to=settings.AUTH_USER_MODEL)),
            ],
            options={
                'verbose_name': 'User Document',
                'verbose_name_plural': 'User Documents',
                'ordering': ['-created_at'],
            },
        ),
        migrations.CreateModel(
            name='UserPreference',
            fields=[
                ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
                ('created_at', models.DateTimeField(auto_now_add=True)),
                ('updated_at', models.DateTimeField(auto_now=True)),
                ('default_model', models.CharField(choices=[('gpt-5-mini', 'GPT-5 Mini (Recommended)'), ('gpt-5-nano', 'GPT-5 Nano (Smaller/Faster)'), ('gpt-4.1-mini', 'GPT-4.1 Mini (Faster/Cheaper)'), ('gpt-4o-mini', 'GPT-4o Mini (Faster/Cheaper)'), ('o4-mini', 'GPT-o4 Mini (Reasoning)')], default='gpt-5-mini', help_text='Default AI model for new conversations', max_length=100)),
                ('default_temperature', models.FloatField(default=0.7, help_text='Default temperature (0.0-2.0). Higher = more creative')),
                ('default_max_tokens', models.IntegerField(default=2000, help_text='Default max tokens for responses')),
                ('enable_auto_summarization', models.BooleanField(default=True, help_text='Enable automatic conversation summarization')),
                ('summarization_trigger_tokens', models.IntegerField(default=384, help_text='Token count to trigger summarization')),
                ('max_summary_tokens', models.IntegerField(default=128, help_text='Maximum tokens in summary')),
                ('summarization_style', models.CharField(choices=[('concise', 'Concise (Brief summaries)'), ('detailed', 'Detailed (More context)'), ('bullet', 'Bullet Points')], default='concise', help_text='Style of automatic summaries', max_length=20)),
                ('custom_system_prompt', models.TextField(blank=True, help_text='Custom system prompt for all conversations', null=True)),
                ('use_custom_system_prompt', models.BooleanField(default=False, help_text='Use custom system prompt instead of default')),
                ('response_language', models.CharField(default='en', help_text='Preferred response language code (e.g., en, es, fr)', max_length=10)),
                ('enable_streaming', models.BooleanField(default=True, help_text='Enable streaming responses (word-by-word)')),
                ('enable_code_execution', models.BooleanField(default=False, help_text='Allow AI to execute code (advanced users only)')),
                ('daily_message_limit', models.IntegerField(default=100, help_text='Maximum messages per day (0 = unlimited)')),
                ('daily_token_limit', models.IntegerField(default=50000, help_text='Maximum tokens per day (0 = unlimited)')),
                ('theme', models.CharField(choices=[('light', 'Light Theme'), ('dark', 'Dark Theme'), ('auto', 'Auto (System)')], default='auto', help_text='Chat interface theme', max_length=20)),
                ('show_token_count', models.BooleanField(default=False, help_text='Show token count in chat interface')),
                ('enable_notifications', models.BooleanField(default=True, help_text='Enable browser notifications for AI responses')),
                ('save_conversation_history', models.BooleanField(default=True, help_text='Save conversation history for future reference')),
                ('allow_data_training', models.BooleanField(default=False, help_text='Allow conversations to be used for model improvement')),
                ('additional_settings', models.JSONField(blank=True, default=dict, help_text='Additional user-specific settings')),
                ('user', models.OneToOneField(help_text='User these preferences belong to', on_delete=django.db.models.deletion.CASCADE, related_name='ai_preferences', to=settings.AUTH_USER_MODEL)),
            ],
            options={
                'verbose_name': 'User Preference',
                'verbose_name_plural': 'User Preferences',
            },
        ),
        migrations.CreateModel(
            name='UserTool',
            fields=[
                ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
                ('created_at', models.DateTimeField(auto_now_add=True)),
                ('updated_at', models.DateTimeField(auto_now=True)),
                ('tool_name', models.CharField(help_text='Internal name of the tool (e.g., "web_search", "code_executor")', max_length=100)),
                ('tool_display_name', models.CharField(help_text='Human-readable tool name', max_length=255)),
                ('is_enabled', models.BooleanField(default=True, help_text='Whether this tool is enabled for the user')),
                ('configuration', models.JSONField(blank=True, default=dict, help_text='Tool-specific configuration settings')),
                ('description', models.TextField(blank=True, help_text='Description of what this tool does', null=True)),
                ('category', models.CharField(choices=[('search', 'Search & Retrieval'), ('code', 'Code Execution'), ('data', 'Data Processing'), ('integration', 'External Integration'), ('utility', 'Utility'), ('custom', 'Custom')], default='general', help_text='Tool category', max_length=50)),
                ('usage_count', models.IntegerField(default=0, help_text='Number of times this tool has been used')),
                ('last_used_at', models.DateTimeField(blank=True, help_text='When this tool was last used', null=True)),
                ('rate_limit', models.IntegerField(blank=True, help_text='Maximum uses per hour (null = unlimited)', null=True)),
                ('rate_limit_period', models.CharField(choices=[('minute', 'Per Minute'), ('hour', 'Per Hour'), ('day', 'Per Day')], default='hour', help_text='Rate limit period', max_length=20)),
                ('requires_approval', models.BooleanField(default=False, help_text='Whether tool usage requires admin approval')),
                ('is_approved', models.BooleanField(default=True, help_text='Whether usage is approved by admin')),
                ('approved_at', models.DateTimeField(blank=True, help_text='When this tool was approved', null=True)),
                ('approved_by', models.ForeignKey(blank=True, help_text='Admin who approved this tool', null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='approved_tools', to=settings.AUTH_USER_MODEL)),
                ('user', models.ForeignKey(help_text='User who configured this tool', on_delete=django.db.models.deletion.CASCADE, related_name='enabled_tools', to=settings.AUTH_USER_MODEL)),
            ],
            options={
                'verbose_name': 'User Tool',
                'verbose_name_plural': 'User Tools',
                'ordering': ['tool_display_name'],
            },
        ),
        migrations.AddIndex(
            model_name='chatsession',
            index=models.Index(fields=['user', '-last_message_at'], name='chatsession_user_lastmsg_idx'),
        ),
        migrations.AddIndex(
            model_name='chatsession',
            index=models.Index(fields=['user', 'is_active'], name='chatsession_user_active_idx'),
        ),
        migrations.AddIndex(
            model_name='chatsession',
            index=models.Index(fields=['user', 'is_archived'], name='chatsession_user_archived_idx'),
        ),
        migrations.AddIndex(
            model_name='chatsession',
            index=models.Index(fields=['is_pinned', '-last_message_at'], name='chatsession_pinned_idx'),
        ),
        migrations.AddIndex(
            model_name='messagefeedback',
            index=models.Index(fields=['user', '-created_at'], name='msgfeedback_user_date_idx'),
        ),
        migrations.AddIndex(
            model_name='messagefeedback',
            index=models.Index(fields=['chat_session', '-created_at'], name='msgfeedback_session_date_idx'),
        ),
        migrations.AddIndex(
            model_name='messagefeedback',
            index=models.Index(fields=['rating'], name='msgfeedback_rating_idx'),
        ),
        migrations.AddIndex(
            model_name='messagefeedback',
            index=models.Index(fields=['reported_issue'], name='msgfeedback_issue_idx'),
        ),
        migrations.AddIndex(
            model_name='messagefeedback',
            index=models.Index(fields=['reviewed'], name='msgfeedback_reviewed_idx'),
        ),
        migrations.AlterUniqueTogether(
            name='messagefeedback',
            unique_together={('checkpoint_id', 'message_index', 'user')},
        ),
        migrations.AddIndex(
            model_name='tokenusage',
            index=models.Index(fields=['user', '-created_at'], name='tokenusage_user_date_idx'),
        ),
        migrations.AddIndex(
            model_name='tokenusage',
            index=models.Index(fields=['chat_session', '-created_at'], name='tokenusage_session_date_idx'),
        ),
        migrations.AddIndex(
            model_name='tokenusage',
            index=models.Index(fields=['model_name'], name='tokenusage_model_idx'),
        ),
        migrations.AddIndex(
            model_name='tokenusage',
            index=models.Index(fields=['request_type'], name='tokenusage_type_idx'),
        ),
        migrations.AddIndex(
            model_name='tokenusage',
            index=models.Index(fields=['user', 'model_name'], name='tokenusage_user_model_idx'),
        ),
        migrations.AddIndex(
            model_name='userapikey',
            index=models.Index(fields=['user', 'provider'], name='apikey_user_provider_idx'),
        ),
        migrations.AddIndex(
            model_name='userapikey',
            index=models.Index(fields=['user', 'is_active'], name='apikey_user_active_idx'),
        ),
        migrations.AddIndex(
            model_name='userapikey',
            index=models.Index(fields=['is_default'], name='apikey_default_idx'),
        ),
        migrations.AlterUniqueTogether(
            name='userapikey',
            unique_together={('user', 'provider', 'key_name')},
        ),
        migrations.AddIndex(
            model_name='userdocument',
            index=models.Index(fields=['user', '-created_at'], name='userdoc_user_date_idx'),
        ),
        migrations.AddIndex(
            model_name='userdocument',
            index=models.Index(fields=['user', 'is_active'], name='userdoc_user_active_idx'),
        ),
        migrations.AddIndex(
            model_name='userdocument',
            index=models.Index(fields=['processing_status'], name='userdoc_status_idx'),
        ),
        migrations.AddIndex(
            model_name='userdocument',
            index=models.Index(fields=['file_type'], name='userdoc_type_idx'),
        ),
        migrations.AddIndex(
            model_name='userdocument',
            index=models.Index(fields=['vector_collection_name'], name='userdoc_collection_idx'),
        ),
        migrations.AddIndex(
            model_name='userdocument',
            index=models.Index(fields=['user', 'vector_collection_name'], name='userdoc_user_collection_idx'),
        ),
        migrations.AddIndex(
            model_name='usertool',
            index=models.Index(fields=['user', 'is_enabled'], name='usertool_user_enabled_idx'),
        ),
        migrations.AddIndex(
            model_name='usertool',
            index=models.Index(fields=['tool_name'], name='usertool_name_idx'),
        ),
        migrations.AddIndex(
            model_name='usertool',
            index=models.Index(fields=['category'], name='usertool_category_idx'),
        ),
        migrations.AlterUniqueTogether(
            name='usertool',
            unique_together={('user', 'tool_name')},
        ),
    ]
