"""Daily configuration backup to Gitea — executed after CEO approval."""
from __future__ import annotations

import json
import os
import subprocess
from datetime import datetime, timezone
from pathlib import Path
from typing import Any

from app.db import execute, fetch_all, fetch_one

BACKUP_ROOT = Path(os.getenv("BACKUP_ROOT", "/data/backup-root"))
GITEA_REMOTE = os.getenv(
    "GITEA_BACKUP_REMOTE",
    "http://sysops:Foodlinkk%23SysOps2026@gitea:3001/aissa/foodlinkk-command-center.git",
)
GITEA_GIT_USER = os.getenv("GITEA_SYSOPS_USER", "sysops")
GITEA_GIT_EMAIL = os.getenv("GITEA_SYSOPS_EMAIL", "sysops@foodlinkk.local")
GITEA_GIT_NAME = os.getenv("GITEA_SYSOPS_NAME", "sysops")
GITEA_BRANCH = os.getenv("GITEA_BACKUP_BRANCH", "main")

BACKUP_PATHS = [
    "docker-compose.yml",
    ".env.example",
    "migrations",
    "monitoring",
    "cockpit/requirements.txt",
    "tools-api/requirements.txt",
    "deploy-all.sh",
    "README.md",
]


def _iso_now() -> str:
    return datetime.now(timezone.utc).isoformat()


def _run(cmd: list[str], cwd: Path | None = None, timeout: int = 120) -> dict[str, Any]:
    try:
        proc = subprocess.run(  # noqa: S603
            cmd,
            cwd=str(cwd) if cwd else None,
            capture_output=True,
            text=True,
            timeout=timeout,
            check=False,
        )
    except subprocess.TimeoutExpired:
        return {"ok": False, "error": "timeout", "cmd": cmd}
    except FileNotFoundError as exc:
        return {"ok": False, "error": str(exc), "cmd": cmd}
    return {
        "ok": proc.returncode == 0,
        "code": proc.returncode,
        "stdout": (proc.stdout or "").strip(),
        "stderr": (proc.stderr or "").strip(),
        "cmd": cmd,
    }


def _table_exists(name: str) -> bool:
    row = fetch_one(
        """
        SELECT EXISTS(
            SELECT 1 FROM information_schema.tables
            WHERE table_schema = 'public' AND table_name = %s
        ) AS ok
        """,
        (name,),
    )
    return bool(row and row.get("ok"))


def _record_backup(
    status: str,
    message: str,
    files_count: int = 0,
    commit_ref: str | None = None,
    approval_request_id: int | None = None,
    payload: dict | None = None,
) -> dict[str, Any] | None:
    if not _table_exists("config_backups"):
        return None
    row = fetch_one(
        """
        INSERT INTO config_backups (approval_request_id, commit_ref, files_count, status, message, payload)
        VALUES (%s, %s, %s, %s, %s, %s::jsonb)
        RETURNING id, created_at
        """,
        (
            approval_request_id,
            commit_ref,
            files_count,
            status,
            message,
            json.dumps(payload or {}),
        ),
    )
    return dict(row) if row else None


def list_backups(limit: int = 20) -> list[dict[str, Any]]:
    if not _table_exists("config_backups"):
        return []
    rows = fetch_all(
        "SELECT * FROM config_backups ORDER BY created_at DESC LIMIT %s",
        (max(1, min(limit, 100)),),
    )
    out = []
    for r in rows:
        item = dict(r)
        if hasattr(item.get("created_at"), "isoformat"):
            item["created_at"] = item["created_at"].isoformat()
        out.append(item)
    return out


def prepare_backup_manifest() -> dict[str, Any]:
    root = BACKUP_ROOT
    files: list[str] = []
    if root.exists():
        for rel in BACKUP_PATHS:
            p = root / rel
            if p.is_file():
                files.append(rel)
            elif p.is_dir():
                for fp in p.rglob("*"):
                    if fp.is_file() and not any(x in str(fp) for x in [".git", "__pycache__", ".pyc"]):
                        files.append(str(fp.relative_to(root)))
    return {
        "root": str(root),
        "root_exists": root.exists(),
        "files": sorted(files)[:500],
        "files_count": len(files),
        "paths_configured": BACKUP_PATHS,
        "generated_at": _iso_now(),
    }


def run_gitea_backup(approval_request_id: int | None = None) -> dict[str, Any]:
    from app.connectors.gitea_repo_sync import run_gitea_repo_sync

    return run_gitea_repo_sync(reason="approved_backup", approval_request_id=approval_request_id)
