"""
Django Forms for Jingles Application

This module contains form definitions for creating and editing
jingle templates, detections, and related models.
"""

import re
from django import forms
from django.utils.text import slugify
from apps.jingles.models import JingleTemplate


class JingleTemplateForm(forms.ModelForm):
    """
    Form for creating and editing jingle templates.
    
    Provides validation for jingle template configuration including
    image upload, slug generation, and threshold validation.
    """
    
    image_file = forms.ImageField(
        required=True,
        help_text="Upload a reference image for jingle detection",
        widget=forms.FileInput(attrs={
            'class': 'block w-full text-sm text-gray-500 file:mr-4 file:py-2 file:px-4 file:rounded-full file:border-0 file:text-sm file:font-semibold file:bg-blue-50 file:text-blue-700 hover:file:bg-blue-100',
            'accept': 'image/*'
        })
    )
    
    class Meta:
        model = JingleTemplate
        fields = [
            'name', 'description', 'category', 
            'similarity_threshold', 'is_active'
        ]
        
        widgets = {
            'name': forms.TextInput(attrs={
                'class': 'mt-1 block w-full border-gray-300 rounded-md shadow-sm focus:ring-blue-500 focus:border-blue-500',
                'placeholder': 'Enter jingle name'
            }),
            'description': forms.Textarea(attrs={
                'class': 'mt-1 block w-full border-gray-300 rounded-md shadow-sm focus:ring-blue-500 focus:border-blue-500',
                'rows': 3,
                'placeholder': 'Describe the jingle and its context'
            }),
            'category': forms.Select(attrs={
                'class': 'mt-1 block w-full border-gray-300 rounded-md shadow-sm focus:ring-blue-500 focus:border-blue-500'
            }),
            'similarity_threshold': forms.NumberInput(attrs={
                'class': 'mt-1 block w-full border-gray-300 rounded-md shadow-sm focus:ring-blue-500 focus:border-blue-500',
                'step': '0.01',
                'min': '0.0',
                'max': '1.0'
            }),
            'is_active': forms.CheckboxInput(attrs={
                'class': 'h-4 w-4 text-blue-600 focus:ring-blue-500 border-gray-300 rounded'
            }),
        }
        
        help_texts = {
            'name': 'Human-readable name for the jingle',
            'description': 'Description of the jingle content and context',
            'category': 'Category classification for this jingle',
            'similarity_threshold': 'Detection threshold (0.0-1.0, lower = more sensitive)',
            'is_active': 'Enable this template for detection',
        }
    
    def __init__(self, *args, **kwargs):
        """Initialize form with default values."""
        super().__init__(*args, **kwargs)
        
        # Set default similarity threshold if not provided
        if not self.instance.pk and not self.initial.get('similarity_threshold'):
            self.initial['similarity_threshold'] = 0.1
    
    
    def clean_similarity_threshold(self):
        """
        Validate similarity threshold range.
        
        Returns:
            float: Validated threshold
            
        Raises:
            ValidationError: If threshold is out of range
        """
        threshold = self.cleaned_data.get('similarity_threshold')
        
        if threshold is not None:
            if threshold < 0.0 or threshold > 1.0:
                raise forms.ValidationError('Similarity threshold must be between 0.0 and 1.0')
        
        return threshold
    
    def clean(self):
        """
        Generate slug from name during form validation.
        """
        cleaned_data = super().clean()
        name = cleaned_data.get('name')
        
        if name:
            # Auto-generate slug from name
            base_slug = slugify(name).lower()
            # Ensure slug meets validation requirements
            base_slug = re.sub(r'[^a-z0-9-]', '', base_slug)
            base_slug = re.sub(r'-+', '-', base_slug)  # Remove consecutive hyphens
            base_slug = base_slug.strip('-')  # Remove leading/trailing hyphens
            
            # If slug starts with number, prefix with 'jingle-'
            if base_slug and base_slug[0].isdigit():
                base_slug = f"jingle-{base_slug}"
            
            # Ensure minimum length
            if len(base_slug) < 3:
                base_slug = f"jingle-{base_slug or 'new'}"[:50]
            
            # Ensure uniqueness by appending number if needed
            slug = base_slug
            counter = 1
            while True:
                existing = JingleTemplate.objects.filter(slug=slug)
                if self.instance.pk:
                    existing = existing.exclude(pk=self.instance.pk)
                
                if not existing.exists():
                    break
                    
                slug = f"{base_slug}-{counter}"
                counter += 1
            
            # Set the slug in cleaned_data
            cleaned_data['slug'] = slug
        
        return cleaned_data
    
    def save(self, commit=True):
        """
        Save the jingle template with auto-generated slug and image file handling.
        
        Args:
            commit (bool): Whether to save to database
            
        Returns:
            JingleTemplate: The saved template instance
        """
        template = super().save(commit=False)
        
        # Set slug from cleaned data
        if hasattr(self, 'cleaned_data') and 'slug' in self.cleaned_data:
            template.slug = self.cleaned_data['slug']
        
        # Handle image file upload
        image_file = self.cleaned_data.get('image_file')
        if image_file:
            # Generate file path based on slug
            import os
            from django.conf import settings
            from django.core.files.storage import default_storage
            
            # Create directory if it doesn't exist
            upload_dir = os.path.join('jingles', template.slug)
            
            # Save file with original name
            file_path = os.path.join(upload_dir, image_file.name)
            saved_path = default_storage.save(file_path, image_file)
            
            # Store the path in the model
            template.image_path = saved_path
        
        if commit:
            template.save()
        
        return template
