# -*- coding: utf-8 -*-
"""把已生成的《软件测试课程设计》教案内容填进学院教案模板。

模板：_tpl/模板.docx（由 广东金融学院课程教案模板.doc 转换而来）
输出：广东金融学院课程教案（软件测试课程设计-周宇文）.docx
规则：
  - 保留模板的标题块、字体（宋体/五号）与字段顺序；
  - 模板中"（五号宋体）"等填写说明一律去掉，换成真实内容；
  - 每次课按模板字段填充：教学重点／教学难点／教学内容（含学习目标与知识点大纲）／
    教学组织（含教学方式、案例讨论、课堂组织、课程思政设计）／作业布置／
    本次课推荐和参考文献／本次课实践教学设计／课后自我总结分析；
  - 16 次课逐次排布，综合实践课（第 16 次）同样处理。
"""
import copy
import os
import re
import sys

from docx import Document
from docx.text.paragraph import Paragraph

BASE = os.path.dirname(os.path.abspath(__file__))
sys.path.insert(0, BASE)

import importlib.util

def _load(name, path):
    spec = importlib.util.spec_from_file_location(name, path)
    mod = importlib.util.module_from_spec(spec)
    spec.loader.exec_module(mod)
    return mod

G = _load('gen', os.path.join(BASE, '_gen_教学文件.py'))
C, SESSIONS = G.C, G.SESSIONS
CN = '一二三四五六七八九十'


def set_text(p, text):
    if not p.runs:
        p.add_run(text)
        return
    p.runs[0].text = text
    for r in p.runs[1:]:
        r.text = ''


def session_blocks(s):
    """按模板字段生成某次课的文字块：[(是否加粗, 文本), ...]"""
    out = [('第 %d 次课   %d学时' % (s['no'], 2), True)]
    out.append(('本次课教学重点：', True))
    out += [(x, False) for x in s['key']]
    out.append(('本次课教学难点：', True))
    out += [(x, False) for x in s['hard']]

    out.append(('本次课教学内容：', True))
    out.append(('%s　%s' % (s['chapter'], s['title']), False))
    out.append(('学习目标：' + '；'.join(s['goal']) + '。', False))
    outline = G.chapter_outline(s)
    if outline:
        idx = 0
        for kind, text in outline:
            if kind == 'p':                        # 知识点标题（去掉原有编号，避免"一、1."）
                title = re.sub(r'^\s*\d+(\.\d+)*\s*[、\.．]?\s*', '', text).strip()
                out.append(('%s、%s' % (CN[idx] if idx < len(CN) else str(idx + 1), title), False))
                idx += 1
            else:                                  # 知识点下的要点
                out.append(('　　· ' + text, False))
    else:
        out += [(x, False) for x in s['detail']]

    org = ['教学方式：%s（支撑%s）' % (s['method'], s['support']),
           '案例讨论：' + s['case']]
    org += ['%d、%s' % (i, x) for i, x in enumerate(s['org'], 1)]
    sz = None
    try:
        from _szdesign import SZ_DESIGN
        sz = SZ_DESIGN.get(s['no'])
    except Exception:
        sz = None
    if sz:
        dim, carrier, how, ev = sz
        org.append('课程思政设计——思政维度：%s' % dim)
        org.append('　　融入载体：%s' % carrier)
        org.append('　　课堂实施：%s' % how)
        org.append('　　评价观测点：%s' % ev)
    out.append(('教学组织（含课堂教学方法、辅助手段、师生互动、时间分配、板书设计、重点如何突出、难点如何解决等）：', True))
    out += [(x, False) for x in org]

    out.append(('作业布置：', True))
    out += [('%d、%s' % (i, x), False) for i, x in enumerate(s['hw'], 1)]

    out.append(('本次课推荐和参考文献', True))
    out += [('%d、%s' % (i, x), False) for i, x in enumerate(C['refs'][:5], 1)]

    out.append(('本次课实践教学设计：', True))
    out += [('%d、%s' % (i, x), False) for i, x in enumerate(s['practice'], 1)]

    out.append(('课后自我总结分析：', True))
    out.append(('根据课堂提问、实验完成情况与作业反馈，记录学生易错点与薄弱环节，作为下次课复习、例题选择与个别辅导的依据。', False))
    return out


