import json
import os
import re
import sys

sys.stdout.reconfigure(encoding='utf-8')

# --- CSS Stylesheet Template ---

CSS_CONTENT = """/* Dictionary Entry Styling */
.dict-entry {
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans JP", Meiryo, sans-serif;
  line-height: 1.6;
  color: #1e293b;
  background-color: #ffffff;
  padding: 12px 16px;
  margin: 0;
}

/* Dark Mode Support */
@media (prefers-color-scheme: dark) {
  .dict-entry {
    color: #e2e8f0;
    background-color: #0f172a;
  }
}

/* Header Section */
.entry-header {
  border-bottom: 2px solid #0284c7;
  padding-bottom: 6px;
  margin-bottom: 12px;
}
.headword-title {
  font-size: 1.35em;
  font-weight: bold;
  color: #0f172a;
  display: inline-block;
  margin-right: 8px;
}
@media (prefers-color-scheme: dark) {
  .headword-title {
    color: #f8fafc;
  }
}
.v1-v2-badge {
  font-size: 0.8em;
  color: #475569;
  background-color: #f1f5f9;
  border: 1px solid #cbd5e1;
  border-radius: 4px;
  padding: 2px 6px;
  display: inline-block;
  vertical-align: middle;
}
@media (prefers-color-scheme: dark) {
  .v1-v2-badge {
    color: #cbd5e1;
    background-color: #334155;
    border-color: #475569;
  }
}

/* Entry Sections */
.section {
  margin-bottom: 10px;
}
.section-body {
  display: inline;
}

/* Section Labels */
.section-label {
  font-size: 0.85em;
  font-weight: bold;
  padding: 2px 6px;
  border-radius: 4px;
  margin-right: 6px;
  display: inline-block;
}
/* Inline Labels */
.inline-label {
  font-size: 0.85em;
  font-weight: bold;
  padding: 1px 4px;
  border-radius: 3px;
  margin: 0 4px;
  display: inline;
}
.label-adverb {
  background-color: #f5f3ff;
  color: #6d28d9;
  border: 1px solid #ddd6fe;
}
@media (prefers-color-scheme: dark) {
  .label-adverb {
    background-color: #4c1d95;
    color: #c084fc;
    border-color: #7c3aed;
  }
}
.label-example {
  background-color: #e0f2fe;
  color: #0369a1;
  border: 1px solid #bae6fd;
}
@media (prefers-color-scheme: dark) {
  .label-example {
    background-color: #0c4a6e;
    color: #38bdf8;
    border-color: #0284c7;
  }
}
.label-noun {
  background-color: #f0fdf4;
  color: #15803d;
  border: 1px solid #bbf7d0;
}
@media (prefers-color-scheme: dark) {
  .label-noun {
    background-color: #064e3b;
    color: #4ade80;
    border-color: #059669;
  }
}
.label-supplement {
  background-color: #fffbeb;
  color: #b45309;
  border: 1px solid #fde68a;
}
@media (prefers-color-scheme: dark) {
  .label-supplement {
    background-color: #78350f;
    color: #fbbf24;
    border-color: #d97706;
  }
}

/* Definition Bullet Numbers */
.label-explanation {
  font-weight: bold;
  color: #0284c7;
  font-size: 1.1em;
  margin-right: 6px;
}
@media (prefers-color-scheme: dark) {
  .label-explanation {
    color: #38bdf8;
  }
}

.sense-item {
  margin-bottom: 10px;
}
.sub-sense-list {
  padding-left: 20px;
  margin-top: 4px;
}
.sub-sense-item {
  margin-bottom: 4px;
  display: block;
}
.sub-sense-num {
  font-weight: bold;
  color: #0369a1;
  font-size: 0.95em;
  margin-right: 6px;
  display: inline-block;
  min-width: 1.2em;
}
@media (prefers-color-scheme: dark) {
  .sub-sense-num {
    color: #38bdf8;
  }
}

/* Examples List */
.example-list {
  margin: 6px 0 0 10px;
  padding-left: 0;
  list-style-type: none;
}
.example-item {
  position: relative;
  padding-left: 14px;
  margin-bottom: 5px;
  font-size: 0.95em;
  color: #334155;
}
@media (prefers-color-scheme: dark) {
  .example-item {
    color: #cbd5e1;
  }
}
.example-item::before {
  content: "•";
  position: absolute;
  left: 2px;
  top: 0;
  color: #0284c7;
}
@media (prefers-color-scheme: dark) {
  .example-item::before {
    color: #38bdf8;
  }
}

.example-sense-item {
  display: flex;
  align-items: flex-start;
  margin-top: 6px;
}
.example-sense-num {
  font-weight: bold;
  color: #0284c7;
  font-size: 1.1em;
  margin-right: 8px;
  margin-top: 2px;
  flex-shrink: 0;
}
@media (prefers-color-scheme: dark) {
  .example-sense-num {
    color: #38bdf8;
  }
}
.example-sense-item .example-list {
  margin: 0;
  flex-grow: 1;
}

/* Text Formatting style */
a {
  color: #0284c7;
  text-decoration: none;
  border-bottom: 1px dashed #0284c7;
}
a:hover {
  color: #0369a1;
  border-bottom-style: solid;
}
@media (prefers-color-scheme: dark) {
  a {
    color: #38bdf8;
    border-bottom-color: #38bdf8;
  }
  a:hover {
    color: #7dd3fc;
  }
}
strong {
  font-weight: bold;
  color: #0f172a;
}
@media (prefers-color-scheme: dark) {
  strong {
    color: #f8fafc;
  }
}
u {
  text-decoration: none;
  border-bottom: 2px solid #0284c7;
  font-weight: 550;
  color: #0369a1;
  padding-bottom: 1px;
}
@media (prefers-color-scheme: dark) {
  u {
    border-bottom-color: #38bdf8;
    color: #38bdf8;
  }
}

/* Furigana Ruby */
ruby {
  ruby-position: over;
}
rt {
  font-size: 0.58em;
  color: #475569;
  font-weight: normal;
}
@media (prefers-color-scheme: dark) {
  rt {
    color: #94a3b8;
  }
}

/* Page Marker */
.page-marker {
  font-size: 0.72em;
  color: #94a3b8;
  text-align: right;
  margin-top: 12px;
  border-top: 1px dashed #e2e8f0;
  padding-top: 4px;
}
@media (prefers-color-scheme: dark) {
  .page-marker {
    color: #475569;
    border-top-color: #334155;
  }
}
"""

