"""IMM5532 real-template binding, hostile payloads and incremental preservation."""
import hashlib
import json
import os
import subprocess
import sys
from pathlib import Path
import tempfile
import unittest
import pikepdf
from lxml import etree as E

BASE = Path(__file__).resolve().parents[2]


class Imm5532Tests(unittest.TestCase):
    def test_download_subprocess_without_windows_systemroot(self):
        if os.name != 'nt':
            return
        env = {key:value for key,value in os.environ.items() if key.lower() != 'systemroot'}
        with tempfile.TemporaryDirectory() as tmp:
            payload = Path(tmp)/'payload.json'
            payload.write_text(json.dumps({'form':'IMM5532','language':'en','fields':{}}),encoding='utf-8')
            output = Path(tmp)/'draft.pdf'
            result = subprocess.run([sys.executable,str(Path(__file__).with_name('prefill_imm_xfa_pdf.py')),str(payload),str(output),str(BASE/'storage/app/imm/imm5532e.pdf')],env=env,capture_output=True,text=True,timeout=60)
            self.assertEqual(0,result.returncode,result.stderr)
            self.assertTrue(output.read_bytes().startswith(b'%PDF-'))

    def test_all_targets_roundtrip_and_preserve_signed_packets(self):
        from imm5532_pdf import fill_relationship, resolve
        for lang, suffix in [('en', 'e'), ('fr', 'f')]:
            c = json.loads(Path(__file__).with_name(f'imm5532-contract.{lang}.json').read_text(encoding='utf-8'))
            fields = {}
            for key, meta in c['fields'].items():
                fields[key] = next(iter(meta['choices'].values())) if meta['choices'] else '2000-01-01' if meta['value_type'] == 'date' else '1' if meta['value_type'] in ['integer','decimal','float'] or meta['max_chars'] < 6 else 'Élodie'
            blank = BASE / f'storage/app/imm/imm5532{suffix}.pdf'
            with tempfile.TemporaryDirectory() as tmp:
                out = Path(tmp)/'draft.pdf'
                fill_relationship({'form':'IMM5532','language':lang,'fields':fields},out,blank)
                self.assertTrue(out.read_bytes().startswith(blank.read_bytes()))
                with pikepdf.open(blank) as original, pikepdf.open(out) as draft:
                    def packets(pdf):
                        x=pdf.Root.AcroForm.XFA
                        return {str(x[i]):x[i+1].read_bytes() for i in range(0,len(x),2)}
                    before, after = packets(original), packets(draft)
                    for name in before:
                        if name not in ['datasets','form']:
                            self.assertEqual(before[name], after[name], name)
                    self.assertEqual(str(original.Root.Perms),str(draft.Root.Perms))
                    data=E.fromstring(after['datasets'])
                    for key,value in fields.items(): self.assertEqual(value,resolve(data,key).text,key)
                    for key in c['manual']: self.assertFalse(resolve(data,key).text,key)
                    from imm0008_xfa_checksum import form_checksum
                    self.assertEqual(form_checksum(after['template'],after['datasets']),E.fromstring(after['form']).get('checksum'))
                    self.assertFalse(E.fromstring(after['form']).xpath('//*[local-name()="exclGroup"]/*[local-name()="value"]'))

    def test_empty_fields_and_malformed_payloads(self):
        from imm5532_pdf import fill_relationship
        blank=BASE/'storage/app/imm/imm5532e.pdf'
        digest=hashlib.sha256(blank.read_bytes()).hexdigest()
        with tempfile.TemporaryDirectory() as tmp:
            for i,fields in enumerate([{},[]]):
                fill_relationship({'form':'IMM5532','fields':fields},Path(tmp)/f'{i}.pdf',blank)
            for fields in [None,'text',[{'bad':'value'}],{'unknown':'value'},{'IMM_5532.page1.yesNo[0]':'invalid'},{'IMM_5532.page1.familyNameSponsor':{}},{'IMM_5532.page1.familyNameSponsor':'x'*2001},{'IMM_5532.page1.Table1[0].Row2.Cell6[1]':'6500 CAD'},{'IMM_5532.page1.Table1[0].Row2.Cell6[1]':'NaN'}]:
                with self.assertRaises(ValueError):fill_relationship({'form':'IMM5532','fields':fields},Path(tmp)/'bad.pdf',blank)
            with self.assertRaises(ValueError):fill_relationship({'form':'IMM5532','fields':{}},blank,blank)
            with self.assertRaises(ValueError):fill_relationship({'form':'IMM5532','language':'xx','fields':{}},Path(tmp)/'bad.pdf',blank)
        self.assertEqual(digest,hashlib.sha256(blank.read_bytes()).hexdigest())


if __name__=='__main__': unittest.main()
