from django import forms
from .models import Filament, FilamentColor, FilamentType


class FilamentTypeForm(forms.ModelForm):
    """Form for managing FilamentType registry"""

    PRESET_TYPES = ['PLA', 'PETG', 'PET', 'ABS', 'ASA', 'TPU', 'PA', 'PC', 'PPS']
    PRESET_SUB_TYPES = [
        'PLA Basic', 'PLA Matte', 'PLA Silk', 'PLA Metal', 'PLA Marble', 'PLA Glow', 'PLA-CF',
        'PETG Basic', 'PETG-CF', 'PETG-HF', 'ABS', 'TPU 95A', 'PA6-CF', 'ASA', 'PC', 'PPS-CF',
        'Support W', 'Support G',
    ]
    PRESET_BRANDS = [
        'Bambu Lab', 'eSUN', 'Polymaker', 'Hatchbox', 'Prusament',
        'MatterHackers', 'Overture', '3DXTech', 'ColorFabb',
    ]

    class Meta:
        model = FilamentType
        fields = ['type', 'sub_type', 'brand']
        widgets = {
            'type': forms.TextInput(attrs={
                'class': 'form-control',
                'placeholder': 'e.g., PLA, PETG, ABS'
            }),
            'sub_type': forms.TextInput(attrs={
                'class': 'form-control',
                'placeholder': 'e.g., PLA Basic, PLA Matte (optional)'
            }),
            'brand': forms.TextInput(attrs={
                'class': 'form-control',
                'placeholder': 'e.g., Bambu Lab'
            }),
        }


class FilamentForm(forms.ModelForm):
    color_hex_text = forms.CharField(
        required=False,
        max_length=7,
        widget=forms.TextInput(attrs={
            'class': 'form-control',
            'placeholder': '#000000',
            'pattern': '#[0-9A-Fa-f]{6}',
            'id': 'id_color_hex_text'
        }),
        label='Color Hex Code'
    )

    class Meta:
        model = Filament
        fields = [
            'tray_uuid', 'tag_uid', 'tag_id', 'created_by',
            'filament_type', 'type', 'sub_type', 'brand', 'color', 'color_hex', 'is_transparent',
            'diameter', 'initial_weight_grams',
            'remaining_percent', 'remaining_weight_grams',
            'is_loaded_in_ams', 'current_tray_id', 'ams_unit_id', 'ams_type',
            'purchase_date', 'purchase_price', 'supplier', 'notes'
        ]
        widgets = {
            'tray_uuid': forms.TextInput(attrs={
                'class': 'form-control font-monospace',
                'placeholder': 'Optional - Auto-filled by MQTT',
                'style': 'font-size: 0.9em;'
            }),
            'tag_uid': forms.TextInput(attrs={
                'class': 'form-control font-monospace',
                'placeholder': 'Optional - RFID chip ID',
                'style': 'font-size: 0.9em;'
            }),
            'tag_id': forms.TextInput(attrs={'class': 'form-control', 'placeholder': 'Optional - User-defined ID'}),
            'created_by': forms.Select(attrs={'class': 'form-select'}),
            'filament_type': forms.Select(attrs={'class': 'form-select', 'id': 'id_filament_type'}),
            'type': forms.TextInput(attrs={'class': 'form-control', 'placeholder': 'e.g., PLA, PETG, ABS'}),
            'sub_type': forms.TextInput(attrs={'class': 'form-control', 'placeholder': 'e.g., PLA Basic (optional)'}),
            'brand': forms.TextInput(attrs={'class': 'form-control', 'placeholder': 'e.g., Bambu Lab'}),
            'color': forms.Select(attrs={'class': 'form-select', 'id': 'id_color'}),
            'color_hex': forms.TextInput(attrs={
                'class': 'form-control',
                'type': 'color',
                'id': 'id_color_hex_picker'
            }),
            'diameter': forms.NumberInput(attrs={'class': 'form-control', 'step': '0.01'}),
            'initial_weight_grams': forms.NumberInput(attrs={'class': 'form-control', 'placeholder': '1000'}),
            'remaining_percent': forms.NumberInput(attrs={'class': 'form-control', 'min': '0', 'max': '100'}),
            'remaining_weight_grams': forms.NumberInput(attrs={'class': 'form-control', 'readonly': 'readonly'}),
            'is_transparent': forms.CheckboxInput(attrs={'class': 'form-check-input', 'id': 'id_is_transparent'}),
            'is_loaded_in_ams': forms.CheckboxInput(attrs={'class': 'form-check-input'}),
            'current_tray_id': forms.NumberInput(attrs={
                'class': 'form-control', 'min': '0', 'max': '15',
                'placeholder': '0–3 for AMS / AMS 2 Pro, 0 for AMS HT',
            }),
            'ams_unit_id': forms.NumberInput(attrs={
                'class': 'form-control', 'min': '0', 'max': '255',
                'placeholder': 'AMS unit id (0,1,… or 128 for AMS HT)',
            }),
            'ams_type': forms.Select(attrs={'class': 'form-select'}),
            'purchase_date': forms.DateInput(attrs={'class': 'form-control', 'type': 'date'}),
            'purchase_price': forms.NumberInput(attrs={'class': 'form-control', 'step': '0.01'}),
            'supplier': forms.TextInput(attrs={'class': 'form-control'}),
            'notes': forms.Textarea(attrs={'class': 'form-control', 'rows': 3}),
        }

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        if self.instance and self.instance.color_hex:
            self.fields['color_hex_text'].initial = self.instance.color_hex

        self.fields['filament_type'].queryset = FilamentType.objects.all()
        self.fields['filament_type'].empty_label = '--- Select Filament Type ---'
        self.fields['filament_type'].required = False

        self.fields['type'].required = False
        self.fields['sub_type'].required = False
        self.fields['brand'].required = False
        self.fields['ams_unit_id'].required = False
        self.fields['ams_type'].required = False

        self._populate_color_choices()

    def _populate_color_choices(self):
        """Populate color field choices from FilamentColor database with suggested colors"""
        from .utils import strip_color_padding, match_filament_color

        color_choices = [('', '--- Select Color ---')]
        suggested_color = None

        all_colors = FilamentColor.objects.all().order_by('filament_type', 'filament_sub_type', 'color_name')

        if self.instance and self.instance.type and self.instance.color_hex:
            color_code = strip_color_padding(self.instance.color_hex.lstrip('#'))
            suggested = match_filament_color(
                filament_type=self.instance.type,
                filament_sub_type=self.instance.sub_type,
                color_code=color_code,
                brand=self.instance.brand or 'Bambu Lab'
            )
            if suggested:
                suggested_color = suggested

        if suggested_color:
            color_choices.append((
                suggested_color.color_name,
                f"SUGGESTED: {suggested_color.filament_sub_type or suggested_color.filament_type}: {suggested_color.color_name}"
            ))
            color_choices.append(('---separator---', '---' * 20))

        for color in all_colors:
            if suggested_color and color.pk == suggested_color.pk:
                continue

            display_name = f"{color.filament_sub_type or color.filament_type}: {color.color_name}"
            color_choices.append((color.color_name, display_name))

        color_choices.append(('---separator2---', '---' * 20))
        color_choices.append(('custom', 'Custom (type in manually)'))

        self.fields['color'].widget.choices = color_choices

    def clean(self):
        cleaned_data = super().clean()
        is_loaded = cleaned_data.get('is_loaded_in_ams')
        tray_id = cleaned_data.get('current_tray_id')

        color_hex_text = cleaned_data.get('color_hex_text')
        if color_hex_text:
            cleaned_data['color_hex'] = color_hex_text

        color = cleaned_data.get('color')
        if color and 'separator' in color:
            cleaned_data['color'] = ''

        ft = cleaned_data.get('filament_type')
        if ft:
            cleaned_data['type'] = ft.type
            cleaned_data['sub_type'] = ft.sub_type or ''
            cleaned_data['brand'] = ft.brand

        if is_loaded and tray_id is None:
            raise forms.ValidationError('Tray ID required when filament is loaded in AMS')

        return cleaned_data


