#!/usr/bin/env python3
import os
import re
import json

BASE_DIR = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
ISL_DIR = os.path.join(BASE_DIR, "..", "ISL-2026")
CONTENT_DIR = os.path.join(BASE_DIR, "content")

MONTH_MAP = {
    "january": "01", "jan": "01",
    "february": "02", "feb": "02",
    "march": "03", "mar": "03",
    "april": "04", "apr": "04",
    "may": "05",
    "june": "06", "jun": "06",
    "july": "07", "jul": "07",
    "august": "08", "aug": "08",
    "september": "09", "sep": "09", "sept": "09",
    "october": "10", "oct": "10",
    "november": "11", "nov": "11",
    "december": "12", "dec": "12",
}

def to_iso(raw):
    if not raw or "in progress" in raw.lower():
        return None
    raw = raw.strip()
    
    MON_PAT = r'(?:January|February|March|April|May|June|July|August|September|October|November|December|Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)'

    # 1) End-anchored English month + 19XX/20XX year: "March 2019.", "October 2018"
    m_end = re.search(rf'\b({MON_PAT})\.?\s*,?\s*((?:19|20)\d{{2}})\s*\.?\s*$', raw, re.I)
    if m_end:
        mo_str = m_end.group(1).lower().rstrip('.')
        if mo_str in MONTH_MAP:
            return f"{m_end.group(2)}-{MONTH_MAP[mo_str]}"

    # 2) Korean "2026년 6월", "9월, 1999"
    m_kor = re.search(r'((?:19|20)\d{2})\s*년\s*(\d{1,2})\s*월', raw)
    if m_kor:
        yr = int(m_kor.group(1))
        mo = int(m_kor.group(2))
        if 1 <= mo <= 12:
            return f"{yr:04d}-{mo:02d}"

    m_kor2 = re.search(r'(\d{1,2})\s*월\s*,?\s*((?:19|20)\d{2})', raw)
    if m_kor2:
        mo = int(m_kor2.group(1))
        yr = int(m_kor2.group(2))
        if 1 <= mo <= 12:
            return f"{yr:04d}-{mo:02d}"

    # 3) Last match of English Month + Year anywhere in string (bypasses preceding article/issue numbers like s19030620 or e2035)
    ms = list(re.finditer(rf'\b({MON_PAT})\.?\s*,?\s*((?:19|20)\d{{2}})', raw, re.I))
    if ms:
        for m_txt in reversed(ms):
            mo_str = m_txt.group(1).lower().rstrip('.')
            yr_str = m_txt.group(2)
            if mo_str in MONTH_MAP:
                return f"{yr_str}-{MONTH_MAP[mo_str]}"

    # 4) ISO date: YYYY-MM-DD, YYYY.MM.DD (where YYYY is 19XX or 20XX)
    m = re.search(r'((?:19|20)\d{2})[. /\\-]?(\d{1,2})[. /\\-]?(\d{1,2})', raw)
    if m:
        yr = int(m.group(1))
        mo = int(m.group(2))
        day = int(m.group(3))
        if 1 <= mo <= 12 and 1 <= day <= 31:
            return f"{yr:04d}-{mo:02d}-{day:02d}"

    # 5) ISO month: YYYY-MM or YYYY.MM
    m_ym = re.search(r'((?:19|20)\d{2})[. /\\-]?(\d{1,2})', raw)
    if m_ym:
        yr = int(m_ym.group(1))
        mo = int(m_ym.group(2))
        if 1 <= mo <= 12:
            return f"{yr:04d}-{mo:02d}"

    # 6) 19XX or 20XX year only
    m_y = re.search(r'\b((?:19|20)\d{2})\b', raw)
    if m_y:
        return f"{m_y.group(1)}"

    return raw

def read_file(filename):
    path = os.path.join(ISL_DIR, filename)
    with open(path, "r", encoding="utf-8-sig") as f:
        return f.read()

