# -*- coding: utf-8 -*-
"""Extrait et met en forme le texte intégral des formulaires (projet, partenaires, motivations).
Blocs : {"t": "p"|"li"|"h", "x": texte}"""
import json, re, sys, pathlib
import pymupdf
from pypdf import PdfReader

SRC = pathlib.Path('/mnt/user-data/uploads/CANDIDATURES')
FORMS = {
 "bm-conseil": "CREATION/BM CONSEIL/BM CONSEIL.pdf",
 "mobisafe": "CREATION/MOBISAFE by CARPE DIEM/MOBISAFE by CARPE DIEM.pdf",
 "handiref": "CREATION/HANDIREF/HANDIREF.pdf",
 "mosaique-nantes": "FORMATION ET SENSIBILISATION/ASSOCIATION MOSAÏQUE NANTES/ASSOCIATION MOSAÏQUE NANTES.pdf",
 "emma-barme": "FORMATION ET SENSIBILISATION/EMMA BARME/EMMA BARME.pdf",
 "enedis-formation": "FORMATION ET SENSIBILISATION/ENEDIS/ENEDIS.pdf",
 "hamadryade": "FORMATION ET SENSIBILISATION/HAMADRYADE, Danser l'indicible/HAMADRYADE, Danser l'indicible.pdf",
 "living-museum": "FORMATION ET SENSIBILISATION/LIVING MUSEUM/LIVING MUSEUM.pdf",
 "tzcld": "FORMATION ET SENSIBILISATION/TZCLD/TZCLD.pdf",
 "enedis-partenariat": "PARTENARIAT/ENEDIS/ENEDIS.pdf",
 "petitbag": "PARTENARIAT/PETITBAG.COM - ESAT DE REZÉ/PETITBAG.COM - ESAT DE REZÉ.pdf",
 "soofut": "PARTENARIAT/SOOFUT/Soofût.pdf",
 "groupe-sf": "RECRUTEMENT/GROUPE SF/GROUPE SF.pdf",
 "primark-angers": "RECRUTEMENT/PRIMARK ANGERS/PRIMARK ANGERS.pdf",
}
LIG = {'\u08a2': 'ti', '\u08a1': 'ti', '\x82': 'tt', 'ﬁ': 'fi', 'ﬀ': 'ff', 'ﬃ': 'ffi', 'ﬂ': 'fl', 'ﬄ': 'ffl', '\r': '\n', '\u00ad': ''}
def lig(s):
    for a, b in LIG.items(): s = s.replace(a, b)
    return s

PUCE = re.compile(r'^\s*(?:[-–•·▪●]|\.\s|\d+\s?[/).]\s?)\s*')
FIN = tuple('.:!?»…;)"')

def typo(s):
    s = re.sub(r'[ \t]+', ' ', s).strip()
    s = s.replace("'", "’")
    s = re.sub(r'\s+([:;!?»])', '\u00a0\\1', s)          # espace insécable avant ponctuation haute
    s = re.sub(r'([«])\s*', '\\1\u00a0', s)
    s = re.sub(r'\s+,', ',', s)
    s = re.sub(r'\s+\.(?!\.)', '.', s)
    return s

def blocs_depuis_lignes(lignes, recoller):
    """lignes -> blocs. recoller=True : texte mis en page (PDF), on recolle les retours à la ligne."""
    paras = []; derniere = ''
    for l in lignes:
        l = l.rstrip()
        if not l.strip():
            paras.append(None); derniere = ''; continue
        if recoller and paras and paras[-1] is not None and not PUCE.match(l):
            prev = paras[-1]
            minus = re.match(r'^\s*[a-zàâçéèêëîïôûùüÿœ(0-9]', l)
            # suite du paragraphe : la ligne précédente était pleine et sans ponctuation finale, ou la ligne commence en minuscule
            if minus or (not prev.rstrip().endswith(FIN) and len(derniere.strip()) >= 85):
                paras[-1] = prev.rstrip() + ' ' + l.strip(); derniere = l; continue
        paras.append(l.strip()); derniere = l
    out = []
    paras = [p for p in paras if p]
    for i, p in enumerate(paras):
        if PUCE.match(p) and len(PUCE.sub('', p)) > 2:
            out.append({"t": "li", "x": typo(PUCE.sub('', p))})
        elif (len(p) < 92 and not p.endswith(FIN) and i + 1 < len(paras) and len(paras[i + 1]) > len(p)
              and not p.endswith(',')):
            out.append({"t": "h", "x": typo(p)})
        else:
            out.append({"t": "p", "x": typo(p)})
    return out

