#!/usr/bin/env python3
# -*- coding: utf-8 -*-

import os
import sys
import gzip
import shutil
import subprocess
from datetime import datetime, timedelta
from pathlib import Path

PROJECT_ROOT = Path(__file__).resolve().parent.parent
MYSQLDUMP = PROJECT_ROOT / "bin" / "mysqldump.exe"


def load_dotenv(dotenv_path: Path) -> None:
    if not dotenv_path.exists():
        return
    for line in dotenv_path.read_text(encoding="utf-8").splitlines():
        line = line.strip()
        if not line or line.startswith("#") or "=" not in line:
            continue
        k, v = line.split("=", 1)
        k = k.strip()
        v = v.strip().strip('"').strip("'")
        os.environ.setdefault(k, v)

def require_env(name: str) -> str:
    v = os.getenv(name)
    if not v:
        raise SystemExit(f"Chybí proměnná {name} (dej ji do .env nebo env).")
    return v

def run(cmd: list[str], *, cwd: Path | None = None) -> None:
    # pro ladění si můžeš odkomentovat print(cmd)
    p = subprocess.run(cmd, cwd=str(cwd) if cwd else None)
    if p.returncode != 0:
        raise SystemExit(f"Příkaz selhal (exit={p.returncode}): {' '.join(cmd)}")

def main() -> None:
    here = Path(__file__).resolve().parent
    load_dotenv(here / ".env")

    host = require_env("KB_MYSQL_HOST")
    port = require_env("KB_MYSQL_PORT")
    user = require_env("KB_MYSQL_USER")
    password = require_env("KB_MYSQL_PASSWORD")
    db = require_env("KB_MYSQL_DB")

    backup_dir = Path(os.getenv("KB_BACKUP_DIR", "./backups")).resolve()
    keep_days = int(os.getenv("KB_KEEP_DAYS", "30"))

    backup_dir.mkdir(parents=True, exist_ok=True)

    ts = datetime.now().strftime("%Y-%m-%d_%H-%M-%S")
    sql_path = backup_dir / f"kanboard_{db}_{ts}.sql"
    gz_path = backup_dir / f"{sql_path.name}.gz"

    # Bezpečně: vytvoříme dočasný mysql config soubor, aby heslo nebylo v "ps"
    cnf_path = backup_dir / f".mysql_{db}_{ts}.cnf"
    cnf_path.write_text(
        "[client]\n"
        f"host={host}\n"
        f"port={port}\n"
        f"user={user}\n"
        f"password={password}\n",
        encoding="utf-8"
    )
    try:
        # omezit práva (na Linuxu/Unraid ok; na Windows to ignoruj)
        try:
            os.chmod(cnf_path, 0o600)
        except Exception:
            pass

        # Mysqldump – kompletní pro obnovu
        dump_cmd = [
            str(MYSQLDUMP),
            f"--defaults-extra-file={str(cnf_path)}",
            "--single-transaction",
            "--routines",
            "--triggers",
            "--events",
            "--hex-blob",
            "--default-character-set=utf8mb4",
            "--set-gtid-purged=OFF",
            "--databases", db,
        ]

        print(f"[OK] Dělám dump DB '{db}' -> {gz_path}")
        # Dump do .sql a rovnou gzip
        with subprocess.Popen(dump_cmd, stdout=subprocess.PIPE) as proc:
            if proc.stdout is None:
                raise SystemExit("Nepodařilo se získat stdout z mysqldump.")
            with gzip.open(gz_path, "wb", compresslevel=6) as gz:
                shutil.copyfileobj(proc.stdout, gz)
            rc = proc.wait()
            if rc != 0:
                raise SystemExit(f"mysqldump selhal (exit={rc}).")

        # Malá kontrola velikosti
        size = gz_path.stat().st_size
        if size < 200:  # hodně hrubé
            raise SystemExit(f"Dump je podezřele malý ({size} B) – něco je špatně.")

        # Retence
        cutoff = datetime.now() - timedelta(days=keep_days)
        for f in backup_dir.glob("kanboard_*_*.sql.gz"):
            try:
                if datetime.fromtimestamp(f.stat().st_mtime) < cutoff:
                    f.unlink(missing_ok=True)
            except Exception:
                pass

        print(f"[OK] Hotovo. Velikost: {size/1024/1024:.2f} MB")

    finally:
        try:
            cnf_path.unlink(missing_ok=True)
        except Exception:
            pass

if __name__ == "__main__":
    main()