def parse_members():
    html = read_file("member.html")
    parts = re.split(r'<H2>\s*Alumni.*?</H2>', html, flags=re.S | re.I)
    active_html = parts[0]
    alumni_html = parts[1] if len(parts) > 1 else ""

    degree_map = {
        "Professor": "Professor",
        "Ph. D.": "PhD",
        "Ph.D.": "PhD",
        "Ph. D. Candidate": "PhDCandidate",
        "Ph.D. Candidate": "PhDCandidate",
        "Ph. D. Student": "PhDStudent",
        "Ph.D. Student": "PhDStudent",
        "M. S. Candidate": "MSCandidate",
        "M.S. Candidate": "MSCandidate",
        "M. S. Student": "MSStudent",
        "M.S. Student": "MSStudent",
    }

    # Active members
    active_members = []
    active_items = re.findall(r'<LI><H4>(.*?)</H4>', active_html, flags=re.S | re.I)
    for item in active_items:
        clean_item = re.sub(r'<a.*?>.*?</a>', '', item, flags=re.I)
        clean_item = re.sub(r'<.*?>', '', clean_item)
        clean_item = clean_item.strip().replace('\n', ' ')
        clean_item = re.sub(r'[:&\s]+$', '', clean_item)
        if not clean_item:
            continue
        if re.search(r'^Seok-Joo Koh\b', clean_item) or "고석주" in clean_item:
          en = "Seok-Joo Koh"
          ko = "고석주"
          degree = "Professor"
          aff = None
        else:
          m = re.search(r'^(.*?)\s*\((.*?),\s*(.*?)\)(?:\s*with\s*(.*))?$', clean_item)
          if m:
            en = m.group(1).strip()
            ko = m.group(2).strip()
            deg_str = m.group(3).strip()
            aff = m.group(4).strip() if m.group(4) else None
          else:
            # Case like Hoang Anh Dang (M. S. Student)
            m2 = re.search(r'^(.*?)\s*\((.*?)\)(?:\s*with\s*(.*))?$', clean_item)
            if m2:
              en = m2.group(1).strip()
              ko = en
              deg_str = m2.group(2).strip()
              aff = m2.group(3).strip() if m2.group(3) else None
            else:
              en = clean_item
              ko = clean_item
              deg_str = "MSStudent"
              aff = None

          degree = degree_map.get(deg_str, "MSStudent")

        mem = {"ko": ko, "en": en, "degree": degree}
        if aff:
          mem["affiliation"] = aff
        active_members.append(mem)

    # Alumni
    alumni = []
    alumni_items = re.findall(r'<LI><H4>(.*?)</H4>', alumni_html, flags=re.S | re.I)
    if len(alumni_items) < 60:
        alumni_items = re.findall(r'<LI>(.*?)(?=<LI>|<OL>|</OL>|$)', alumni_html, flags=re.S | re.I)

    month_map = {"January":"01","February":"02","March":"03","April":"04","May":"05","June":"06","July":"07","August":"08","September":"09","October":"10","November":"11","December":"12"}

    for item in alumni_items:
        clean = re.sub(r'<.*?>', '\n', item).strip()
        lines = [l.strip() for l in clean.split('\n') if l.strip()]
        if not lines:
            continue
        first_line = lines[0]
        if "Alumni" in first_line:
            continue

        m = re.search(r'^(.*?)\s*\((?:(.*?),\s*)?(Ph\.\s*D\.|Ph\.D\.|M\.\s*S\.|M\.S\.)\s+([A-Za-z]+\s+\d{4})', first_line)
        if not m:
            m = re.search(r'^(.*?)\s*\((?:(.*?),\s*)?(Ph\.\s*D\.|Ph\.D\.|M\.\s*S\.|M\.S\.)', first_line)

        if m:
            en = m.group(1).strip()
            ko = m.group(2).strip() if m.group(2) else en
            deg_raw = m.group(3).strip()
            date_raw = m.group(4).strip() if len(m.groups()) >= 4 and m.group(4) else "August 2026"
            major = None
            if " in " in first_line:
                m_maj = re.search(r'\s+in\s+([A-Za-z\s]+)', first_line)
                if m_maj: major = m_maj.group(1).strip()

            degree = "PhD" if "Ph" in deg_raw else "MS"
            parts = date_raw.split()
            grad_date = f"{parts[1]}-{month_map.get(parts[0], '01')}" if len(parts)==2 else "2026-01"
            cur_pos = " ".join(lines[1:]) if len(lines) > 1 else None

            alum = {
                "ko": ko,
                "en": en,
                "degree": degree,
                "graduatedAt": grad_date,
            }
            if major: alum["major"] = major
            if cur_pos: alum["currentPosition"] = cur_pos
            alumni.append(alum)

    return active_members, alumni

