import json

from directory_validators import enrolment as shared_validators
from directory_validators.constants import choices

from django import forms
from django.conf import settings
from django.utils.safestring import mark_safe

from enrolment import helpers, validators


class IndentedInvalidFieldsMixin:
    error_css_class = 'input-field-container has-error'


class CompanyForm(IndentedInvalidFieldsMixin, forms.Form):
    company_number = forms.CharField(
        label='Company number:',
        help_text=mark_safe(
            'This is the company number on your certificate of '
            'incorporation. Find your company number from '
            '<a href="{url}" target="_blank">Companies House'
            '</a>.'.format(url=settings.COMPANIES_HOUSE_SEARCH_URL)
        ),
        validators=helpers.halt_validation_on_failure(
            shared_validators.company_number,
            validators.company_number,
        )
    )


class CompanyNameForm(IndentedInvalidFieldsMixin, forms.Form):
    company_name = forms.CharField(
        label='Company Name:',
        help_text=(
            "If this is not your company then click back in your browser "
            "and re-enter your company's number."
        ),
        widget=forms.TextInput(attrs={'readonly': 'readonly'}),
    )


class CompanyExportStatusForm(IndentedInvalidFieldsMixin, forms.Form):
    export_status = forms.ChoiceField(
        label=(
            'Has your company sold products or services to overseas customers?'
        ),
        choices=choices.EXPORT_STATUSES,
        validators=[shared_validators.export_status_intention]
    )


class CompanyBasicInfoForm(IndentedInvalidFieldsMixin, forms.Form):
    company_name = forms.CharField(
        help_text=(
            'You can change this from the Companies House listing to '
            'better fit your profile.'
        ),
        max_length=255,
    )
    website = forms.URLField(max_length=255)
    keywords = forms.CharField(
        label='Enter up to 10 keywords that describe your company:',
        help_text=(
            'Keywords should be separated with commas. These keywords will be '
            'used to help potential overseas buyers find your company.'
        ),
        widget=forms.Textarea,
        max_length=1000,
    )


class CompanyDescriptionForm(IndentedInvalidFieldsMixin, forms.Form):
    description = forms.CharField(
        widget=forms.Textarea,
        label='Describe your business to overseas buyers:',
        help_text='Maximum 1,000 characters.',
        max_length=1000,
    )


class CompanyLogoForm(IndentedInvalidFieldsMixin, forms.Form):
    logo = forms.FileField(
        help_text=(
            'For best results this should be a transparent PNG file of 600 x '
            '600 pixels and more than {0}MB'.format(
                int(settings.VALIDATOR_MAX_LOGO_SIZE_BYTES / 1024 / 1014)
            )
        ),
        required=False,
        validators=[shared_validators.logo_filesize]
    )


class CompanyEmailAddressForm(IndentedInvalidFieldsMixin, forms.Form):
    company_email = forms.EmailField(
        label='Email address:',
        help_text=(
            'Please enter a company email address rather than a personal '
            'email address.'
        ),
        validators=[
            shared_validators.email_domain_free,
            shared_validators.email_domain_disposable,
        ]
    )
    email_confirmed = forms.EmailField(
        label='Please confirm your email address:',
    )

    def clean_email_confirmed(self):
        email = self.cleaned_data.get('company_email')
        confirmed = self.cleaned_data.get('email_confirmed')
        if (email and confirmed and email != confirmed):
            raise forms.ValidationError('Your emails do not match')
        return confirmed


class UserForm(IndentedInvalidFieldsMixin, forms.Form):
    mobile_number = forms.CharField(
        label='Your mobile phone number:',
        help_text=(
            'We will send a verification code to this mobile phone number.'
        )
    )
    mobile_confirmed = forms.CharField(
        label='Please confirm your mobile phone number:'
    )
    terms_agreed = forms.BooleanField(
        label=mark_safe(
            'Tick this box to accept the '
            '<a href="/terms_and_conditions" target="_blank">terms and '
            'conditions</a> of the Find a Buyer service.'
        )
    )
    referrer = forms.CharField(required=False, widget=forms.HiddenInput())

    def clean_mobile_confirmed(self):
        mobile = self.cleaned_data.get('mobile_number')
        confirmed = self.cleaned_data.get('mobile_confirmed')
        if (mobile and confirmed and mobile != confirmed):
            raise forms.ValidationError('Your numbers do not match')
        return confirmed


class CompanySizeForm(IndentedInvalidFieldsMixin, forms.Form):
    employees = forms.ChoiceField(
        choices=choices.EMPLOYEES,
        label='How many employees are in your company?',
        help_text=(
            'Customers may use this to judge how capable you are of '
            'fulfilling orders.'
        )
    )


class CompanyClassificationForm(IndentedInvalidFieldsMixin, forms.Form):
    sectors = forms.MultipleChoiceField(
        label='What sectors is your company interested in working in?',
        choices=choices.COMPANY_CLASSIFICATIONS,
        widget=forms.CheckboxSelectMultiple()
    )


class PhoneNumberVerificationForm(IndentedInvalidFieldsMixin, forms.Form):

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

    sms_code = forms.CharField(
        label='Enter the verification code from the text message we sent you:',
        help_text=mark_safe(
            'We sent you a text message containing a six digit code. '
            'Continue creating your Find a Buyer profile by entering '
            'this code. <a href="#" target="_self">Create a new code</a> if '
            'you do not receive the text message in 10 minutes.'
        ),
    )

    def clean_sms_code(self):
        sms_code = self.cleaned_data['sms_code']
        if sms_code != self.expected_sms_code:
            raise forms.ValidationError('Incorrect code.')
        return sms_code


def serialize_enrolment_forms(cleaned_data):
    """
    Return the shape directory-api-client expects for enrolment.

    @param {dict} cleaned_data - All the fields in `CompanyForm`, `UserForm`,
                                 `CorporateEmailAddressForm`,
                                 `CompanyNameForm`, and
                                 `CompanyExportStatusForm`
    @returns dict

    """

    return {
        'company_email': cleaned_data['company_email'],
        'company_name': cleaned_data['company_name'],
        'company_number': cleaned_data['company_number'],
        'mobile_number': cleaned_data['mobile_number'],
        'referrer': cleaned_data['referrer'],
        'export_status': cleaned_data['export_status'],
    }


def serialize_company_profile_forms(cleaned_data):
    """
    Return the shape directory-api-client expects for company profile edit.

    @param {dict} cleaned_data - All the fields in `CompanyBasicInfoForm`
                                 `CompanySizeForm`, `CompanyLogoForm`, and
                                 `CompanyClassificationForm`
    @returns dict

    """

    return {
        'name': cleaned_data['company_name'],
        'website': cleaned_data['website'],
        'keywords': cleaned_data['keywords'],
        'employees': cleaned_data['employees'],
        'sectors': json.dumps(cleaned_data['sectors']),
    }


def serialize_company_logo_forms(cleaned_data):
    """
    Return the shape directory-api-client expects for changing logo.

    @param {dict} cleaned_data - All the fields in `CompanyLogoForm`

    @returns dict

    """

    return {
        'logo': cleaned_data['logo'],
    }


def serialize_company_description_forms(cleaned_data):
    """
    Return the shape directory-api-client expects for changing description.

    @param {dict} cleaned_data - All the fields in `CompanyDescriptionForm`

    @returns dict

    """

    return {
        'description': cleaned_data['description'],
    }

@@ -5044,94 +5044,93 @@
    '
-Customers may use this to judge how capable you are of '%0A            'fulfilling order
+Tell international buyers more about your business for tailored '%0A            'result
 s.'%0A

Update help text for company size form