"""Turn plain-text job ads (pasted from Word/WhatsApp/PDF) into clean, structured, safe HTML."""
import re

from django.template.defaultfilters import urlize
from django.utils.html import escape
from django.utils.safestring import mark_safe

_BULLET = re.compile(r'^\s*(?:[-*•●▪‣◦⁃·–—>]|\d{1,2}[.)]|[a-z][.)])\s+(.*\S)\s*$')
_NUMBERED = re.compile(r'^\s*(\d{1,2})[.)]\s+(.*\S)\s*$')
_HEADING_HINT = re.compile(
    r'^(?:key\s+)?(?:responsibilit\w*|duties|requirements?|qualifications?|skills?|experience|benefits?|about\b.*|'
    r'how\s+to\s+apply|application\w*|deadline|salary|remuneration|position\w*|full[\s-]?time.*|part[\s-]?time.*|'
    r'internship.*|job\s+(?:summary|description|purpose)|purpose|overview|note|notes|attachments?|documents?)\b.*$', re.I)


def _clean(line):
    return line.replace('\xa0', ' ').replace('�', '-').strip()


def _is_heading(line):
    text = line.strip()
    if not text or len(text) > 90 or _BULLET.match(text):
        return False
    if text.endswith(':') and len(text.split()) <= 10:
        return True
    letters = [c for c in text if c.isalpha()]
    if len(letters) >= 4 and text.upper() == text and len(text.split()) <= 12 and not text.endswith(('.', ',')):
        return True
    return bool(_HEADING_HINT.match(text.rstrip(':'))) and len(text.split()) <= 8 and not text.endswith('.')


def _inline(text):
    html = urlize(escape(text), autoescape=False)
    return mark_safe(re.sub(r'<a ', '<a target="_blank" rel="noopener noreferrer" ', str(html)))


def format_job_text(value):
    """Return (html, headings) where headings is a list of (anchor_id, title) for long multi-part ads."""
    if not value:
        return '', []
    lines = [_clean(l) for l in str(value).replace('\r\n', '\n').replace('\r', '\n').split('\n')]
    out, headings = [], []
    list_kind, list_items = None, []
    para = []

    def flush_list():
        nonlocal list_kind, list_items
        if list_items:
            tag = 'ol' if list_kind == 'ol' else 'ul'
            out.append('<%s class="jd-list">%s</%s>' % (tag, ''.join('<li>%s</li>' % _inline(i) for i in list_items), tag))
        list_kind, list_items = None, []

    def flush_para():
        nonlocal para
        if para:
            out.append('<p>%s</p>' % _inline(' '.join(para)))
        para = []

    for line in lines:
        if not line:
            flush_para()
            flush_list()
            continue
        m = _BULLET.match(line)
        if m and not _HEADING_HINT.match(line.rstrip(':')):
            flush_para()
            kind = 'ol' if _NUMBERED.match(line) else 'ul'
            if list_kind and list_kind != kind:
                flush_list()
            list_kind = kind
            list_items.append(m.group(1))
            continue
        if _is_heading(line):
            flush_para()
            flush_list()
            title = line.rstrip(':').strip()
            anchor = 'jd-%d' % (len(headings) + 1)
            headings.append((anchor, title.title() if title.isupper() else title))
            out.append('<h4 class="jd-heading" id="%s">%s</h4>' % (anchor, escape(title.title() if title.isupper() else title)))
            continue
        flush_list()
        para.append(line)
        if len(' '.join(para)) > 420 or line.endswith(('.', '!', '?')) and len(para) >= 3:
            flush_para()
    flush_para()
    flush_list()
    return mark_safe(''.join(out)), headings
