import os
from datetime import datetime
from bs4 import BeautifulSoup
from docx import Document
from docx.shared import Pt
from docx.enum.text import WD_ALIGN_PARAGRAPH, WD_BREAK
from docx.shared import RGBColor
from docx.oxml.ns import qn
from docx.oxml import OxmlElement
from DCbackend.settings import MEDIA_ROOT
# 添加标题和书签
def add_title_with_bookmark(doc, text, style, bookmark_id):
    paragraph = doc.add_paragraph(text, style=style)

    run = paragraph.add_run()
    tag = run._r
    start = OxmlElement('w:bookmarkStart')
    start.set(qn('w:id'), str(bookmark_id))
    start.set(qn('w:name'), text)
    tag.append(start)

    tr = OxmlElement('w:r')
    tr.text = ''
    tag.append(tr)

    end = OxmlElement('w:bookmarkEnd')
    end.set(qn('w:id'), str(bookmark_id))
    end.set(qn('w:name'), text)
    tag.append(end)




# 获取文档文件名称
def getDocxFileName():
    date = datetime.now().strftime("%Y%m%d%H%M%S")
    fileName = "output.docx"
    filename = f"{date}_{fileName}"
    path = os.path.join(MEDIA_ROOT, filename)
    return path



def saveDocFile(title,htmlContent):
    doc = Document()


    # 标记目录的位置
    soup = BeautifulSoup(htmlContent, 'html.parser')
    paragraphs = soup.find_all(['h1'])
    # 将HTML内容转换为Word文档
    bookMarkId = 0
    if paragraphs:
        doc.add_paragraph(title)
        doc.add_paragraph("目录")
        catalog_p = doc.add_paragraph('')

        for p in paragraphs:
            text = p.get_text()
            style = p.name
            if style.startswith('h1'):
                # 添加标题
                bookMarkId=bookMarkId+1
                add_title_with_bookmark(doc, text, style='Heading 1', bookmark_id=bookMarkId)
            else:
                doc.add_paragraph(text)
    else:
        paragraphs = soup.find_all(['div'])
        for paragraph in paragraphs:
            doc.add_paragraph(paragraph.getText())

    if bookMarkId>0:
        # 开始写入目录
        # 目录开头增加值域，方便手动更新整个目录。自动生成的目录标题包含在值域中。
        toc_paragraph = catalog_p.insert_paragraph_before()  # 在标记的目录位置前添加段落
        r1 = toc_paragraph.add_run()
        toc_field = OxmlElement('w:fldChar')
        toc_field.set(qn('w:fldCharType'), 'begin')
        r1._r.append(toc_field)

        r2 = toc_paragraph.add_run()
        toc_field = OxmlElement('w:instrText')
        toc_field.set(qn('xml:space'), 'preserve')
        toc_field.text = 'TOC \\o "1-3" \\h \\z '
        r2._r.append(toc_field)

        r3 = toc_paragraph.add_run()
        toc_field = OxmlElement('w:fldChar')
        toc_field.set(qn('w:fldCharType'), 'separate')
        r3._r.append(toc_field)

        # 自动生成目录内容，不包含页码
        for paragraph in doc.paragraphs:
            if 'Heading' in paragraph.style.name:

                b = paragraph._element.findall('.//' + qn('w:bookmarkStart'))
                bookmark_name = b[0].get(qn('w:name'))
                text = paragraph.text
                level = int(paragraph.style.name[-1])
                # print(text, bookmark_name)

                toc_paragraph = catalog_p.insert_paragraph_before(style='Normal')
                # 二级标题设置缩进
                if level == 2:
                    toc_paragraph.paragraph_format.first_line_indent = Pt(24)

                # 设置制表符，可显示页码前的"…………"
                tabs = OxmlElement('w:tabs')
                tab1 = OxmlElement('w:tab')
                tab1.set(qn('w:val'), "left")
                tab1.set(qn('w:leader'), "dot")
                tab1.set(qn('w:pos'), "8400")
                tabs.append(tab1)
                toc_paragraph._p.pPr.append(tabs)
                # toc_paragraph若未设定style，toc_paragraph._p没有pPr属性，需注释前一句代码，使用以下语句
                # pPr = OxmlElement('w:pPr')
                # pPr.append(tabs)
                # toc_paragraph._p.append(pPr)

                hyperlink = OxmlElement('w:hyperlink')
                hyperlink.set(qn('w:anchor'), bookmark_name)
                hyperlink.set(qn('w:history'), '1')

                hr1 = OxmlElement('w:r')
                rPr = OxmlElement('w:rPr')
                rStyle = OxmlElement('w:rStyle')
                rStyle.set(qn('w:val'), "a4")
                rPr.append(rStyle)
                hr1.text = text
                hr1.append(rPr)
                hyperlink.append(hr1)

                hr2 = OxmlElement('w:r')
                rPr = OxmlElement('w:rPr')
                fldChar = OxmlElement('w:fldChar')
                fldChar.set(qn('w:fldCharType'), 'begin')
                hr2.append(rPr)
                hr2.append(fldChar)
                hyperlink.append(hr2)

                hr3 = OxmlElement('w:r')
                rPr = OxmlElement('w:rPr')
                instrText = OxmlElement('w:instrText')
                instrText.set(qn('xml:space'), 'preserve')
                instrText.text = ' PAGEREF {} \h '.format(bookmark_name)
                hr3.append(rPr)
                hr3.append(instrText)
                hyperlink.append(hr3)

                hr4 = OxmlElement('w:r')
                rPr = OxmlElement('w:rPr')
                fldChar = OxmlElement('w:fldChar')
                fldChar.set(qn('w:fldCharType'), 'separate')
                hr4.append(rPr)
                hr4.append(fldChar)
                hyperlink.append(hr4)

                hrt = OxmlElement('w:r')
                tab = OxmlElement('w:tab')
                hrt.append(tab)
                hyperlink.append(hrt)

                hr5 = OxmlElement('w:r')
                rPr = OxmlElement('w:rPr')
                hr5.text = ''
                hr5.append(rPr)
                hyperlink.append(hr5)

                hr6 = OxmlElement('w:r')
                rPr = OxmlElement('w:rPr')
                fldChar = OxmlElement('w:fldChar')
                fldChar.set(qn('w:fldCharType'), 'end')
                hr6.append(rPr)
                hr6.append(fldChar)
                hyperlink.append(hr6)

                toc_paragraph._p.append(hyperlink)

        # 目录结尾的值域
        toc_paragraph = catalog_p.insert_paragraph_before()
        r4 = toc_paragraph.add_run()
        toc_field = OxmlElement('w:fldChar')
        toc_field.set(qn('w:fldCharType'), 'end')
        r4._r.append(toc_field)
        # 分页
        break_page_p = catalog_p.insert_paragraph_before()
        break_page_p.add_run().add_break(WD_BREAK.PAGE)

    fileName=getDocxFileName()

    doc.save(fileName)

    return fileName