from django import forms
from django.contrib.auth import get_user_model
from django.core.exceptions import ValidationError

from accounts.models import KYCDocument, ShipperProfile, TransporterProfile, UserRole, VehicleDocument
from core.models import Trip

User = get_user_model()


_ACCOUNT_TYPE_CHOICES = (
    ('INDIVIDUAL', 'Shipper — Individual'),
    ('BUSINESS', 'Shipper — Business'),
    ('DRIVER', 'Transporter — Driver'),
    ('FLEET_OWNER', 'Transporter — Fleet owner'),
)


class AdminUserCreateForm(forms.Form):
    email = forms.EmailField()
    password = forms.CharField(widget=forms.PasswordInput, min_length=8)
    first_name = forms.CharField(required=False, strip=True)
    last_name = forms.CharField(required=False, strip=True)
    phone = forms.CharField(required=False, strip=True)
    role = forms.ChoiceField(choices=[(UserRole.Role.SHIPPER, 'Shipper'), (UserRole.Role.TRANSPORTER, 'Transporter')])
    account_type = forms.ChoiceField(
        label='Account type',
        required=False,
        choices=(('', '— (Admin only: leave blank)'),) + _ACCOUNT_TYPE_CHOICES,
        help_text='Required for Shipper and Transporter; leave blank when role is Admin.',
    )
    company_name = forms.CharField(required=False, strip=True)
    national_id_number = forms.CharField(required=False, strip=True, max_length=64)
    national_id_expiry_date = forms.DateField(
        required=False,
        input_formats=['%Y-%m-%d', '%m/%d/%Y', '%d/%m/%Y'],
    )
    passport_number = forms.CharField(required=False, strip=True, max_length=64)
    passport_expiry_date = forms.DateField(
        required=False,
        input_formats=['%Y-%m-%d', '%m/%d/%Y', '%d/%m/%Y'],
    )

    def __init__(self, *args, allow_admin_role=False, **kwargs):
        self.allow_admin_role = allow_admin_role
        super().__init__(*args, **kwargs)
        roles = [(UserRole.Role.SHIPPER, 'Shipper'), (UserRole.Role.TRANSPORTER, 'Transporter')]
        if allow_admin_role:
            roles.append((UserRole.Role.ADMIN, 'Admin'))
        self.fields['role'].choices = roles

    def clean_email(self):
        email = self.cleaned_data['email'].strip().lower()
        if User.objects.filter(username=email).exists():
            raise ValidationError('A user with this email already exists.')
        return email

    def clean(self):
        data = super().clean()
        if not data:
            return data
        role = data.get('role')
        at = data.get('account_type')
        shipper_ok = {ShipperProfile.AccountType.INDIVIDUAL, ShipperProfile.AccountType.BUSINESS}
        transporter_ok = {TransporterProfile.AccountType.DRIVER, TransporterProfile.AccountType.FLEET_OWNER}
        if role == UserRole.Role.ADMIN:
            return data
        at = (at or '').strip()
        if not at:
            self.add_error('account_type', 'Select an account type.')
            return data
        if role == UserRole.Role.SHIPPER and at not in shipper_ok:
            self.add_error('account_type', 'For shipper, choose Individual or Business.')
        if role == UserRole.Role.TRANSPORTER and at not in transporter_ok:
            self.add_error('account_type', 'For transporter, choose Driver or Fleet owner.')
        if role == UserRole.Role.SHIPPER:
            national_id = (data.get('national_id_number') or '').strip()
            passport_number = (data.get('passport_number') or '').strip()
            if not national_id and not passport_number:
                self.add_error(
                    'national_id_number',
                    'Provide national ID or passport. At least one is required.',
                )
            if data.get('passport_expiry_date') and not passport_number:
                self.add_error('passport_number', 'Passport number is required when passport expiry date is provided.')
            data['national_id_number'] = national_id
            data['passport_number'] = passport_number.upper() if passport_number else ''
        return data


