# === FORMS ===
# Django form classes for the app.
# - AttendanceLogForm: daily work log creation with date ranges and conflict detection
# - PayrollAdjustmentForm: adding bonuses, deductions, overtime, and loan adjustments
# - ExpenseReceiptForm + ExpenseLineItemFormSet: expense receipt creation with dynamic line items

from django import forms
from django.forms import inlineformset_factory
from .models import WorkLog, Project, Team, Worker, PayrollAdjustment, ExpenseReceipt, ExpenseLineItem


class AttendanceLogForm(forms.ModelForm):
    """
    Form for logging daily worker attendance.

    Extra fields (not on the WorkLog model):
    - end_date: optional end date for logging multiple days at once
    - include_saturday: whether to include Saturdays in a date range
    - include_sunday: whether to include Sundays in a date range

    The supervisor field is NOT shown on the form — it gets set automatically
    in the view to whoever is logged in.
    """

    # --- Extra fields for date range logging ---
    # These aren't on the WorkLog model, they're only used by the form
    end_date = forms.DateField(
        required=False,
        widget=forms.DateInput(attrs={'type': 'date', 'class': 'form-control'}),
        label='End Date',
        help_text='Leave blank to log a single day'
    )
    include_saturday = forms.BooleanField(
        required=False,
        initial=False,
        label='Include Saturdays',
        widget=forms.CheckboxInput(attrs={'class': 'form-check-input'})
    )
    include_sunday = forms.BooleanField(
        required=False,
        initial=False,
        label='Include Sundays',
        widget=forms.CheckboxInput(attrs={'class': 'form-check-input'})
    )

    class Meta:
        model = WorkLog
        # Supervisor is NOT included — it gets set in the view automatically
        fields = ['date', 'project', 'team', 'workers', 'overtime_amount', 'notes']
        widgets = {
            'date': forms.DateInput(attrs={'type': 'date', 'class': 'form-control'}),
            'project': forms.Select(attrs={'class': 'form-select'}),
            'team': forms.Select(attrs={'class': 'form-select'}),
            'workers': forms.CheckboxSelectMultiple(attrs={'class': 'form-check-input'}),
            'overtime_amount': forms.Select(attrs={'class': 'form-select'}),
            'notes': forms.Textarea(attrs={
                'class': 'form-control',
                'rows': 3,
                'placeholder': 'Any notes about the day...'
            }),
        }

    def __init__(self, *args, **kwargs):
        # Pop 'user' from kwargs so we can filter based on who's logged in
        self.user = kwargs.pop('user', None)
        super().__init__(*args, **kwargs)

        # --- Supervisor filtering ---
        # If the user is NOT an admin, they can only see:
        #   - Projects they're assigned to (via project.supervisors M2M)
        #   - Workers in teams they supervise
        if self.user and not (self.user.is_staff or self.user.is_superuser):
            # Only show projects this supervisor is assigned to
            self.fields['project'].queryset = Project.objects.filter(
                active=True,
                supervisors=self.user
            )
            # Only show workers from teams this supervisor manages
            supervised_teams = Team.objects.filter(supervisor=self.user, active=True)
            self.fields['workers'].queryset = Worker.objects.filter(
                active=True,
                teams__in=supervised_teams
            ).distinct()
            # Only show teams this supervisor manages
            self.fields['team'].queryset = supervised_teams
        else:
            # Admins see everything
            self.fields['workers'].queryset = Worker.objects.filter(active=True)
            self.fields['project'].queryset = Project.objects.filter(active=True)
            self.fields['team'].queryset = Team.objects.filter(active=True)

        # Make team optional (it already is on the model, but make the form match)
        self.fields['team'].required = False

        # Force start date to be blank — don't pre-fill with today's date.
        # Django 5.x auto-fills form fields from model defaults (default=timezone.now),
        # but we want the user to consciously pick a date every time.
        self.fields['date'].initial = None

    def clean(self):
        """Validate the date range makes sense."""
        cleaned_data = super().clean()
        start_date = cleaned_data.get('date')
        end_date = cleaned_data.get('end_date')

        if start_date and end_date and end_date < start_date:
            raise forms.ValidationError('End date cannot be before start date.')

        return cleaned_data


