import nasio
import re
import xml.etree.ElementTree as ET
import io
import platform
import os
from urllib.parse import urlparse
from dotenv import load_dotenv

load_dotenv()

SYNO_URL = os.getenv("SYNO_URL")
SYNO_USERNAME = os.getenv("SYNO_USERNAME")
SYNO_PASSWORD = os.getenv("SYNO_PASSWORD")
SYNO_PATH_VMIX = os.getenv("SYNO_PATH_VMIX")


def get_fqdn():
    system_name = platform.system()
    if system_name == "Linux":
        hostname = platform.node().lower()
        return f"https://{hostname}.tvstart.ru"
    return "http://127.0.0.1:8000"


FQDN = get_fqdn()


def rebuild_vmix_url(old_url: str, new_base_url: str, session_token: str) -> str:
    """
    Меняет URL вида:
    http://127.0.0.1:8000/vmix/session/OLDTOKEN/home-lineup
    на:
    https://hostname.tvstart.ru/vmix/session/NEWTOKEN/home-lineup
    """
    old_url = (old_url or "").strip()
    parsed = urlparse(old_url)
    path = parsed.path or ""

    match = re.match(r"^/vmix/session/[^/]+/(.+)$", path)
    if match:
        endpoint = match.group(1)
        return f"{new_base_url}/vmix/session/{session_token}/{endpoint}"

    # fallback: если структура другая, просто меняем host
    return re.sub(r"https?://[^/]+", new_base_url, old_url)


def change_vmix_datasource_urls(
    xml_data,
    new_base_url: str,
    session_token: str,
    match_id: str | int | None = None,
    operator_login: str | None = None,
) -> bytes:
    if isinstance(xml_data, dict):
        candidate = None

        for key in ("content", "data", "body", "text", "file", "bio"):
            if key in xml_data and xml_data[key] is not None:
                candidate = xml_data[key]
                break

        if candidate is None:
            raise TypeError(
                f"Unsupported xml_data dict structure. Keys: {list(xml_data.keys())}"
            )

        if isinstance(candidate, (bytes, bytearray)):
            raw_bytes = bytes(candidate)
        elif isinstance(candidate, str):
            raw_bytes = candidate.encode("utf-8")
        elif isinstance(candidate, io.IOBase) or hasattr(candidate, "read"):
            raw_bytes = candidate.read()
            try:
                candidate.seek(0)
            except Exception:
                pass
        else:
            raise TypeError(
                f"Unsupported xml_data payload inside dict: {type(candidate)}; "
                f"available keys: {list(xml_data.keys())}"
            )

    elif isinstance(xml_data, (bytes, bytearray)):
        raw_bytes = bytes(xml_data)

    elif isinstance(xml_data, str):
        raw_bytes = xml_data.encode("utf-8")

    elif isinstance(xml_data, io.IOBase) or hasattr(xml_data, "read"):
        raw_bytes = xml_data.read()
        try:
            xml_data.seek(0)
        except Exception:
            pass

    else:
        raise TypeError(f"Unsupported xml_data type: {type(xml_data)}")

    text = raw_bytes.decode("utf-8", errors="replace")
    root = ET.fromstring(text)

    for url_tag in root.findall(
        ".//datasource[@friendlyName='JSON']//instance//state/xml/url"
    ):
        old_url = (url_tag.text or "").strip()
        url_tag.text = rebuild_vmix_url(old_url, new_base_url, session_token)

    dynamic_settings = root.find(".//DynamicSettings")
    if dynamic_settings is None:
        dynamic_settings = ET.SubElement(root, "DynamicSettings")

    dynamic = dynamic_settings.find("Dynamic")
    if dynamic is None:
        dynamic = ET.SubElement(dynamic_settings, "Dynamic")


    def get_or_create_dynamic_value(index: int):
        values = dynamic.findall("DynamicValue")

        # гарантируем нужное количество
        while len(values) <= index:
            ET.SubElement(dynamic, "DynamicInput")
            ET.SubElement(dynamic, "DynamicValue")
            values = dynamic.findall("DynamicValue")

        return values[index]


    # value1 = session
    get_or_create_dynamic_value(0).text = str(session_token)

    # value2 = match_id
    get_or_create_dynamic_value(1).text = "" if match_id is None else str(match_id)

    # value4 = operator_login
    get_or_create_dynamic_value(3).text = "" if not operator_login else str(operator_login)

    return ET.tostring(root, encoding="utf-8", method="xml")



def build_vmix_project_bytes(
    session_token: str,
    match_id: str | int | None = None,
    operator_login: str | None = None,
) -> bytes:
    vmix_bio = nasio.load_bio(
        user=SYNO_USERNAME,
        password=SYNO_PASSWORD,
        nas_ip=SYNO_URL,
        nas_port="443",
        path=SYNO_PATH_VMIX,
    )

    edited_vmix = change_vmix_datasource_urls(
        vmix_bio,
        FQDN,
        session_token,
        match_id,
        operator_login,
    )

    if isinstance(edited_vmix, str):
        edited_vmix = edited_vmix.encode("utf-8")

    return edited_vmix


def build_vmix_filename(session_row) -> str:
    home = session_row[14].replace("«", "").replace("»", "")
    away = session_row[18].replace("«", "").replace("»", "")
    tour = session_row[10]
    date_str = session_row[9].strftime("%d%m%Y")
    filename = f"ЖФЛ_{home} VS {away}_{tour}_{date_str}.vmix"
    return filename