class AdminUserEditForm(forms.Form):
    email = forms.EmailField(required=False)
    password = forms.CharField(required=False, widget=forms.PasswordInput, min_length=8)
    first_name = forms.CharField(required=False, strip=True)
    last_name = forms.CharField(required=False, strip=True)
    is_active = forms.BooleanField(required=False)
    role = forms.ChoiceField(choices=UserRole.Role.choices)
    phone = forms.CharField(required=False, strip=True)
    kyc_verified = forms.BooleanField(required=False)
    credit_approved = forms.BooleanField(required=False)
    documents_verified = forms.BooleanField(required=False)

    @classmethod
    def for_user(cls, user):
        role = None
        phone = ''
        try:
            role = user.role.role
            phone = user.role.phone or ''
        except UserRole.DoesNotExist:
            role = UserRole.Role.SHIPPER

        initial = {
            'email': user.email or '',
            'password': '',
            'first_name': user.first_name or '',
            'last_name': user.last_name or '',
            'is_active': user.is_active,
            'role': role,
            'phone': phone,
            'kyc_verified': False,
            'credit_approved': False,
            'documents_verified': False,
        }
        try:
            sp = user.shipper_profile
            initial['kyc_verified'] = sp.kyc_verified
            initial['credit_approved'] = sp.credit_approved
        except ShipperProfile.DoesNotExist:
            pass
        try:
            initial['documents_verified'] = user.transporter_profile.documents_verified
        except TransporterProfile.DoesNotExist:
            pass
        return cls(initial=initial)


class VehicleDocumentReviewWebForm(forms.Form):
    review_status = forms.ChoiceField(
        choices=[
            (VehicleDocument.ReviewStatus.APPROVED, 'Approved'),
            (VehicleDocument.ReviewStatus.REJECTED, 'Rejected'),
        ],
    )
    review_notes = forms.CharField(required=False, widget=forms.Textarea(attrs={'rows': 3}), strip=True)
    expiry_date = forms.DateField(required=False, input_formats=['%Y-%m-%d', '%m/%d/%Y', '%d/%m/%Y'])

    def clean_expiry_date(self):
        value = self.cleaned_data.get('expiry_date')
        return value


class KYCDocumentReviewWebForm(forms.Form):
    review_status = forms.ChoiceField(
        choices=[
            (KYCDocument.ReviewStatus.APPROVED, 'Approved'),
            (KYCDocument.ReviewStatus.REJECTED, 'Rejected'),
        ],
    )
    review_notes = forms.CharField(required=False, widget=forms.Textarea(attrs={'rows': 3}), strip=True)

    def clean(self):
        cleaned = super().clean()
        status = cleaned.get('review_status')
        notes = (cleaned.get('review_notes') or '').strip()
        if status == KYCDocument.ReviewStatus.REJECTED and not notes:
            self.add_error('review_notes', 'Rejection reason is required.')
        cleaned['review_notes'] = notes
        return cleaned


class VehicleVerifyWebForm(forms.Form):
    is_verified = forms.ChoiceField(
        choices=[('true', 'Verified'), ('false', 'Not verified')],
        widget=forms.RadioSelect,
    )
    is_active = forms.ChoiceField(
        choices=[('true', 'Active'), ('false', 'Inactive')],
        widget=forms.RadioSelect,
    )


class TripStatusOverrideWebForm(forms.Form):
    new_status = forms.ChoiceField(choices=Trip.Status.choices)
    justification = forms.CharField(
        min_length=5,
        widget=forms.Textarea(attrs={'rows': 4}),
        strip=True,
        label='Justification (required for audit)',
    )


class PlatformSettingsForm(forms.ModelForm):
    class Meta:
        from accounts.models import PlatformSettings

        model = PlatformSettings
        fields = [
            'bidding_rate_distribution_count',
        ]
        widgets = {
            'bidding_rate_distribution_count': forms.NumberInput(
                attrs={
                    'class': 'settings-input text-lg font-bold text-gray-800 text-center w-36',
                    'min': 1,
                    'placeholder': '1',
                }
            ),
        }

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.help_texts = {}
        for name, field in self.fields.items():
            self.help_texts[name] = field.help_text or ''
            field.help_text = ''

    def clean_bidding_rate_distribution_count(self):
        val = self.cleaned_data.get('bidding_rate_distribution_count')
        if val is None or val < 1:
            raise ValidationError('Bidding rate distribution count must be at least 1.')
        return val
