"""Email notifications for job-related events."""
import os

from django.conf import settings
from django.core.mail import EmailMessage, send_mail
from django.urls import reverse

SIGNATURE = '-- PEZAJOB'


def _absolute_url(path):
    return f'{settings.SITE_URL.rstrip("/")}{path}'


def _ascii_safe(text):
    """Avoid encoding issues in plain-text emails on legacy Windows consoles."""
    return (
        text.replace('\u2013', '-')
        .replace('\u2014', '-')
        .replace('\u2026', '...')
    )


def notify_seeker_job_alert(user, profile, job, match_score):
    """Send a priority job alert to a paid subscriber. Returns True if sent."""
    from accounts import events

    events.job_alert(user, job, match_score)
    if not user.email:
        return False

    job_url = _absolute_url(job.get_absolute_url())
    name = profile.full_name or user.get_short_name() or user.email
    summary = (job.summary or job.description or '')[:280].strip()
    if len((job.summary or job.description or '')) > 280:
        summary = f'{summary}...'

    body_lines = [
        f'Hi {name},',
        '',
        'A new job matching your profile was just posted on PEZAJOB:',
        '',
        f'{job.title} at {job.company_name}',
        f'Location: {job.location}',
        f'Salary: {_ascii_safe(job.salary_display)}',
        f'Match score: {match_score}%',
    ]
    if summary:
        body_lines.extend(['', summary])
    body_lines.extend([
        '',
        f'View and apply: {job_url}',
        '',
        'You receive these priority alerts as a Professional Plus member (K20/month).',
        'Manage your profile: ' + _absolute_url(reverse('seekers:dashboard')),
        '',
        SIGNATURE,
    ])

    send_mail(
        subject=f'Job alert: {job.title} at {job.company_name} ({match_score}% match)',
        message='\n'.join(body_lines),
        from_email=settings.DEFAULT_FROM_EMAIL,
        recipient_list=[user.email],
        fail_silently=True,
    )
    return True


def notify_employer_new_application(application):
    from accounts import events

    events.new_application_received(application)
    events.application_submitted(application)
    job = application.job
    employer = job.posted_by
    if not employer or not employer.email:
        return

    applicant_name = application.applicant.get_full_name() or application.applicant.email

    send_mail(
        subject=f'New application: {job.title}',
        message=(
            f'Hi {employer.get_short_name() or employer.email},\n\n'
            f'{applicant_name} applied for "{job.title}".\n\n'
            f'Review applications: {_absolute_url(reverse("ats:pipeline"))}\n\n'
            f'{SIGNATURE}'
        ),
        from_email=settings.DEFAULT_FROM_EMAIL,
        recipient_list=[employer.email],
        fail_silently=True,
    )


def _send_application_email(job, company, applicant_name, applicant_email, cover_letter, linkedin_url, cv_attachment=None):
    recipient = (company.email if company and company.email else '') or (
        job.posted_by.email if job.posted_by else ''
    )
    if not recipient:
        return

    body_lines = [
        f'Hi {job.company_name},',
        '',
        f'{applicant_name} applied for "{job.title}" on PEZAJOB.',
        f'Applicant email: {applicant_email}',
    ]
    if linkedin_url:
        body_lines.append(f'LinkedIn: {linkedin_url}')
    body_lines.extend([
        '',
        'Cover letter:',
        cover_letter or '(No cover letter provided)',
        '',
        SIGNATURE,
    ])

    email = EmailMessage(
        subject=f'New application: {job.title} ({applicant_name})',
        body='\n'.join(body_lines),
        from_email=settings.DEFAULT_FROM_EMAIL,
        to=[recipient],
        reply_to=[applicant_email] if applicant_email else None,
    )
    if cv_attachment:
        filename, content = cv_attachment
        email.attach(filename, content)
    email.send(fail_silently=True)


def notify_employer_application_by_email(application, company):
    """Deliver a full application (cover letter + CV) to the employer's own
    email, for employers who aren't on an ATS plan or who chose to receive
    applications by email instead of through PEZAJOB."""
    job = application.job
    applicant = application.applicant
    applicant_name = applicant.get_full_name() or applicant.email

    cv_attachment = None
    if application.cv_file:
        try:
            application.cv_file.open('rb')
            cv_attachment = (os.path.basename(application.cv_file.name), application.cv_file.read())
        finally:
            application.cv_file.close()

    _send_application_email(
        job, company, applicant_name, applicant.email,
        application.cover_letter, application.linkedin_url, cv_attachment,
    )


def notify_employer_guest_application(job, company, data):
    """Deliver a no-account (guest) application straight to the employer's
    email. Only used when the employer receives applications by email."""
    applicant_name = data.get('full_name') or data.get('email')
    applicant_email = data.get('email', '')
    cv_file = data.get('cv_file')
    cv_attachment = (cv_file.name, cv_file.read()) if cv_file else None

    _send_application_email(
        job, company, applicant_name, applicant_email,
        data.get('cover_letter', ''), data.get('linkedin_url', ''), cv_attachment,
    )


def notify_seeker_application_status_change(application):
    seeker = application.applicant

    from accounts import events
    from jobs.models import JobApplication as JobApplicationModel
    from subscriptions.access import user_has_seeker_plus

    if application.status == JobApplicationModel.Status.SHORTLISTED and not user_has_seeker_plus(seeker):
        return
    events.application_status_changed(application)
    if not seeker.email:
        return

    job = application.job
    dashboard_url = _absolute_url(reverse('seekers:applications'))

    send_mail(
        subject=f'Application update: {job.title}',
        message=(
            f'Hi {seeker.get_short_name() or seeker.email},\n\n'
            f'Your application for "{job.title}" at {job.company_name} '
            f'is now: {application.get_status_display()}.\n\n'
            f'View your applications: {dashboard_url}\n\n'
            f'{SIGNATURE}'
        ),
        from_email=settings.DEFAULT_FROM_EMAIL,
        recipient_list=[seeker.email],
        fail_silently=True,
    )


def notify_seeker_interview_scheduled(interview):
    from accounts import events

    events.interview_scheduled(interview)
    application = interview.application
    seeker = application.applicant
    if not seeker.email:
        return

    job = application.job
    when = interview.scheduled_at.strftime('%d %b %Y at %H:%M')
    location = interview.location or interview.meeting_url or 'See your applications page for details'

    send_mail(
        subject=f'Interview scheduled: {job.title}',
        message=(
            f'Hi {seeker.get_short_name() or seeker.email},\n\n'
            f'You have an interview for "{job.title}" at {job.company_name}.\n'
            f'When: {when}\n'
            f'Where: {location}\n\n'
            f'View details: {_absolute_url(reverse("seekers:applications"))}\n\n'
            f'{SIGNATURE}'
        ),
        from_email=settings.DEFAULT_FROM_EMAIL,
        recipient_list=[seeker.email],
        fail_silently=True,
    )