def depuis_champs(path):
    try: f = PdfReader(str(path)).get_fields() or {}
    except Exception: return None
    v = {k: lig(str(x.get('/V'))) for k, x in f.items() if x.get('/V')}
    if not all(len(v.get(k, '').strip()) > 20 for k in ('Texte10', 'Texte11', 'Texte12')): return None
    return {s: blocs_depuis_lignes(v[k].split('\n'), recoller=False)
            for s, k in (("projet", "Texte10"), ("partenaires", "Texte11"), ("motivations", "Texte12"))}

Q = [("projet", r"Présentez-nous de façon synthétique le projet que vous avez mené\s*:?"),
     ("partenaires", r"Quels sont les partenaires de votre projet\s*\?"),
     ("motivations", r"Quelles sont les motivations qui vous ont poussé à candidater\s*\??")]
BRUIT = re.compile(r'^\s*(DOSSIER DE|CANDIDATURE|VOTRE PROJET|\d/\d|DOSSIER DE CANDIDATURE|DOSSIER DE CANDIDATURE · TROPHÉES.*|Votre projet · Motivations \(suite\)|HandiRef · Showroom.*Catégorie.*|Motivations \(suite\), détails.*)\s*$')

def depuis_texte(path, pages=None, coupe_fin=None, tri=True):
    d = pymupdf.open(str(path))
    t = lig('\n'.join(d[i].get_text(sort=tri) for i in (pages or range(len(d)))))
    if coupe_fin: t = t.split(coupe_fin)[0]
    pos = [(s, re.search(rx, t)) for s, rx in Q]
    res = {}
    for i, (s, m) in enumerate(pos):
        debut = m.end()
        fin = pos[i + 1][1].start() if i + 1 < len(pos) else len(t)
        bloc = [l for l in t[debut:fin].split('\n') if not BRUIT.match(l)]
        res[s] = blocs_depuis_lignes(bloc, recoller=True)
    return res

def corrige(fid, r):
    pr = r.get("projet") or []
    if pr and pr[0]["t"] == "p" and len(pr[0]["x"]) < 110 and len(pr) > 1:
        pr[0]["t"] = "h"
    for s, bl in r.items():
        for b in bl:
            if b["t"] == "h" and (b["x"].startswith(("http", "Vous pouvez suivre", "Préambule")) ):
                b["t"] = "p"
        r[s] = [b for b in bl if not (fid == "emma-barme" and b["x"] == "Life in Small")]
    if fid == "handiref":
        m = r["motivations"]
        i = next(k for k, b in enumerate(m) if b["x"].startswith("Parce que ce trophée"))
        part, mot = m[:i], m[i:]
        # recoller le fragment « 12). » au paragraphe précédent
        for k in range(len(part) - 1, 0, -1):
            if part[k]["x"].strip() in ("12).", "12)."):
                part[k - 1]["x"] = part[k - 1]["x"].rstrip() + " " + part[k]["x"].strip(); del part[k]
        for k, b in enumerate(mot):
            if b["x"].startswith("Parce que le projet a réuni tout un écosystème "):
                reste = b["x"][len("Parce que le projet a réuni tout un écosystème "):]
                mot[k:k + 1] = [{"t": "h", "x": "Parce que le projet a réuni tout un écosystème"}, {"t": "p", "x": reste}]
                break
        r["partenaires"], r["motivations"] = part, mot
        pr = r["projet"]
        m0 = re.match(r"^(Showroom «.*?»)\s+(.*)$", pr[0]["x"])
        if m0:
            pr[0:1] = [{"t": "h", "x": m0.group(1)}, {"t": "p", "x": m0.group(2)}]
    if fid == "mobisafe":
        pa = r["partenaires"]
        i = next(k for k, b in enumerate(pa) if b["x"].startswith("Parmi les acteurs"))
        j = next(k for k, b in enumerate(pa) if b["x"].startswith("Cette approche partenariale"))
        for b in pa[i + 1:j]: b["t"] = "li"
    return r

