from django import forms
from django.forms import inlineformset_factory
from django.core.exceptions import ValidationError
from .models import  Account, Transaction, JournalEntry, PurchaseReturn
from .models import  PurchaseOrder, PurchaseOrderItem
from partners.models import Supplier, Company
from products.models import Product, Warehouse
from projects.models import Project

class AccountForm(forms.ModelForm):
    class Meta:
        model = Account
        fields = ['code', 'name', 'sub_type', 'parent', 'is_active', 'description']
        widgets = {
            'code': forms.TextInput(attrs={'class': 'form-control'}),
            'name': forms.TextInput(attrs={'class': 'form-control'}),
            'sub_type': forms.Select(attrs={'class': 'form-control'}),
            'parent': forms.Select(attrs={'class': 'form-control'}),
            'description': forms.Textarea(attrs={'rows': 3}),
        }

    def __init__(self, *args, **kwargs):
        super(AccountForm, self).__init__(*args, **kwargs)

        # Get all accounts and sort them
        accounts = Account.objects.all().order_by('code')

        # Create a label function for indentation
        def get_label(account, level=0):
            prefix = "—" * level
            label = f"{prefix} {account.name}"
            return label

        # Build a flattened, indented list of accounts
        def get_account_choices(account_list, parent=None, level=0):
            result = []
            children = [acc for acc in account_list if acc.parent_id == (parent.id if parent else None)]
            for child in children:
                result.append((child.id, get_label(child, level)))
                result += get_account_choices(account_list, child, level + 1)
            return result

        # Set the queryset and choices with indentation
        account_list = list(accounts)
        self.fields['parent'].choices = [('', '---------')] + get_account_choices(account_list)

class JournalEntryForm(forms.ModelForm):
    class Meta:
        model = JournalEntry
        fields = '__all__'
        exclude = ['created_by']
        widgets = {
            'date': forms.DateInput(attrs={'type': 'date', 'class': 'form-control'}),
            'description': forms.Textarea(attrs={'rows': 2, 'class': 'form-control'}),
            'reference': forms.TextInput(attrs={'class': 'form-control'}),
            'project': forms.Select(attrs={'class': 'form-select'}),
            'status': forms.Select(attrs={'class': 'form-select'}),
            'supplier': forms.Select(attrs={'class': 'form-select'}),
            'customer': forms.Select(attrs={'class': 'form-select'}),
        }

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.fields['date'].widget.attrs.update({'class': 'form-control'})
        self.fields['description'].widget.attrs.update({
            'class': 'form-control',
            'rows': 2
        })
        self.fields['reference'].widget.attrs.update({'class': 'form-control'})
        self.fields['project'].widget.attrs.update({'class': 'form-select'})
        self.fields['status'].initial = 'draft'  # Set default
        self.fields['status'].widget.attrs.update({'class': 'form-select'})
        self.fields['supplier'].widget.attrs.update({'class': 'form-select'})
        self.fields['customer'].widget.attrs.update({'class': 'form-select'})

class TransactionForm(forms.ModelForm):
    id = forms.IntegerField(required=False, widget=forms.HiddenInput())
    class Meta:
        model = Transaction
        fields = ['id','account', 'debit', 'credit', 'description']
        widgets = {
            'account': forms.Select(attrs={'class': 'form-select account-select'}),
            'debit': forms.NumberInput(attrs={'class': 'form-control debit-input', 'placeholder': '0.00'}),
            'credit': forms.NumberInput(attrs={'class': 'form-control credit-input', 'placeholder': '0.00'}),
            'description': forms.TextInput(attrs={'class': 'form-control'}),
        }
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.fields['debit'].required = False
        self.fields['credit'].required = False
        
    def clean(self):
        cleaned_data = super().clean()
        debit = cleaned_data.get('debit', 0)
        credit = cleaned_data.get('credit', 0)
        
        if debit and credit:
            raise ValidationError("Transaction cannot have both debit and credit amounts")
        if not debit and not credit:
            raise ValidationError("Transaction must have either debit or credit amount")
        
        return cleaned_data

class PurchaseOrderForm(forms.ModelForm):
    class Meta:
        model = PurchaseOrder
        fields = '__all__'
        exclude = ['created_by', 'po_number']
        widgets = {
            'order_date': forms.DateInput(attrs={'type': 'date', 'class': 'form-control'}),
            'warehouse': forms.Select(attrs={
                'class': 'form-select',
                'required': 'required'
            }),
            
        }

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.fields['supplier'].widget.attrs.update({'class': 'form-control'})
        self.fields['project'].queryset = Project.objects.all()
        self.fields['project'].widget.attrs.update({'class': 'form-control'})
        self.fields['status'].widget.attrs.update({'class': 'form-control'})
        # self.fields['po_number'].widget.attrs.update({'class': 'form-control'})
        self.fields['warehouse'].queryset = Warehouse.objects.filter(is_active=True)

         # Handle po_number for edit case
        if self.instance and self.instance.pk:
            self.fields['po_number'] = forms.CharField(
                required=False,
                widget=forms.TextInput(attrs={
                    'class': 'form-control',
                    'readonly': 'readonly'
                }))
            self.initial['po_number'] = self.instance.po_number

    def clean(self):
        cleaned_data = super().clean()
        if self.instance.pk and cleaned_data.get('status') == 'completed':
            if not hasattr(self.instance, 'warehouse'):
                raise forms.ValidationError("Cannot complete PO without warehouse assignment")
        return cleaned_data

class PurchaseOrderItemForm(forms.ModelForm):
    class Meta:
        model = PurchaseOrderItem
        fields = ['product', 'price', 'quantity']
        widgets = {
            'product': forms.Select(attrs={'class': 'form-control'}),
            'price': forms.NumberInput(attrs={'class': 'form-control', 'step': '0.01'}),
            'quantity': forms.NumberInput(attrs={'class': 'form-control'}),
        }

PurchaseOrderItemFormSet = inlineformset_factory(
    PurchaseOrder,
    PurchaseOrderItem,
    form=PurchaseOrderItemForm,
    extra=1,
    can_delete=True
)



# Returns sales and purchases

class PurchaseReturnForm(forms.ModelForm):
    class Meta:
        model = PurchaseReturn
        fields = '__all__'

    def __init__(self, *args, **kwargs):
        po = kwargs.pop('po', None)
        super().__init__(*args, **kwargs)

        if po:
            # Limit product choices to PO items
            self.fields['product'].queryset = Product.objects.filter(
                id__in=po.items.values_list('product_id', flat=True)
            )

        # Optional: make reason a textarea or styled dropdown
        self.fields['notes'].widget.attrs.update({'class': 'form-control'})
        # self.fields['quantity'].widget.attrs.update({'class': 'form-control', 'min': 1})

class PurchaseReturnItemForm(forms.Form):
    product = forms.ModelChoiceField(queryset=Product.objects.all(), widget=forms.Select(attrs={'class': 'form-control'}))
    quantity = forms.DecimalField(max_digits=10, decimal_places=2, min_value=0, widget=forms.NumberInput(attrs={'class': 'form-control'}))
    price = forms.DecimalField(max_digits=10, decimal_places=2, required=False, widget=forms.NumberInput(attrs={'readonly': 'readonly', 'class': 'form-control'}))

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)

        # 👉 If initial price is passed, set it inside the input value
        if 'initial' in kwargs:
            initial = kwargs['initial']
            if initial.get('price') is not None:
                self.fields['price'].widget.attrs['value'] = f"{initial['price']:.2f}"