def parse_publications():
    intl_html = read_file("paper-international.html")
    dom_html = read_file("paper-domestic.html")
    pat_html = read_file("patent.html")

    intl_pubs = []
    intl_items = re.findall(r'<LI>(.*?)</LI>', intl_html, flags=re.S | re.I)
    for item in intl_items:
        m_title = re.search(r'<U>(.*?)</U>', item, flags=re.S | re.I)
        if m_title:
            raw_t = re.sub(r'<br/?>', '', m_title.group(1), flags=re.I).replace('\n', ' ').strip()
            title = re.sub(r'^[\s"“”]+|[\s"“”,]+$', '', raw_t).strip()
        else:
            title = ""
        
        m_venue = re.search(r'<I>\s*(.*?)\s*</I>', item, flags=re.S | re.I)
        venue = m_venue.group(1).replace('\n', ' ').strip() if m_venue else ""

        rest = item[m_venue.end():] if m_venue else item
        rest_clean = re.sub(r'<.*?>', '', rest).replace('\n', ' ').strip()
        rest_clean = re.sub(r'^\s*,\s*', '', rest_clean)

        pub_date = to_iso(rest_clean) or "2026-01"

        intl_pubs.append({
            "category": "intl-journal-conf",
            "title": title,
            "venue": venue,
            "volume": rest_clean,
            "publishedAt": pub_date
        })

    dom_pubs = []
    dom_items = re.findall(r'<LI>(.*?)</LI>', dom_html, flags=re.S | re.I)
    for item in dom_items:
        m_title = re.search(r'<U>(.*?)</U>', item, flags=re.S | re.I)
        if m_title:
            raw_t = re.sub(r'<br/?>', '', m_title.group(1), flags=re.I).replace('\n', ' ').strip()
            title = re.sub(r'^[\s"“”]+|[\s"“”,]+$', '', raw_t).strip()
        else:
            title = ""

        m_venue = re.search(r'<I>\s*(.*?)\s*</I>', item, flags=re.S | re.I)
        venue = m_venue.group(1).replace('\n', ' ').strip() if m_venue else ""

        rest = item[m_venue.end():] if m_venue else item
        rest_clean = re.sub(r'<.*?>', '', rest).replace('\n', ' ').strip()
        rest_clean = re.sub(r'^\s*,\s*', '', rest_clean)

        is_kci = "(KCI)" in item or "(KCI)" in rest_clean
        pub_date = to_iso(rest_clean) or "2026-01"

        dom_pubs.append({
            "category": "domestic-journal-conf",
            "title": title,
            "venue": venue,
            "volume": rest_clean,
            "publishedAt": pub_date,
            "kci": is_kci
        })

    patents = []
    pat_items = re.findall(r'<LI>(.*?)</LI>', pat_html, flags=re.S | re.I)
    for item in pat_items:
        clean = re.sub(r'<.*?>', '\n', item)
        lines = [l.strip() for l in clean.split('\n') if l.strip()]
        if not lines:
            continue
        title = re.sub(r'^[\s"“”]+|[\s"“”,]+$', '', lines[0]).strip()
        inventors = ""
        app_no = ""
        app_date = None
        reg_no = None
        reg_date = None
        country = "한국"

        for l in lines[1:]:
            if l.startswith("발명자:"):
                inventors = l.replace("발명자:", "").strip()
            elif l.startswith("출원번호:"):
                m = re.search(r'출원번호:\s*([\d-]+)\s*\((.*?),\s*([\d.]+)\)', l)
                if m:
                    app_no = m.group(1)
                    country = m.group(2)
                    app_date = to_iso(m.group(3))
                else:
                    app_no = l.replace("출원번호:", "").strip()
            elif l.startswith("등록번호:"):
                m = re.search(r'등록번호:\s*([\d-]+)\s*\((.*?),\s*([\d.]+)\)', l)
                if m:
                    reg_no = m.group(1)
                    reg_date = to_iso(m.group(3))
                else:
                    reg_no = l.replace("등록번호:", "").strip()

        pub_date = app_date[:7] if app_date else "2026-01"
        patents.append({
            "category": "patent",
            "title": title,
            "inventors": inventors,
            "applicationNo": app_no,
            "applicationAt": app_date,
            "registrationNo": reg_no,
            "registrationAt": reg_date,
            "country": country,
            "publishedAt": pub_date
        })

    return intl_pubs, dom_pubs, patents

