from pathlib import Path
from datetime import datetime
import json,re,shutil
from docx import Document

ROOT=Path(r'C:\Users\Asus\Desktop\TourAppProject\travelin_app\docs\thesis_appendices')
STAMP=datetime.now().strftime('%Y%m%d_%H%M%S')
OUT=ROOT/'checkpoints'/('continuation_'+STAMP)
OUT.mkdir(parents=True,exist_ok=True)
DOC=ROOT/'TourApp_Appendix_A_B.docx'
shutil.copy2(DOC,OUT/'00_before_continuation.docx')
for f in ['appendix_pending.md','appendix_image_index.md','appendix_progress.md']:
    shutil.copy2(ROOT/f,OUT/f)
shared={
'ก.5': 'ภาพประกอบที่ ข-1 แสดงหน้าแรกเมื่อเปิดแอปนักท่องเที่ยวได้ ใช้ภาพร่วมกับ ข.1.1; ภาพนี้ไม่ใช่หลักฐานการติดตั้ง SDK หรือการเชื่อมต่อฐานข้อมูล',
'ก.8': 'ใช้ภาพประกอบที่ ก-1 และ ข-1 ร่วมกันเพื่อเทียบหน้าล็อกอิน Portal และหน้าแรกแอปที่เปิดได้ การยืนยันการเชื่อมต่อฐานข้อมูลและความพร้อมครบระบบให้ตรวจตามขั้นตอนด้านล่าง',
'ข.1.26': 'ใช้ภาพประกอบที่ ข-2 ร่วมกันเพื่อแสดงหน้าสำหรับเข้าสู่ระบบด้วยบัญชีถัดไป ภาพนี้ไม่แสดงปุ่มออกจากกลุ่มหรือยืนยันว่ามีการออกจากกลุ่มแล้ว',
'ข.2.12': 'ใช้ภาพประกอบที่ ข-7 ร่วมกันเพื่อแสดงหน้าล็อกอินบริษัทสำหรับเข้าใช้งานครั้งถัดไป ภาพนี้ไม่ใช่หน้าคะแนนบริษัท',
'ข.3.8': 'ใช้ภาพประกอบที่ ข-9 ร่วมกันเพื่อแสดงหน้าล็อกอินผู้ดูแลสำหรับเข้าใช้งานครั้งถัดไป ไม่ใช้ภาพนี้เป็นหลักฐานการเปลี่ยนสิทธิ์บัญชี',
}
bs={'ก.1','ก.2','ก.3','ก.4','ก.7','ข.1.2'}
ds={'ข.1.10','ข.1.21','ข.2.7','ข.3.4','ข.3.6'}
old=(ROOT/'appendix_pending.md').read_text(encoding='utf-8')
rows=[]
for line in old.splitlines():
    m=re.match(r'- ([กข]\.\d+(?:\.\d+)?) (.+?) \((.+?); key `(.+?)`\)',line)
    if m:
        label,title,role,key=m.groups();cat='E' if label in shared else ('B' if label in bs else ('D' if label in ds else 'C'))
        reason={'B':'เปิดหน้าที่ไม่ต้องเข้าสู่ระบบหรือแสดงไฟล์โครงการที่ไม่มีค่าลับได้ โดยไม่รันคำสั่งเปลี่ยนระบบ','C':'ต้องมี session ตามบทบาทและข้อมูลเดิมที่เข้าถึงได้ อ่านอย่างเดียว; หากไม่มีข้อมูลเดิมให้รอภาพจากการใช้งานจริง','D':'ใช้ได้เฉพาะภาพผลจากธุรกิจที่เกิดขึ้นแล้ว ห้ามดำเนินรายการเพื่อสร้างภาพ','E':'ใช้ภาพร่วมที่ระบุใน Word ไม่แทรกภาพซ้ำ'}[cat]
        rows.append(dict(label=label,title=title,role=role,key=key,category=cat,reason=reason))
assert len(rows)==44,len(rows)
d=Document(DOC);current=''
for p in d.paragraphs:
    m=re.match(r'^([กข]\.\d+(?:\.\d+)?) ',p.text)
    if m:current=m.group(1)
    elif p.text.startswith('[รอภาพหน้าจอจริง:') and current in shared:
        p.clear();p.add_run(shared[current]);p.paragraph_format.keep_with_next=True