# --- Text Formatting parser ---

def parse_anki_to_ruby(text):
    # Regex to capture Kanji[Furigana] and replace with html ruby tag
    # E.g. "一[いち]途[ず]に" -> "<ruby>一<rt>いち</rt></ruby><ruby>途<rt>ず</rt></ruby>に"
    # E.g. "梢[こずえ]" -> "<ruby>梢<rt>こずえ</rt></ruby>"
    pattern = r'([\u4e00-\u9fff]+)\[([\u3040-\u309f\u30a0-\u30ff]+)\]'
    def repl(m):
        return f"<ruby>{m.group(1)}<rt>{m.group(2)}</rt></ruby>"
    return re.sub(pattern, repl, text)

def process_text_formatting(text):
    # 1. Anki furigana to ruby
    res = parse_anki_to_ruby(text)
    # 2. **text** to <strong>text</strong>
    res = re.sub(r'\*\*(.*?)\*\*', r'<strong>\1</strong>', res)
    # 3. __text__ to <u>text</u>
    res = re.sub(r'__(.*?)__', r'<u>\1</u>', res)
    
    # 4. Inline styled labels replacement
    label_replacements = {
        r'【副⁺】': '<span class="inline-label label-adverb">副⁺</span>',
        r'【副】': '<span class="inline-label label-adverb">副</span>',
        r'【例文】': '<span class="inline-label label-example">例文</span>',
        r'【例\s+文】': '<span class="inline-label label-example">例文</span>',
        r'【名詞形】': '<span class="inline-label label-noun">名詞形</span>',
        r'【名詞】': '<span class="inline-label label-noun">名詞</span>',
        r'【補足】': '<span class="inline-label label-supplement">補足</span>',
        r'【動】': '<span class="inline-label label-supplement">動</span>',
    }
    for pat, rep in label_replacements.items():
        res = re.sub(pat, rep, res)
        
    # 5. Inline reference links replacement (e.g. →「あきれかえる」 -> →「<a href="entry://あきれかえる">あきれかえる</a>」)
    # We clean the link target of trailing sequence numbers/labels to ensure it resolves successfully in MDX readers.
    def link_repl(m):
        indicator = m.group(1)
        target = m.group(2).strip()
        clean_target = re.sub(r'[\s❶❷❸❹❺❻❼❽❾❿ⓐⓑⓒⓓⓔⓕⓖⓗⓘⓙ]+.*', '', target)
        clean_target = re.sub(r'【.*', '', clean_target)
        clean_target = clean_target.strip()
        return f'{indicator}「<a href="entry://{clean_target}">{target}</a>」'
    res = re.sub(r'([→☞])\s*「([^」]+)」', link_repl, res)
    
    # 6. Inline sequence numbers styling (❶-❿, ⓐ-ⓙ) to match standard blue styles.
    # We split by HTML tags and only apply sequence styling to text outside tags to avoid corrupting href attributes.
    parts = re.split(r'(<[^>]+>)', res)
    for i in range(0, len(parts), 2):
        parts[i] = re.sub(r'([❶❷❸❹❺❻❼❽❾❿])', r'<span class="label-explanation">\1</span>', parts[i])
        parts[i] = re.sub(r'([ⓐⓑⓒⓓⓔⓕⓖⓗⓘⓙ])', r'<span class="sub-sense-num">\1</span>', parts[i])
    res = "".join(parts)
        
    return res

