"""Targeted image insertion into saved appendix; no application/DB changes."""
from pathlib import Path
from datetime import datetime
from shutil import copy2
from hashlib import sha256
from zipfile import ZipFile
from copy import deepcopy
import json, re, sys
from PIL import Image, ImageDraw
from docx import Document
from docx.shared import Cm, Pt
from docx.enum.text import WD_ALIGN_PARAGRAPH

ROOT = Path(r'C:\Users\Asus\Desktop\TourAppProject\travelin_app\docs\thesis_appendices')
WORD = ROOT / 'TourApp_Appendix_A_B.docx'
STATE = ROOT / 'work/profile_dashboard_batch.json'
if sys.argv[1] == 'prepare':
    checkpoint = ROOT / 'checkpoints' / ('profile_dashboard_' + datetime.now().strftime('%Y%m%d_%H%M%S'))
    checkpoint.mkdir(parents=True, exist_ok=False)
    for name in (WORD.name, 'TourApp_Appendix_A_B_Review.pdf', 'appendix_progress.md', 'appendix_pending.md', 'appendix_image_index.md', 'appendix_capture_guide.md'):
        copy2(ROOT / name, checkpoint / ('before_' + name))
    source = ROOT / 'work/capture_inbox/tourist/tourist_profile.png'
    with Image.open(source) as src:
        im = src.convert('RGB')
    # Coordinates are normalized to the inspected 922 x 2048 display.
    boxes = [(130,345,242,424),(320,308,740,436),
             (190,803,700,868),(190,962,700,1018),
             (190,1115,750,1176),(190,1268,750,1338)]
    draw = ImageDraw.Draw(im)
    for x1,y1,x2,y2 in boxes:
        draw.rectangle((round(x1*im.width/922),round(y1*im.height/2048),round(x2*im.width/922),round(y2*im.height/2048)), fill='#626A78')
    out_profile = ROOT / 'screenshots/appendix_b/tourist/tourist_profile.png'
    assert not out_profile.exists(), 'Do not overwrite an existing image'
    im.save(out_profile)
    agency_source = ROOT / 'work/capture_inbox/agency/agency_dashboard.png'
    with Image.open(agency_source) as src:
        im = src.convert('RGB')
    draw = ImageDraw.Draw(im)
    for box in [(374,244,850,302),(896,428,1130,490),(1392,429,1775,490),
                (82,939,275,974),(45,952,67,977)]:
        draw.rectangle(box, fill='#626A78')
    # Exclude browser chrome/account-avatar and retain the actual portal content.
    im = im.crop((6,102,1916,1016))
    out_agency = ROOT / 'screenshots/appendix_b/agency/agency_dashboard.png'
    assert not out_agency.exists(), 'Do not overwrite an existing image'
    im.save(out_agency)
    state = {'checkpoint':str(checkpoint), 'sources':[str(source),str(agency_source)],
             'outputs':[str(out_profile),str(out_agency)],
             'before_word_sha256':sha256(WORD.read_bytes()).hexdigest(),
             'privacy':'Opaque pixel masks; originals preserved; no raw originals embedded'}
    STATE.write_text(json.dumps(state,ensure_ascii=False,indent=2),encoding='utf-8')
    print(json.dumps(state,ensure_ascii=False))