d.save(DOC);shutil.copy2(DOC,OUT/'01_shared_images.docx')
remaining=[r for r in rows if r['category']!='E']
classification=['# การจำแนกรายการรอภาพเดิม 44 จุด','', 'A ภาพเก่าที่เหมาะสมยังไม่ใช้; B ถ่ายใหม่แบบอ่านอย่างเดียว; C เจ้าของช่วยเข้าสู่ระบบ; D ต้องใช้ผลธุรกิจเดิมเท่านั้น; E ใช้ภาพร่วม','', '| หัวข้อ | หมวด | เหตุผล |','|---|---|---|']
classification += [f"| {r['label']} {r['title']} | {r['category']} | {r['reason']} |" for r in rows]
classification+=['','สรุป A 0 / B 6 / C 28 / D 5 / E 5','', 'ตรวจภาพที่ยังไม่เลือกเพิ่ม: profile_lower.png และ profile_saved.png เป็น UI เก่าที่มีข้อมูลบัญชี; register_mobile.png แบบเก่าระบุรหัสผ่าน 6 ตัว; japan_detail.png เป็นโฟลว์เข้าร่วมกลุ่มแบบเก่า จึงไม่ใช้ในคู่มือปัจจุบัน ไม่เปิดไฟล์ password_typed.png, qa_login_retry.png หรือ contact sheet ที่อาจแสดงรหัสผ่านซ้ำ']
(ROOT/'work'/'pending_classification.md').write_text('\n'.join(classification)+'\n',encoding='utf-8')
pending=['# รายการภาพที่ยังต้องเก็บ','', 'เหลือ 39 หัวข้อหลังใช้ภาพร่วม 5 หัวข้อ ไม่สร้างภาพจำลองหรือเปลี่ยนธุรกิจเพื่อถ่ายภาพ รายการ C ต้องใช้บัญชีตามบทบาทและข้อมูลเดิมที่เจ้าของมีสิทธิ์ดู รายการ D ให้รอภาพจากการใช้งานจริง หากยังไม่มีผลรายการเดิม','', '| หัวข้อ | หมวด | การจัดหา |','|---|---|---|']
pending += [f"| {r['label']} {r['title']} | {r['category']} | {r['reason']} |" for r in remaining]
pending+=['','## รายการเดียวสำหรับเจ้าของช่วยเปิดหน้าจอ','', 'ไม่ส่งหรือบันทึกรหัสผ่าน กรุณาเข้าสู่ระบบด้วยตนเองและเก็บเฉพาะข้อมูลที่มีสิทธิ์ดู ปิดบังชื่อ อีเมล โทรศัพท์ เลขบัญชี สลิป และ token ในสำเนาภาพก่อนใช้','', '| แอป | บทบาท | เมนูและหน้าที่ต้องเปิด | ที่บันทึก |','|---|---|---|','| Flutter บน Pixel_6 | นักท่องเที่ยว | โปรไฟล์; สถานะจับคู่/กลุ่มของฉัน; แชตและโหวตแผนเที่ยว; ข้อเสนอ/รายละเอียดบริษัท/ผลโหวต; ช่องทางชำระและสถานะเดิม; Trip Hub/เอกสาร/สถานะเดินทาง/แบบให้คะแนนที่เปิดได้ | screenshots/appendix_b/tourist |','| Portal | บริษัทที่อนุมัติแล้ว | หน้าหลัก/Lead Marketplace/รายละเอียดกลุ่ม/แบบข้อเสนอที่ยังไม่ส่ง/ข้อเสนอเดิม/ผลโหวตและทริปที่ชนะ; เอกสารต้องปิดบังข้อมูลบุคคล | screenshots/appendix_b/agency |','| Portal | ผู้ดูแล | รายการบริษัท/ใบอนุญาต/ผู้ใช้งาน/รายละเอียดสถานะ/กลุ่ม เปิดดูเท่านั้นไม่กดอนุมัติ ระงับหรือ reset | screenshots/appendix_b/admin |','', 'ไม่ต้องสร้างกลุ่ม โหวต เสนอราคา ยืนยันชำระเงิน ส่งสลิป หรือเรียก SlipOK เพื่อภาพ; กลุ่ม #115/#102 ห้ามแก้ ลบหรือรีเซ็ต','', 'ยังต้องจัดเตรียม clean schema-only installer สำหรับติดตั้งใหม่; ก.3 ไม่ใช่คำสั่งให้ import dump ธุรกิจ']
(ROOT/'appendix_pending.md').write_text('\n'.join(pending)+'\n',encoding='utf-8')
with (ROOT/'appendix_image_index.md').open('a',encoding='utf-8') as f:
    f.write('\n## การใช้ภาพร่วมในงานต่อเนื่อง\n\n'+ '\n'.join(f'- {k}: {v}' for k,v in shared.items())+'\n\nยังมีภาพแทรกจริง 10 ตำแหน่งจาก 9 ไฟล์ อ้างใช้ร่วมเพิ่ม 5 หัวข้อ ไม่นับเป็นภาพใหม่หรือ Fixture\n')
with (ROOT/'appendix_progress.md').open('a',encoding='utf-8') as f:
    f.write('\n## งานต่อเนื่อง '+STAMP+' ชุด 1\n\nแก้ Word เดิมเท่านั้น อ้างใช้ภาพร่วม 5 หัวข้อ เหลือ marker 39 จุด จำแนกเดิม44: A0/B6/C28/D5/E5 เก็บ checkpoint รุ่นก่อนและหลังชุดนี้ โดยไม่แตะ checkpoint_01–06 เดิม รอ render/ตรวจหน้ารุ่นต่อเนื่องก่อนส่งมอบ\n')
json.dump({'stamp':STAMP,'checkpoint':str(OUT),'remaining':remaining,'shared':shared},(ROOT/'work'/'continuation_state.json').open('w',encoding='utf-8'),ensure_ascii=False,indent=2)
orig=Document(r'C:\Users\Asus\Downloads\256 EDIT 26 (1).docx')
extract=[{'index':i,'text':p.text} for i,p in enumerate(orig.paragraphs) if p.text.strip()]
json.dump(extract,(ROOT/'work'/'thesis_paragraphs.json').open('w',encoding='utf-8'),ensure_ascii=False,indent=2)
print(json.dumps({'saved':str(DOC),'checkpoint':str(OUT),'pending':39},ensure_ascii=False))