# --- Example Parser ---

def format_examples_html(text):
    content = text
    m_pref = re.match(r'^(【?例文】?|【?例\s+文】?|例文)\s*', text)
    if m_pref:
        content = text[m_pref.end():]
        
    raw_items = content.split('/')
    final_items = []
    
    for item in raw_items:
        # Split by number markers like ❶-❿ using lookahead
        sub_items = re.split(r'(?=[❶❷❸❹❺❻❼❽❾❿])', item)
        for sub in sub_items:
            sub_strip = sub.strip()
            if sub_strip:
                final_items.append(sub_strip)
                
    html_lines = ['<ul class="example-list">']
    for item in final_items:
        item_html = process_text_formatting(item)
        html_lines.append(f'<li class="example-item">{item_html}</li>')
    html_lines.append('</ul>')
    return "\n".join(html_lines)

# --- Section HTML Formatter ---

def format_section_to_html(sec):
    stype = sec['type']
    
    if stype == 'page_marker':
        content_lines = sec['content']
        m_num = re.search(r'\d+', content_lines[0])
        num_str = m_num.group(0) if m_num else "?"
        return f'<div class="page-marker">Page {num_str}</div>'
        
    senses = sec.get('senses', [])
    
    if stype == 'explanation':
        html_blocks = ['<div class="section explanation-section">']
        for sense in senses:
            num = sense['num']
            text = sense['text']
            subs = sense.get('subs', [])
            
            html_blocks.append('  <div class="sense-item">')
            # Sense level 1 prefix and body
            sense_line_parts = []
            if num:
                sense_line_parts.append(f'<span class="label-explanation">{num}</span>')
            if text:
                text_html = process_text_formatting(text)
                sense_line_parts.append(f'<span class="section-body">{text_html}</span>')
            if sense_line_parts:
                html_blocks.append(f"    {''.join(sense_line_parts)}")
            
            # Sense level 2 (subs)
            if subs:
                html_blocks.append('    <div class="sub-sense-list">')
                for sub in subs:
                    sub_num = sub['num']
                    sub_text = sub['text']
                    sub_text_html = process_text_formatting(sub_text)
                    html_blocks.append('      <div class="sub-sense-item">')
                    html_blocks.append(f'        <span class="sub-sense-num">{sub_num}</span>')
                    html_blocks.append(f'        <span class="section-body">{sub_text_html}</span>')
                    html_blocks.append('      </div>')
                html_blocks.append('    </div>')
                
            html_blocks.append('  </div>')
        html_blocks.append('</div>')
        return "\n".join(html_blocks)
        
    elif stype == 'adverb':
        html_blocks = []
        for sense in senses:
            num = sense['num']
            text = sense['text']
            
            content = text
            m_pref = re.match(r'^(【?副⁺】?|【?副】?|副\(|副（)\s*', text)
            label_text = "副⁺"
            if m_pref:
                content = text[m_pref.end():]
                label_raw = m_pref.group(1)
                if "副⁺" in label_raw:
                    label_text = "副⁺"
                elif "副" in label_raw:
                    label_text = "副"
            if m_pref and ('(' in m_pref.group(1) or '（' in m_pref.group(1)):
                content = content.rstrip(')）').strip()
                
            full_label = f"{label_text} {num}".strip() if num else label_text
            body_html = process_text_formatting(content)
            
            html_blocks.append(
                f'<div class="section adverb-section">\n'
                f'  <span class="section-label label-adverb">{full_label}</span>\n'
                f'  <span class="section-body">{body_html}</span>\n'
                f'</div>'
            )
        return "\n".join(html_blocks)
        
    elif stype == 'noun':
        html_blocks = []
        for sense in senses:
            num = sense['num']
            text = sense['text']
            
            content = text
            m_pref = re.match(r'^(【?名詞形】?|名詞形|【?名詞】?|名詞)\s*', text)
            label_text = "名詞形"
            if m_pref:
                content = text[m_pref.end():]
                label_raw = m_pref.group(1)
                if "名詞形" in label_raw:
                    label_text = "名詞形"
                elif "名詞" in label_raw:
                    label_text = "名詞"
                    
            full_label = f"{label_text} {num}".strip() if num else label_text
            body_html = process_text_formatting(content)
            
            html_blocks.append(
                f'<div class="section noun-section">\n'
                f'  <span class="section-label label-noun">{full_label}</span>\n'
                f'  <span class="section-body">{body_html}</span>\n'
                f'</div>'
            )
        return "\n".join(html_blocks)
        
    elif stype in ['verb_examples', 'noun_examples']:
        html_blocks = ['<div class="section example-section">']
        html_blocks.append('  <span class="section-label label-example">例文</span>')
        
        # If there is only one sense and its num is empty
        if len(senses) == 1 and not senses[0]['num']:
            items = senses[0].get('items', [])
            list_html = ['  <ul class="example-list">']
            for item in items:
                item_html = process_text_formatting(item)
                list_html.append(f'    <li class="example-item">{item_html}</li>')
            list_html.append('  </ul>')
            html_blocks.extend(list_html)
        else:
            for sense in senses:
                num = sense['num']
                items = sense.get('items', [])
                if not items:
                    continue
                
                html_blocks.append('  <div class="example-sense-item">')
                if num:
                    html_blocks.append(f'    <span class="example-sense-num">{num}</span>')
                
                list_html = ['    <ul class="example-list">']
                for item in items:
                    item_html = process_text_formatting(item)
                    list_html.append(f'      <li class="example-item">{item_html}</li>')
                list_html.append('    </ul>')
                html_blocks.extend(list_html)
                html_blocks.append('  </div>')
                
        html_blocks.append('</div>')
        return "\n".join(html_blocks)
        
        
    elif stype == 'other':
        html_blocks = []
        for sense in senses:
            num = sense['num']
            text = sense['text']
            
            content = text
            m_pref = re.match(r'^(【?補足】?|補足|【?動】?)\s*', text)
            label_text = "補足"
            if m_pref:
                content = text[m_pref.end():]
                label_raw = m_pref.group(1)
                if "補足" in label_raw:
                    label_text = "補足"
                elif "動" in label_raw:
                    label_text = "動"
                    
            full_label = f"{label_text} {num}".strip() if num else label_text
            body_html = process_text_formatting(content)
            
            html_blocks.append(
                f'<div class="section supplement-section">\n'
                f'  <span class="section-label label-supplement">{full_label}</span>\n'
                f'  <span class="section-body">{body_html}</span>\n'
                f'</div>'
            )
        return "\n".join(html_blocks)
        
    return f'<div>{process_text_formatting(sec.get("content", [""])[0])}</div>'