def parse_lectures():
    html = read_file("lecture.html")
    semesters = []
    sections = re.split(r'<H1 ALIGN="CENTER">(.*?)</H1>', html, flags=re.I)
    for i in range(1, len(sections), 2):
        term_str = sections[i].strip()
        body = sections[i+1]
        parts = term_str.split()
        if len(parts) != 2:
            continue
        term = parts[0]
        year = int(parts[1])

        courses = []
        c_items = re.findall(r'<H3>(.*?)(?:</H3>|<BR>|$)', body, flags=re.S | re.I)
        for item in c_items:
            clean = re.sub(r'<.*?>', '', item).strip()
            if not clean:
                continue
            if "No Class" in clean:
                courses.append({"code": "SABBATICAL", "en": "No Class (Sabbatical)", "note": "Sabbatical"})
            else:
                m = re.search(r'^(.*?)\s*\((.*?)\)$', clean)
                if m:
                    courses.append({"code": m.group(2).strip(), "en": m.group(1).strip()})
                else:
                    courses.append({"code": "COMP", "en": clean})

        semesters.append({
            "term": term,
            "year": year,
            "courses": courses
        })

    return semesters

def parse_standards():
    html = read_file("standard.html")
    bodies = []
    sections = re.split(r'<H3>(.*?)</H3>', html, flags=re.I)
    for i in range(1, len(sections), 2):
        header = sections[i].strip()
        body = sections[i+1]

        m_head = re.search(r'^(.*?)\s*\((.*?)\):\s*(.*)$', header)
        if not m_head:
            continue
        org = m_head.group(1).strip()
        full = m_head.group(2).strip()
        period = m_head.group(3).strip()
        scope = "domestic" if "TTA" in org else "international"
        role = "Convenor" if "Convenor" in header or "Convenor" in body else None

        projects = []
        if re.search(r'^\s*o\s+', body, flags=re.M):
            proj_blocks = re.split(r'\s*o\s+', body)
            for proj_b in proj_blocks:
                if not proj_b.strip():
                    continue
                lines = proj_b.strip().split('<OL>')
                p_head = lines[0].replace('<BR>', '').strip()
                
                m_proj = re.search(r'^(.*?):\s*(.*)$', p_head)
                wg = m_proj.group(1).strip() if m_proj else "WG"
                p_name = m_proj.group(2).strip() if m_proj else p_head

                docs = []
                if len(lines) > 1:
                    doc_items = re.findall(r'<LI>(.*?)</LI>', lines[1], flags=re.S | re.I)
                    for d_item in doc_items:
                        d_clean = re.sub(r'<.*?>', '\n', d_item)
                        d_lines = [l.strip() for l in d_clean.split('\n') if l.strip()]
                        if not d_lines:
                            continue
                        d_title = d_lines[0].strip('" ')
                        d_rest = " ".join(d_lines[1:]) if len(d_lines) > 1 else ""

                        status = "IS"
                        if "In Progress" in d_rest: status = "InProgress"
                        elif "WDTR" in d_rest or "CDTR" in d_rest: status = "WDTR"
                        elif "CDV" in d_rest: status = "CDV"
                        elif "TR" in d_rest: status = "TR"
                        elif "TS" in d_rest: status = "TS"

                        m_date = re.search(r'\((.*?)\)', d_rest)
                        pub_date = to_iso(m_date.group(1)) if m_date else None

                        docs.append({
                            "title": d_title,
                            "ref": d_rest,
                            "status": status,
                            "publishedAt": pub_date
                        })

                projects.append({
                    "wg": wg,
                    "name": p_name,
                    "documents": docs
                })
        else:
            doc_items = re.findall(r'<LI>(.*?)</LI>', body, flags=re.S | re.I)
            docs = []
            for d_item in doc_items:
                d_clean = re.sub(r'<.*?>', '\n', d_item)
                d_lines = [l.strip() for l in d_clean.split('\n') if l.strip()]
                if not d_lines:
                    continue
                d_title = d_lines[0].strip('" ')
                d_rest = " ".join(d_lines[1:]) if len(d_lines) > 1 else ""

                status = "IS"
                if "In Progress" in d_rest: status = "InProgress"
                elif "WDTR" in d_rest or "CDTR" in d_rest: status = "WDTR"
                elif "CDV" in d_rest: status = "CDV"
                elif "TR" in d_rest: status = "TR"
                elif "TS" in d_rest: status = "TS"

                m_date = re.search(r'\((.*?)\)', d_rest)
                pub_date = to_iso(m_date.group(1)) if m_date else None

                docs.append({
                    "title": d_title,
                    "ref": d_rest,
                    "status": status,
                    "publishedAt": pub_date
                })

            projects.append({
                "wg": "Main",
                "name": full,
                "documents": docs
            })

        bodies.append({
            "org": org,
            "full": full,
            "scope": scope,
            "period": period,
            "role": role,
            "projects": projects
        })

    return bodies

