from django import forms
from django.urls import reverse

from .application_requirements import DOCUMENT_CHOICES
from .application_utils import seeker_has_profile_cv
from .models import Job, JobApplication

DOCUMENT_FIELD_MAP = {
    'cv': 'cv_file',
    'cover_letter': 'cover_letter',
    'portfolio': 'portfolio_file',
    'qualifications': 'qualification_file',
    'other': 'other_document',
}

DOCUMENT_LABELS = dict(DOCUMENT_CHOICES)


class JobFilterForm(forms.Form):
    q = forms.CharField(
        required=False,
        label='Search',
        widget=forms.TextInput(attrs={'placeholder': 'Job title, skill, keyword or company...'}),
    )
    company = forms.CharField(
        required=False,
        widget=forms.TextInput(attrs={'placeholder': 'Company name...'}),
    )
    location = forms.CharField(
        required=False,
        widget=forms.TextInput(attrs={'placeholder': 'Location...'}),
    )
    category = forms.ChoiceField(
        required=False,
        label='Job Category',
        choices=[('', 'Any category')],
    )
    industry = forms.ChoiceField(
        required=False,
        label='Industry',
        choices=[('', 'Any industry')],
    )
    job_type = forms.MultipleChoiceField(
        required=False,
        choices=Job.JobType.choices,
        widget=forms.CheckboxSelectMultiple,
    )
    experience = forms.MultipleChoiceField(
        required=False,
        choices=Job.ExperienceLevel.choices,
        widget=forms.CheckboxSelectMultiple,
    )
    sort = forms.ChoiceField(
        required=False,
        choices=[
            ('relevant', 'Most Relevant'),
            ('ongoing', 'Ongoing'),
            ('active', 'Active'),
            ('newest', 'Newest First'),
            ('salary_high', 'Salary: High to Low'),
            ('salary_low', 'Salary: Low to High'),
        ],
        initial='newest',
    )

    def __init__(self, *args, category_choices=None, industry_choices=None, **kwargs):
        super().__init__(*args, **kwargs)
        select_attrs = {'class': 'filter-select', 'onchange': 'this.form.submit()'}
        self.fields['category'].widget = forms.Select(attrs=select_attrs)
        self.fields['industry'].widget = forms.Select(attrs=select_attrs)
        if category_choices is not None:
            self.fields['category'].choices = [('', 'Any category')] + list(category_choices)
        if industry_choices is not None:
            self.fields['industry'].choices = [('', 'Any industry')] + list(industry_choices)


class JobApplicationForm(forms.ModelForm):
    linkedin_url = forms.URLField(
        required=False,
        label='LinkedIn Profile (optional)',
        widget=forms.URLInput(attrs={'placeholder': 'https://linkedin.com/in/yourprofile (optional)'}),
    )

    class Meta:
        model = JobApplication
        fields = [
            'cover_letter',
            'cv_file',
            'portfolio_file',
            'qualification_file',
            'other_document',
            'linkedin_url',
        ]
        widgets = {
            'cover_letter': forms.Textarea(
                attrs={
                    'rows': 4,
                    'placeholder': "Tell us why you're a great fit for this role...",
                }
            ),
            'cv_file': forms.FileInput(attrs={
                'accept': '.pdf,.doc,.docx,.txt,.rtf,.odt,.jpg,.jpeg,.png',
            }),
            'portfolio_file': forms.FileInput(attrs={
                'accept': '.pdf,.doc,.docx,.txt,.rtf,.odt,.zip',
            }),
            'qualification_file': forms.FileInput(attrs={
                'accept': '.pdf,.doc,.docx,.jpg,.jpeg,.png,.zip',
            }),
            'other_document': forms.FileInput(attrs={
                'accept': '.pdf,.doc,.docx,.txt,.rtf,.odt,.zip,.jpg,.jpeg,.png',
            }),
        }

    def __init__(self, *args, job=None, profile=None, **kwargs):
        super().__init__(*args, **kwargs)
        self.job = job
        self.profile = profile
        required_docs = job.application_documents_list() if job else ['cv']

        for doc_key, field_name in DOCUMENT_FIELD_MAP.items():
            if doc_key == 'cover_letter':
                if doc_key not in required_docs:
                    self.fields.pop('cover_letter', None)
                else:
                    self.fields['cover_letter'].required = True
                    self.fields['cover_letter'].label = 'Cover Letter'
                continue

            if field_name not in self.fields:
                continue
            if doc_key not in required_docs:
                self.fields.pop(field_name, None)
                continue

            field = self.fields[field_name]
            field.required = doc_key != 'cv'
            field.label = DOCUMENT_LABELS.get(doc_key, field.label)

            if doc_key == 'cv' and seeker_has_profile_cv(profile):
                field.required = False
                field.label = 'Replace CV (optional)'
                field.help_text = (
                    'Your profile CV will be attached automatically. Upload here only if you '
                    'want to use a different file.'
                )

        if job:
            for question in job.screening_questions_list():
                field_name = f'screening_{question["id"]}'
                self.fields[field_name] = forms.CharField(
                    label=question['text'],
                    required=question['required'],
                    widget=forms.Textarea(attrs={'rows': 2, 'placeholder': 'Your answer'}),
                )

    def screening_answers(self):
        answers = {}
        for name, value in self.cleaned_data.items():
            if name.startswith('screening_'):
                answers[name.replace('screening_', '', 1)] = value
        return answers


class GuestJobApplicationForm(forms.Form):
    """Application form for seekers without a PEZAJOB account, used only when
    the employer receives applications by email rather than through the ATS."""

    full_name = forms.CharField(
        max_length=150,
        widget=forms.TextInput(attrs={'placeholder': 'Your full name'}),
    )
    email = forms.EmailField(
        widget=forms.EmailInput(attrs={'placeholder': 'you@example.com'}),
    )
    cover_letter = forms.CharField(
        required=False,
        widget=forms.Textarea(
            attrs={
                'rows': 4,
                'placeholder': "Tell us why you're a great fit for this role...",
            }
        ),
    )
    cv_file = forms.FileField(
        required=False,
        widget=forms.FileInput(attrs={'accept': '.pdf,.doc,.docx,.txt,.rtf,.odt'}),
    )
    linkedin_url = forms.URLField(
        required=False,
        label='LinkedIn Profile (optional)',
        widget=forms.URLInput(attrs={'placeholder': 'https://linkedin.com/in/yourprofile (optional)'}),
    )


def validate_seeker_candidate_info(job, user, profile):
    """Return list of user-facing errors when required candidate info is missing."""
    errors = []
    settings_url = reverse('accounts:settings')
    for field_key in job.application_candidate_fields_list():
        if field_key == 'full_name':
            name = (user.get_full_name() or '').strip()
            if not name and not (profile and profile.full_name):
                errors.append(
                    f'Full name is required. Please update your profile in '
                    f'<a href="{settings_url}">Account Settings</a>.'
                )
        elif field_key == 'email':
            if not user.email:
                errors.append('Email address is required on your account.')
        elif field_key == 'phone':
            if not (user.phone or '').strip():
                errors.append(
                    f'Phone number is required. Please add it in '
                    f'<a href="{settings_url}">Account Settings</a>.'
                )
        elif field_key == 'profile':
            if not profile:
                errors.append(
                    f'A PezaJob professional profile is required. Please complete your '
                    f'<a href="{reverse("seekers:dashboard")}">seeker profile</a>.'
                )
            elif not profile.is_public:
                errors.append(
                    f'Your PezaJob profile must be public for this application. Enable it in '
                    f'<a href="{settings_url}">Account Settings</a>.'
                )
    return errors