class PayrollAdjustmentForm(forms.ModelForm):
    """
    Form for adding/editing payroll adjustments (bonuses, deductions, etc.).

    Business rule: A project is required for Overtime, Bonus, Deduction, and
    Advance Payment types. Loan and Loan Repayment are worker-level (no project).
    """

    class Meta:
        model = PayrollAdjustment
        fields = ['type', 'project', 'worker', 'amount', 'date', 'description']
        widgets = {
            'type': forms.Select(attrs={'class': 'form-select'}),
            'project': forms.Select(attrs={'class': 'form-select'}),
            'worker': forms.Select(attrs={'class': 'form-select'}),
            'amount': forms.NumberInput(attrs={
                'class': 'form-control',
                'step': '0.01',
                'min': '0.01'
            }),
            'date': forms.DateInput(attrs={'type': 'date', 'class': 'form-control'}),
            'description': forms.Textarea(attrs={
                'class': 'form-control',
                'rows': 2,
                'placeholder': 'Reason for this adjustment...'
            }),
        }

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.fields['project'].queryset = Project.objects.filter(active=True)
        self.fields['project'].required = False
        self.fields['worker'].queryset = Worker.objects.filter(active=True)

    def clean(self):
        """Validate that project-required types have a project selected."""
        cleaned_data = super().clean()
        adj_type = cleaned_data.get('type', '')
        project = cleaned_data.get('project')

        # These types must have a project — they're tied to specific work
        project_required_types = ('Overtime', 'Bonus', 'Deduction', 'Advance Payment')
        if adj_type in project_required_types and not project:
            self.add_error('project', 'A project must be selected for this adjustment type.')

        return cleaned_data


# =============================================================================
# === EXPENSE RECEIPT FORM ===
# Used on the /receipts/create/ page.
# The form handles receipt header fields (vendor, date, payment method, VAT type).
# Line items are handled separately by the ExpenseLineItemFormSet below.
# =============================================================================

class ExpenseReceiptForm(forms.ModelForm):
    """
    Form for the receipt header — vendor, date, payment method, VAT type.
    Line items (products + amounts) are handled by ExpenseLineItemFormSet.
    """

    class Meta:
        model = ExpenseReceipt
        fields = ['date', 'vendor_name', 'description', 'payment_method', 'vat_type']
        widgets = {
            'date': forms.DateInput(attrs={'type': 'date', 'class': 'form-control'}),
            'vendor_name': forms.TextInput(attrs={
                'class': 'form-control',
                'placeholder': 'Vendor Name'
            }),
            'description': forms.Textarea(attrs={
                'class': 'form-control',
                'rows': 2,
                'placeholder': 'What was purchased and why...'
            }),
            'payment_method': forms.Select(attrs={'class': 'form-select'}),
            # Radio buttons for VAT type — shown as 3 options side by side
            'vat_type': forms.RadioSelect(attrs={'class': 'form-check-input'}),
        }


# === LINE ITEM FORMSET ===
# A "formset" is a group of identical mini-forms — one per line item.
# inlineformset_factory creates it automatically from the parent-child relationship.
# - extra=1: start with 1 blank row
# - can_delete=True: allows removing rows (checks a hidden DELETE checkbox)
ExpenseLineItemFormSet = inlineformset_factory(
    ExpenseReceipt,         # Parent model
    ExpenseLineItem,        # Child model
    fields=['product_name', 'amount'],
    extra=1,                # Show 1 blank row by default
    can_delete=True,        # Allow deleting rows
    widgets={
        'product_name': forms.TextInput(attrs={
            'class': 'form-control',
            'placeholder': 'Item Name'
        }),
        'amount': forms.NumberInput(attrs={
            'class': 'form-control item-amount',
            'step': '0.01',
            'placeholder': '0.00'
        }),
    }
)