def parse_projects():
    projects = [
        {
            "slug": "iot-standards",
            "title": "AIoT & AI-RAN",
            "abstract": "AIoT & AI-RAN investigates agent-based IoT architectures in which autonomous AI agents are distributed across sensor, edge, and radio access layers. The project studies agent-to-agent coordination over high-performance transport (gRPC/QUIC) bridged with constrained edge protocols (MQTT/CoAP), targeting AI-RAN designs for distributed autonomous control.",
            "keywords": ["AIoT", "agent-based IoT", "AI-RAN", "constrained edge protocols", "distributed autonomous control"],
            "standardsTrack": "National Research Foundation of Korea (NRF)",
            "standardsOrg": "NRF",
            "period": "2026 ~ Present",
            "deliverables": [],
        },
        {
            "slug": "ccis",
            "title": "MCM",
            "abstract": "Multilateral and Collaborative Metaverse (MCM) refers to metaverse systems in which two or more participants simultaneously interact within a shared virtual space for a common collaborative purpose. Unlike single-user or purely competitive environments, an MCM service is defined by coordinated participation: its intended outcome cannot be achieved by a single user acting alone. The project defines general requirements, service classification, and a gap analysis against existing standards.",
            "keywords": ["MCM", "metaverse", "shared virtual space", "coordinated participation", "service classification"],
            "standardsTrack": "IEC/TC 100/WG 12 supported by KEIT",
            "standardsOrg": "IEC TC100",
            "period": "2026 ~ Present",
            "deliverables": [],
        },
        {
            "slug": "vlc-iot",
            "title": "MVQM",
            "abstract": "Management of Visual Quality in Metaverse Systems (MVQM) is a conceptual and functional approach for managing visual quality by dynamically adapting visual data delivery in response to user context, device capability, and network conditions. It emphasizes user-centric, context-aware quality management over static system-centric optimization, covering hybrid visual assets, level of detail, and area of interest adaptation.",
            "keywords": ["MVQM", "visual quality", "hybrid visual assets", "level of detail", "area of interest"],
            "standardsTrack": "IEC/TC 100/WG 12 supported by KEIT",
            "standardsOrg": "IEC TC100",
            "period": "2026 ~ Present",
            "deliverables": [],
        }
    ]

    return projects

