#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""将《需求澄清问题清单》的 Markdown 表格导出为 .xlsx。

纯 Python 标准库实现（仅用 zipfile / xml），无需 openpyxl 或联网，
适配公司内网 / 信创环境。

用法:
    python3 export_to_excel.py 清单.md                 # 输出 清单.xlsx
    python3 export_to_excel.py 清单.md -o 澄清清单.xlsx
    cat 清单.md | python3 export_to_excel.py -          # 从标准输入读取

行为:
    读取输入中的第一张 Markdown 表格（以 | 分隔的行），
    将其原样写入一个 .xlsx 工作表（单元格用 inlineStr，兼容 Excel / WPS / LibreOffice）。
"""

import argparse
import os
import re
import sys
import zipfile

_SEP_CELL = re.compile(r"^:?-+:?$")


def parse_markdown_table(text):
    """从文本中提取第一张 Markdown 表格，返回二维字符串列表（含表头行）。"""
    rows = []
    in_table = False
    for raw in text.splitlines():
        line = raw.strip()
        if line.startswith("|"):
            in_table = True
            cells = [c.strip() for c in line.strip("|").split("|")]
            # 跳过分隔行，如 | --- | :--: |
            if cells and all(_SEP_CELL.match(c or "-") for c in cells):
                continue
            rows.append(cells)
        elif in_table:
            # 表格结束（遇到第一张表之后的非表格行）
            break
    return rows


def _col_letter(idx):
    """0 -> A, 25 -> Z, 26 -> AA ..."""
    letters = ""
    idx += 1
    while idx:
        idx, rem = divmod(idx - 1, 26)
        letters = chr(65 + rem) + letters
    return letters


def _xml_escape(value):
    return (
        str(value)
        .replace("&", "&amp;")
        .replace("<", "&lt;")
        .replace(">", "&gt;")
        .replace('"', "&quot;")
        .replace("'", "&apos;")
    )


def _build_sheet_xml(rows):
    parts = [
        '<?xml version="1.0" encoding="UTF-8" standalone="yes"?>',
        '<worksheet xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main">',
        "<sheetData>",
    ]
    for r_idx, row in enumerate(rows, start=1):
        parts.append('<row r="%d">' % r_idx)
        for c_idx, cell in enumerate(row):
            ref = "%s%d" % (_col_letter(c_idx), r_idx)
            text = _xml_escape(cell)
            parts.append(
                '<c r="%s" t="inlineStr"><is><t xml:space="preserve">%s</t></is></c>'
                % (ref, text)
            )
        parts.append("</row>")
    parts.append("</sheetData></worksheet>")
    return "".join(parts)


_CONTENT_TYPES = (
    '<?xml version="1.0" encoding="UTF-8" standalone="yes"?>'
    '<Types xmlns="http://schemas.openxmlformats.org/package/2006/content-types">'
    '<Default Extension="rels" ContentType="application/vnd.openxmlformats-package.relationships+xml"/>'
    '<Default Extension="xml" ContentType="application/xml"/>'
    '<Override PartName="/xl/workbook.xml" ContentType="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.main+xml"/>'
    '<Override PartName="/xl/worksheets/sheet1.xml" ContentType="application/vnd.openxmlformats-officedocument.spreadsheetml.worksheet+xml"/>'
    "</Types>"
)

_ROOT_RELS = (
    '<?xml version="1.0" encoding="UTF-8" standalone="yes"?>'
    '<Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships">'
    '<Relationship Id="rId1" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument" Target="xl/workbook.xml"/>'
    "</Relationships>"
)

_WORKBOOK = (
    '<?xml version="1.0" encoding="UTF-8" standalone="yes"?>'
    '<workbook xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main" '
    'xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships">'
    '<sheets><sheet name="澄清清单" sheetId="1" r:id="rId1"/></sheets>'
    "</workbook>"
)

_WORKBOOK_RELS = (
    '<?xml version="1.0" encoding="UTF-8" standalone="yes"?>'
    '<Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships">'
    '<Relationship Id="rId1" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/worksheet" Target="worksheets/sheet1.xml"/>'
    "</Relationships>"
)


def write_xlsx(rows, out_path):
    sheet_xml = _build_sheet_xml(rows)
    with zipfile.ZipFile(out_path, "w", zipfile.ZIP_DEFLATED) as zf:
        zf.writestr("[Content_Types].xml", _CONTENT_TYPES)
        zf.writestr("_rels/.rels", _ROOT_RELS)
        zf.writestr("xl/workbook.xml", _WORKBOOK)
        zf.writestr("xl/_rels/workbook.xml.rels", _WORKBOOK_RELS)
        zf.writestr("xl/worksheets/sheet1.xml", sheet_xml)


def main(argv=None):
    parser = argparse.ArgumentParser(description="将需求澄清清单的 Markdown 表格导出为 .xlsx")
    parser.add_argument("input", help="输入的 Markdown 文件路径；用 - 表示从标准输入读取")
    parser.add_argument("-o", "--output", help="输出的 .xlsx 路径（默认与输入同名）")
    args = parser.parse_args(argv)

    if args.input == "-":
        text = sys.stdin.read()
        default_out = "clarification.xlsx"
    else:
        with open(args.input, "r", encoding="utf-8") as fh:
            text = fh.read()
        default_out = os.path.splitext(args.input)[0] + ".xlsx"

    rows = parse_markdown_table(text)
    if not rows:
        sys.stderr.write("未在输入中找到 Markdown 表格（以 | 分隔的行）。\n")
        return 1

    out_path = args.output or default_out
    write_xlsx(rows, out_path)
    sys.stdout.write("已导出 %d 行到 %s\n" % (len(rows), out_path))
    return 0


if __name__ == "__main__":
    raise SystemExit(main())