def main():
    tpl = os.path.join(BASE, '_tpl', '模板.docx')
    doc = Document(tpl)
    paras = doc.paragraphs

    # 1) 标题块
    header = {
        '课程名称：': '课程名称：' + C['name'],
        '课程代码：': '课程代码：' + C['code'],
        '开课单位：': '开课单位：' + C['college'],
        '制定人：': '制定人：' + C['teacher'],
        '审核人：': '审核人：' + C['reviewer'],
        '制定时间：': '制定时间：' + C['date'],
    }
    for p in paras:
        t = p.text.strip()
        for k, v in header.items():
            if t.startswith(k.strip()):
                set_text(p, v)

    for p in paras:
        t = p.text.strip()
        if t.startswith('一、课程简介'):
            set_text(p, '一、课程简介')
        elif t.startswith('二、教学目的与教学要求'):
            set_text(p, '二、教学目的与教学要求：')

    # 2) 一、课程简介 与 二、教学目的与教学要求
    refs_txt = '；'.join(C['refs'][:8])
    fill = {
        '课程类别：': '课程类别：' + C['nature'],
        '授课对象：': '授课对象：本科　' + C['major'],
        '学时与学分：': '学时与学分：%d学时，%d学分' % (C['hours'], C['credits']),
        '使用教材：': '使用教材：' + C['textbook'],
        '参考教材：': '参考教材：' + refs_txt,
    }
    for p in paras:
        t = p.text.strip()
        for k, v in fill.items():
            if t.startswith(k):
                set_text(p, v)

    aim = ('性质：%s\n目的：%s\n任务：%s' % (
        '本课程是软件工程与软件测试交叉的实践性课程，面向软件测试岗位能力培养，是计算机类专业的专业课程。',
        C['aim'],
        '完成软件测试基本理论与方法的学习与实验；以一个具体软件系统为对象完成课程设计项目，包括测试需求分析、测试计划、测试用例设计、测试执行、缺陷报告与测试总结，并进行项目答辩。'))
    for p in paras:
        if p.text.strip().startswith('×××大约200字'):
            set_text(p, aim)

    # 3) 定位模板里的"次课"原型块，并在其后插入 16 次课内容
    start = end = None
    for i, p in enumerate(paras):
        if p.text.strip().startswith('第 ×× 次课'):
            start = i
        if start is not None and p.text.strip().startswith('（教案一律使用A4纸打印）'):
            end = i
            break
    if start is None or end is None:
        raise SystemExit('未找到模板中的次课原型块或结尾说明')
    proto_head = paras[start]
    proto_body = None
    for p in paras[start + 1:end]:
        if p.text.strip() and not p.runs[0].font.bold:
            proto_body = p
            break
    if proto_body is None:
        proto_body = paras[start + 1]

    note_p = paras[end]
    for s in SESSIONS:
        for text, bold in session_blocks(s):
            proto = proto_head if bold else proto_body
            new_el = copy.deepcopy(proto._p)
            note_p._p.addprevious(new_el)
            para = Paragraph(new_el, note_p._parent)
            set_text(para, text)

    # 4) 删除原来的原型块
    for p in paras[start:end]:
        p._p.getparent().remove(p._p)

    out = os.path.join(BASE, '广东金融学院课程教案（软件测试课程设计-周宇文）.docx')
    doc.save(out)
    print('已生成：%s' % out)
    print('段落数：%d' % len(Document(out).paragraphs))
    return 0


if __name__ == '__main__':
    sys.exit(main())