def clean_dict(obj):
    if isinstance(obj, dict):
        return {k: clean_dict(v) for k, v in obj.items() if v is not None}
    elif isinstance(obj, list):
        return [clean_dict(v) for v in obj if v is not None]
    return obj

def main():
    active_m, alumni_m = parse_members()
    intl_p, dom_p, pat_p = parse_publications()
    semesters = parse_lectures()
    bodies = parse_standards()
    projects = parse_projects()

    os.makedirs(CONTENT_DIR, exist_ok=True)

    with open(os.path.join(CONTENT_DIR, "members.ts"), "w", encoding="utf-8") as f:
        f.write('// AUTO-GENERATED by scripts/extract/generate_all.py — DO NOT EDIT BY HAND\n')
        f.write('import { Member, Alumnus } from "./types";\n\n')
        f.write(f'export const activeMembers: Member[] = {json.dumps(clean_dict(active_m), ensure_ascii=False, indent=2)};\n\n')
        f.write(f'export const alumni: Alumnus[] = {json.dumps(clean_dict(alumni_m), ensure_ascii=False, indent=2)};\n')

    with open(os.path.join(CONTENT_DIR, "publications.ts"), "w", encoding="utf-8") as f:
        f.write('// AUTO-GENERATED by scripts/extract/generate_all.py — DO NOT EDIT BY HAND\n')
        f.write('import { Publication, Patent } from "./types";\n\n')
        all_pubs = intl_p + dom_p
        f.write(f'export const publications: Publication[] = {json.dumps(clean_dict(all_pubs), ensure_ascii=False, indent=2)};\n\n')
        f.write(f'export const patents: Patent[] = {json.dumps(clean_dict(pat_p), ensure_ascii=False, indent=2)};\n')

    with open(os.path.join(CONTENT_DIR, "lectures.ts"), "w", encoding="utf-8") as f:
        f.write('// AUTO-GENERATED by scripts/extract/generate_all.py — DO NOT EDIT BY HAND\n')
        f.write('import { Semester } from "./types";\n\n')
        f.write(f'export const semesters: Semester[] = {json.dumps(clean_dict(semesters), ensure_ascii=False, indent=2)};\n')

    with open(os.path.join(CONTENT_DIR, "standards.ts"), "w", encoding="utf-8") as f:
        f.write('// AUTO-GENERATED by scripts/extract/generate_all.py — DO NOT EDIT BY HAND\n')
        f.write('import { StandardsBody } from "./types";\n\n')
        f.write(f'export const standardsBodies: StandardsBody[] = {json.dumps(clean_dict(bodies), ensure_ascii=False, indent=2)};\n')

    with open(os.path.join(CONTENT_DIR, "projects.ts"), "w", encoding="utf-8") as f:
        f.write('// AUTO-GENERATED by scripts/extract/generate_all.py — DO NOT EDIT BY HAND\n')
        f.write('import { ResearchProject } from "./types";\n\n')
        f.write(f'export const researchProjects: ResearchProject[] = {json.dumps(clean_dict(projects), ensure_ascii=False, indent=2)};\n')

if __name__ == "__main__":
    main()
