"""
core/history.py — история запусков задач.

Хранится в data/db/history.sqlite. Записываем на finish/stop/crash задачи
достаточно для отчёта: тип, акк, когда, что со счётчиками.
"""
import json
import logging
import sqlite3
import threading
import time
from pathlib import Path
from typing import Optional

from config import DB_PATH

logger = logging.getLogger("telepush.history")

_HIST_PATH = Path(DB_PATH).parent / "history.sqlite"
_HIST_LOCK = threading.Lock()
_HIST_READY = False


def _init():
    global _HIST_READY
    if _HIST_READY:
        return
    try:
        _HIST_PATH.parent.mkdir(parents=True, exist_ok=True)
        conn = sqlite3.connect(str(_HIST_PATH), timeout=10)
        conn.execute("""
            CREATE TABLE IF NOT EXISTS runs(
                id INTEGER PRIMARY KEY AUTOINCREMENT,
                owner_id INTEGER NOT NULL,
                kind TEXT NOT NULL,
                phone TEXT,
                started_at REAL NOT NULL,
                finished_at REAL NOT NULL,
                status TEXT,
                total INTEGER DEFAULT 0,
                ok INTEGER DEFAULT 0,
                fail INTEGER DEFAULT 0,
                counts_json TEXT,
                note TEXT
            )
        """)
        conn.execute("CREATE INDEX IF NOT EXISTS runs_owner_time ON runs(owner_id, finished_at DESC)")
        conn.commit()
        conn.close()
        _HIST_READY = True
    except Exception as e:
        logger.warning("[history] init failed: %s", e)


def log_run(owner_id: int, kind: str, phone: str, started_at: float,
            status: str, counts: Optional[dict] = None, total: int = 0,
            note: str = ""):
    """Записывает итог задачи в историю."""
    _init()
    if not _HIST_READY:
        return
    counts = counts or {}
    try:
        ok = int(counts.get("sent") or counts.get("joined") or 0) + int(counts.get("already") or 0)
        fail = int(counts.get("failed") or 0) + int(counts.get("spamfilter") or 0) + \
               int(counts.get("no_rights") or 0) + int(counts.get("flood") or 0)
    except Exception:
        ok = fail = 0

    with _HIST_LOCK:
        try:
            conn = sqlite3.connect(str(_HIST_PATH), timeout=10)
            conn.execute(
                "INSERT INTO runs(owner_id,kind,phone,started_at,finished_at,status,total,ok,fail,counts_json,note) "
                "VALUES(?,?,?,?,?,?,?,?,?,?,?)",
                (int(owner_id), str(kind), str(phone or ""), float(started_at),
                 float(time.time()), str(status or ""), int(total or 0),
                 int(ok), int(fail),
                 json.dumps(counts, ensure_ascii=False), str(note or "")),
            )
            conn.commit()
            # Держим не более 500 записей на юзера — старые удаляем
            conn.execute(
                "DELETE FROM runs WHERE owner_id=? AND id NOT IN "
                "(SELECT id FROM runs WHERE owner_id=? ORDER BY finished_at DESC LIMIT 500)",
                (int(owner_id), int(owner_id)),
            )
            conn.commit()
            conn.close()
        except Exception as e:
            logger.debug("[history] log_run: %s", e)


def list_runs(owner_id: int, limit: int = 50):
    _init()
    if not _HIST_READY:
        return []
    with _HIST_LOCK:
        try:
            conn = sqlite3.connect(str(_HIST_PATH), timeout=10)
            conn.row_factory = sqlite3.Row
            rows = conn.execute(
                "SELECT kind,phone,started_at,finished_at,status,total,ok,fail,counts_json,note "
                "FROM runs WHERE owner_id=? ORDER BY finished_at DESC LIMIT ?",
                (int(owner_id), int(limit)),
            ).fetchall()
            conn.close()
            out = []
            for r in rows:
                out.append({
                    "kind": r["kind"], "phone": r["phone"],
                    "started_at": r["started_at"], "finished_at": r["finished_at"],
                    "status": r["status"], "total": r["total"],
                    "ok": r["ok"], "fail": r["fail"],
                    "counts": json.loads(r["counts_json"] or "{}"),
                    "note": r["note"],
                })
            return out
        except Exception as e:
            logger.debug("[history] list_runs: %s", e)
            return []