class FilamentColorForm(forms.ModelForm):
    """Form for managing FilamentColor database"""

    color_code = forms.CharField(
        required=False,
        widget=forms.HiddenInput()
    )

    color_hex_input = forms.CharField(
        required=True,
        max_length=7,
        widget=forms.TextInput(attrs={
            'class': 'form-control',
            'placeholder': '#000000',
            'pattern': '#[0-9A-Fa-f]{6}',
        }),
        label='Color Hex Code'
    )

    class Meta:
        model = FilamentColor
        fields = ['color_code', 'color_name', 'filament_type_fk', 'filament_type', 'filament_sub_type', 'brand']
        widgets = {
            'color_name': forms.TextInput(attrs={'class': 'form-control', 'placeholder': 'e.g., Black, Orange'}),
            'filament_type_fk': forms.Select(attrs={'class': 'form-select'}),
            'filament_type': forms.HiddenInput(),
            'filament_sub_type': forms.HiddenInput(),
            'brand': forms.HiddenInput(),
        }

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        if self.instance and self.instance.color_code:
            self.fields['color_hex_input'].initial = f"#{self.instance.color_code}"

        self.fields['filament_type_fk'].queryset = FilamentType.objects.all()
        self.fields['filament_type_fk'].empty_label = '--- Select Filament Type ---'
        self.fields['filament_type_fk'].required = False

        self.fields['filament_type'].required = False
        self.fields['filament_sub_type'].required = False
        self.fields['brand'].required = False

    def clean(self):
        cleaned_data = super().clean()

        color_hex = cleaned_data.get('color_hex_input', '')
        if color_hex:
            color_code = color_hex.lstrip('#').upper()[:6]
            cleaned_data['color_code'] = color_code

        ft_fk = cleaned_data.get('filament_type_fk')
        if ft_fk:
            cleaned_data['filament_type'] = ft_fk.type
            cleaned_data['filament_sub_type'] = ft_fk.sub_type or ''
            cleaned_data['brand'] = ft_fk.brand

        return cleaned_data
