#!/usr/bin/env python3

import re
import tempfile
import xml.etree.ElementTree as ET

from pathlib import Path
from zipfile import ZipFile
from urllib.parse import urlsplit, urlunsplit

import requests
from bs4 import BeautifulSoup


INPUT_DOCX = "Отчет.docx"
OUTPUT_DOCX = "Отчет_fixed.docx"

FIRST_NEW_SOURCE = 8
ACCESS_DATE = "30.05.2026"

NS = {
    "w": "http://schemas.openxmlformats.org/wordprocessingml/2006/main"
}


def normalize_url(url):
    url = url.strip()

    if "#:~:text=" in url:
        url = url.split("#:~:text=", 1)[0]

    parts = urlsplit(url)

    return urlunsplit((
        parts.scheme.lower(),
        parts.netloc.lower(),
        parts.path.rstrip("/"),
        "",
        ""
    ))


def get_title(url):
    try:
        response = requests.get(
            url,
            timeout=15,
            headers={
                "User-Agent": "Mozilla/5.0"
            }
        )

        response.raise_for_status()

        soup = BeautifulSoup(response.text, "html.parser")

        og = soup.find("meta", property="og:title")
        if og and og.get("content"):
            return " ".join(og["content"].split())

        meta = soup.find("meta", attrs={"name": "title"})
        if meta and meta.get("content"):
            return " ".join(meta["content"].split())

        if soup.title and soup.title.string:
            return " ".join(soup.title.string.split())

    except Exception as e:
        print(f"WARNING: {url}: {e}")

    return url


def main():
    with tempfile.TemporaryDirectory() as tmpdir:

        tmpdir = Path(tmpdir)

        with ZipFile(INPUT_DOCX) as archive:
            archive.extractall(tmpdir)

        document_xml = tmpdir / "word" / "document.xml"

        tree = ET.parse(document_xml)
        root = tree.getroot()

        url_to_index = {}
        index_to_url = {}

        next_index = FIRST_NEW_SOURCE

        #
        # Первый проход:
        # собираем все URL и выдаем номера
        #
        for node in root.findall(".//w:instrText", NS):

            text = "".join(node.itertext())

            match = re.search(r'HYPERLINK\s+"([^"]+)"', text)

            if not match:
                continue

            url = normalize_url(match.group(1))

            if url in url_to_index:
                continue

            url_to_index[url] = next_index
            index_to_url[next_index] = url

            next_index += 1

        print("\n=== URL -> INDEX ===\n")

        for index in sorted(index_to_url):
            print(f"[{index}] {index_to_url[index]}")

        print()

        #
        # Второй проход:
        # меняем номера ссылок
        #
        current_url = None
        waiting_for_text = False
        replaced_count = 0

        for elem in root.iter():

            tag = elem.tag

            if tag.endswith("instrText"):

                text = "".join(elem.itertext())

                match = re.search(
                    r'HYPERLINK\s+"([^"]+)"',
                    text
                )

                if match:
                    current_url = normalize_url(match.group(1))
                    waiting_for_text = True

                continue

            if not waiting_for_text:
                continue

            if not tag.endswith("t"):
                continue

            if elem.text is None:
                continue

            if not re.match(r"\[\d+\]", elem.text.strip()):
                continue

            new_index = url_to_index[current_url]

            old_text = elem.text

            elem.text = f"[{new_index}]"

            print(
                f"{old_text} -> {elem.text} : {current_url}"
            )

            replaced_count += 1

            waiting_for_text = False
            current_url = None

        print()
        print(f"Replaced links: {replaced_count}")
        print()

        tree.write(
            document_xml,
            encoding="utf-8",
            xml_declaration=True
        )

        with ZipFile(OUTPUT_DOCX, "w") as out_zip:

            for file in tmpdir.rglob("*"):

                if file.is_dir():
                    continue

                out_zip.write(
                    file,
                    file.relative_to(tmpdir)
                )

        print(f"Saved: {OUTPUT_DOCX}")

        #
        # Формируем список литературы
        #
        print("\n=== SOURCES ===\n")

        for index in sorted(index_to_url):

            url = index_to_url[index]

            title = get_title(url)

            print(
                f"{index}. "
                f"{title} "
                f"(дата обращения: {ACCESS_DATE}). "
                f"Режим доступа - {url}"
            )


if __name__ == "__main__":
    main()