# --- Primary Headword Resolver ---

def make_primary_key(entry):
    kana_list = entry.get('kana', [])
    kanji_list = entry.get('kanji', [])
    if kana_list and kanji_list:
        title_kana = "・".join(kana_list)
        title_kanji = "・".join(kanji_list)
        return f'{title_kana}【{title_kanji}】'
    elif kana_list:
        return "・".join(kana_list)
    else:
        hw = entry['headword'].strip()
        hw_clean = hw.replace('**', '').split('☞')[0].strip()
        return hw_clean

def main():
    json_file = r"d:\OCR Project\复合动词\dictionary.json"
    css_file = r"d:\OCR Project\复合动词\KDJCV.css"
    mdx_file = r"d:\OCR Project\复合动词\KDJCV.txt"
    
    # 1. Write the CSS stylesheet
    with open(css_file, 'w', encoding='utf-8') as f:
        f.write(CSS_CONTENT)
    print(f"Created stylesheet: {css_file}")
    
    style_link = '<link rel="stylesheet" type="text/css" href="KDJCV.css">'
    
    # 2. Load JSON database
    if not os.path.exists(json_file):
        print(f"Error: JSON file {json_file} does not exist.")
        return
        
    with open(json_file, 'r', encoding='utf-8') as f:
        entries = json.load(f)
        
    print(f"Loaded {len(entries)} entries from JSON.")
    
    # Dictionary to hold the final MDX records: search_term -> content
    final_mdx_dict = {}
    
    # First Pass: Generate HTML content for all primary entries (both regular and redirects)
    for idx, entry in enumerate(entries):
        kana_list = entry['kana']
        kanji_list = entry['kanji']
        v1_v2 = entry['v1_v2']
        is_redirect = entry['is_redirect']
        redirect_target = entry['redirect_target']
        sections = entry['sections']
        
        primary_hw = make_primary_key(entry)
        
        # Generate HTML structure
        html_parts = [style_link, '<div class="dict-entry">']
        
        # Header block
        html_parts.append('  <div class="entry-header">')
        title_kana = "・".join(kana_list)
        title_kanji = "・".join(kanji_list)
        title_formatted = f'{title_kana}【{title_kanji}】' if title_kanji else title_kana
        title_html = process_text_formatting(title_formatted)
        
        html_parts.append(f'    <span class="headword-title">{title_html}</span>')
        if v1_v2:
            v1_v2_html = process_text_formatting(v1_v2)
            html_parts.append(f'    <span class="v1-v2-badge">{v1_v2_html}</span>')
        html_parts.append('  </div>')
        
        if is_redirect:
            # Redirection link
            ref_html = (
                f'<div class="section explanation-section">\n'
                f'  <span class="section-body">☞ <a href="entry://{redirect_target}">{redirect_target}</a></span>\n'
                f'</div>'
            )
            html_parts.append(f"  {ref_html}")
            
        # Section blocks
        for sec in sections:
            sec_html = format_section_to_html(sec)
            html_parts.append(f"  {sec_html}")
            
        html_parts.append('</div>')
        
        entry_html_content = "\n".join(html_parts)
        final_mdx_dict[primary_hw] = entry_html_content

    # Second Pass: Generate redirects for individual search keys
    for idx, entry in enumerate(entries):
        kana_list = entry['kana']
        kanji_list = entry['kanji']
        primary_hw = make_primary_key(entry)
        
        # Candidates for redirects
        redirects = set()
        
        # 1. Individual kana
        for kn in kana_list:
            if kn != primary_hw:
                redirects.add(kn)
                
        # 2. Individual kanji (clean of Anki brackets)
        for kj in kanji_list:
            kj_clean = re.sub(r'\[.*?\]', '', kj)
            if kj_clean != primary_hw:
                redirects.add(kj_clean)
                
        # Write redirects to final dict if key not already occupied by a primary entry
        for r_key in redirects:
            if r_key not in final_mdx_dict:
                final_mdx_dict[r_key] = f"@@@LINK={primary_hw}"
                
    # 3. Write records to mdx.txt
    print(f"Total MDX records to write: {len(final_mdx_dict)}")
    
    with open(mdx_file, 'w', encoding='utf-8') as f:
        # Sort keys to make the file structured and predictable
        for term in sorted(final_mdx_dict.keys()):
            content = final_mdx_dict[term]
            f.write(f"{term}\n")
            f.write(f"{content}\n")
            f.write("</>\n")
            
    print(f"Successfully generated MDX dictionary text file: {mdx_file}")

if __name__ == '__main__':
    main()