texte = {}
H = lambda s: {"t": "p", "x": typo(s)}
texte["hakoona-matata"] = {
 "projet": [
  H("Lorsqu'en 2020 j'ai ouvert la crèche, c'était une évidence qu'elle soit inclusive. C'est déjà une obligation, mais je le souhaitais pour les personnes sourdes. Formée, j'ai dès les recrutements ouvert les postes aux personnes signantes. Ainsi j'ai recruté « K. »."),
  H("Durant un an, nous avons travaillé ensemble pour son aménagement de poste. Puis les travaux ont pu se faire en partenariat avec l'AGEFIPH."),
  H("En parallèle, j'ai commencé à former ses collègues. Chaque année, l'une d'elles part une semaine par mois, pendant 6 mois, à l'école STEUM de Nantes. Nous travaillons avec un réseau d'interprètes (qui m'ont envoyé ce dossier) qui viennent pour les formations, les réunions d'équipe, les bilans, et dès que cela est nécessaire. Nous essayons d'avoir les mêmes personnes pour la discrétion, la facilité de compréhension pour K. et pour leur travail (retenir les lieux, les prénoms des enfants, les termes spécifiques à notre pédagogie)."),
  H("Cela fait maintenant 6 ans que K. travaille à la crèche. Ses collègues ont évolué, il en reste 2 à former. Nous participons à la Journée mondiale des Sourds, faisons de la sensibilisation auprès des familles (livret d'accueil, livres, affiches, vidéos mensuelles…). Nous avons participé à l'émission L'Œil et la Main cette année."),
  H("Nous souhaitons faire connaître notre projet pour valoriser le travail d'équipe fait au quotidien pour accueillir chacun dans son individualité, et valoriser ce super pouvoir de la culture sourde dès le plus jeune âge."),
 ],
 "partenaires": [
  H("Pour la crèche, nous travaillons avec la PMI, le Conseil départemental, avec la Fédération française des entreprises de crèches et les acteurs locaux : confrères, fournisseurs, etc."),
  H("Pour la partie inclusion / LSF, nous travaillons avec les interprètes, avec STEUM, certaines associations. Nous avons aussi la médecine du travail pour la RQTH et l'AGEFIPH."),
 ],
 "motivations": [
  H("C'est une de nos interprètes qui m'a envoyé ce lien, puis qui m'a motivée et relancée. Je n'avais pas le courage de le faire, car déjà postulé sur ce genre de mise en valeur des pratiques collectives de l'équipe et jamais retenue. Mais elle a réussi à me convaincre de prendre ce temps."),
  H("Ce qui m'a motivée, c'est qu'au final je ne le fais pas que pour la crèche, mais pour toutes les personnes qui soutiennent le projet, l'inclusion… Pour K. et pour ses collègues qui sont signantes, pour les interprètes, pour les familles qui apprennent et sensibilisent à leur tour… Bref, pour faire que nous soyons un petit sachet de thé qui, grâce à vous, va infuser et diffuser le plus largement cette possibilité de travailler ensemble dans la bienveillance et l'harmonie."),
 ],
}
for fid, rel in FORMS.items():
    p = SRC / rel
    r = depuis_champs(p)
    src = 'champs'
    if r is None:
        src = 'texte'
        if fid == 'handiref':
            r = depuis_texte(p, pages=range(0, 4), coupe_fin='Parce que HandiRef est une startup', tri=False)
        elif fid == 'groupe-sf':
            r = depuis_texte(p, coupe_fin='Nous vous proposons de joindre des fichiers')
        else:
            r = depuis_texte(p)
    texte[fid] = corrige(fid, r)
    print(f"{fid:20} {src:7} " + " ".join(f"{k}:{len(v)}" for k, v in r.items()))
json.dump(texte, open(pathlib.Path(__file__).parent / 'texte_complet.json', 'w'), ensure_ascii=False, indent=1)