elif sys.argv[1] == 'insert':
    state = json.loads(STATE.read_text(encoding='utf-8'))
    assert sha256(WORD.read_bytes()).hexdigest() == state['before_word_sha256'], 'Saved document changed'
    doc = Document(WORD)
    assert len(doc.inline_shapes)==14
    old_caps = {id(p._p):re.match(r'ภาพประกอบที่ (ข-\d+) ',p.text).group(1)
                for p in doc.paragraphs if re.match(r'ภาพประกอบที่ (ข-\d+) ',p.text)}
    # Hold actual elements: python-docx wrapper identity can change on iteration.
    old_caps = [(p._p,re.match(r'ภาพประกอบที่ (ข-\d+) ',p.text).group(1))
                for p in doc.paragraphs if re.match(r'ภาพประกอบที่ (ข-\d+) ',p.text)]
    items = [
      ('การดูและแก้ไขโปรไฟล์', state['outputs'][0], 'หน้าจอโปรไฟล์ของนักท่องเที่ยว', 6.4,
       'เปิดเมนู โปรไฟล์ แล้วเลือก โปรไฟล์ของฉัน เพื่อตรวจสอบชื่อ นามสกุล อีเมล และเบอร์โทรศัพท์ตามช่องที่แสดง หากต้องปรับข้อมูลให้แก้เฉพาะช่องที่ต้องการแล้วกด บันทึก ที่มุมขวาบน จากนั้นรอผลการบันทึกก่อนออกจากหน้า ส่วน ความสนใจในการเที่ยว แสดงตัวเลือกกิจกรรมที่ผู้ใช้งานเลือกไว้ โดยสามารถเลื่อนหน้าจอเพื่อดูรายการด้านล่างได้'),
      ('การตรวจสถานะอนุมัติและข้อมูลบริษัท', state['outputs'][1], 'หน้าภาพรวมและสถานะบัญชีบริษัทนำเที่ยว', 15.0,
       'หลังเข้าสู่ระบบบริษัทนำเที่ยว ให้เลือกเมนู ภาพรวม เพื่อดูสถานะบัญชีและข้อมูลบริษัท หน้านี้แสดงสถานะ อนุมัติแล้ว พร้อมข้อมูลใบอนุญาตและผู้ประสานงาน บริษัทสามารถเลือก เปิด Lead Marketplace เพื่อดูกลุ่มที่พร้อมรับแพ็กเกจ หรือเลือก ดูข้อเสนอของฉัน เพื่อติดตามข้อเสนอเดิม ภาพนี้แสดงเฉพาะหน้าภาพรวม ไม่ใช่ผลการยื่นข้อเสนอหรือผลโหวตเลือกบริษัท'),
    ]
    for title,path,caption,width,text in items:
        match = [p for p in doc.paragraphs if p.text=='[รอภาพหน้าจอจริง: '+title+']']
        assert len(match)==1, 'Expected one pending marker'
        p=match[0];p.clear();p.style='Normal';p.alignment=WD_ALIGN_PARAGRAPH.CENTER
        p.paragraph_format.first_line_indent=Cm(0)
        p.paragraph_format.keep_with_next=True
        p.paragraph_format.space_before=Pt(6);p.paragraph_format.space_after=Pt(6)
        shape=p.add_run().add_picture(path,width=Cm(width))
        shape._inline.docPr.set('descr',caption+' โดยปิดบังข้อมูลส่วนตัวในสำเนาภาพ')
        c=p.insert_paragraph_before('ภาพประกอบที่ ข-0 '+caption,style='Caption');p._p.addnext(c._p)
        c.alignment=WD_ALIGN_PARAGRAPH.CENTER;c.paragraph_format.first_line_indent=Cm(0)
        c.paragraph_format.keep_with_next=True
        p.paragraph_format.line_spacing=1
        # Update only the first existing explanatory paragraph after this marker.
        nxt=c._p.getnext()
        target=next(q for q in doc.paragraphs if q._p is nxt)
        target.runs[0].text=text
        for run in target.runs[1:]:
            run.text=''
    mapping={};n=0;captions=[]
    for p in doc.paragraphs:
        if re.match(r'ภาพประกอบที่ ข-\d+ ',p.text):
            n+=1
            old=next((old for el,old in old_caps if el is p._p),None)
            if old:mapping[old]=f'ข-{n}'
            txt=re.sub(r'ข-\d+',f'ข-{n}',p.text,count=1)
            p.runs[0].text=txt
            for r in p.runs[1:]:r.text=''
            captions.append(txt)
    # Preserve cross-references to the existing figures after renumbering.
    for p in doc.paragraphs:
        if p.text.startswith('ภาพประกอบที่ '):continue
        for r in p.runs:
            if re.search(r'ข-\d+',r.text):
                r.text=re.sub(r'ข-\d+',lambda m:mapping.get(m.group(0),m.group(0)),r.text)
    assert len(doc.inline_shapes)==16
    assert sum('[รอภาพหน้าจอจริง:' in p.text for p in doc.paragraphs)==33
    doc.core_properties.author='';doc.core_properties.last_modified_by=''
    staging=ROOT/'work/appendix_profile_dashboard_staging.docx'
    doc.save(staging)
    with ZipFile(staging) as z:
        assert z.testzip() is None
    check=Document(staging)
    ids=[re.match(r'ภาพประกอบที่ ([กข]-\d+) ',p.text).group(1) for p in check.paragraphs if re.match(r'ภาพประกอบที่ ([กข]-\d+) ',p.text)]
    assert len(ids)==16 and len(set(ids))==16
    staging.replace(WORD)
    copy2(WORD,Path(state['checkpoint'])/WORD.name)
    state.update({'embedded_images':16,'pending_topics':33,'caption_mapping':mapping,'captions_b':captions,'word_sha256':sha256(WORD.read_bytes()).hexdigest()})
    STATE.write_text(json.dumps(state,ensure_ascii=False,indent=2),encoding='utf-8')
    (Path(state['checkpoint'])/'verification.json').write_text(json.dumps(state,ensure_ascii=False,indent=2),encoding='utf-8')
    print(json.dumps(state,ensure_ascii=False))
else:
    raise SystemExit('Use prepare or insert')
