from __future__ import annotations

import os
import subprocess
from pathlib import Path

from core_db import CORE_ROOT

BASE_DIR = Path(__file__).resolve().parent
PYTHON = Path(os.getenv("ORIGUS_CORE_PYTHON", BASE_DIR / ".venv" / "bin" / "python"))
CONNECTOR_MODULE = "connectors.techexpert"
RUNTIME_DIR = CORE_ROOT / "runtime"
SYNC_LOG = RUNTIME_DIR / "techexpert_sync.log"
SYNC_PID = RUNTIME_DIR / "techexpert_sync.pid"

def _running_pid() -> int | None:
    if not SYNC_PID.exists():
        return None
    try:
        pid=int(SYNC_PID.read_text(encoding="utf-8").strip())
    except Exception:
        SYNC_PID.unlink(missing_ok=True); return None
    proc=Path(f"/proc/{pid}")
    if not proc.exists():
        SYNC_PID.unlink(missing_ok=True); return None
    try:
        stat=(proc/"stat").read_text(encoding="utf-8",errors="replace")
        rparen=stat.rfind(")")
        tail=stat[rparen+2:].split()
        if tail and tail[0]=="Z":
            SYNC_PID.unlink(missing_ok=True); return None
    except Exception:
        pass
    try:
        cmd=(proc/"cmdline").read_bytes().replace(b"\0",b" ").decode("utf-8",errors="replace")
        if "connectors.techexpert" not in cmd or " sync" not in f" {cmd}":
            SYNC_PID.unlink(missing_ok=True); return None
    except Exception:
        pass
    try:
        os.kill(pid,0); return pid
    except OSError:
        SYNC_PID.unlink(missing_ok=True); return None

def start_sync(document_slug: str | None = None) -> int:
    running=_running_pid()
    if running:
        raise RuntimeError(f"Синхронизация уже выполняется (PID {running}).")
    RUNTIME_DIR.mkdir(parents=True,exist_ok=True)
    cmd=[str(PYTHON),"-m",CONNECTOR_MODULE,"sync"]
    if document_slug:
        cmd += ["--document",document_slug]
    log=SYNC_LOG.open("a",encoding="utf-8")
    log.write(f"\n\n===== START {'ONE '+document_slug if document_slug else 'ALL'} =====\n")
    log.flush()
    proc=subprocess.Popen(
        cmd,cwd=str(BASE_DIR),stdout=log,stderr=subprocess.STDOUT,
        start_new_session=True,close_fds=True
    )
    SYNC_PID.write_text(str(proc.pid),encoding="utf-8")
    return proc.pid

def sync_state() -> dict:
    pid=_running_pid()
    tail=""
    if SYNC_LOG.exists():
        try:
            text=SYNC_LOG.read_text(encoding="utf-8",errors="replace")
            tail=text[-12000:]
        except Exception:
            pass
    return {"running":bool(pid),"pid":pid,"log_tail":tail}
