# retoor <retoor@molodetz.nl>

import asyncio
from datetime import datetime, timezone
from pathlib import Path
import pytest
from devplacepy.database import init_db, get_table, refresh_snapshot
from devplacepy import project_files
from devplacepy.services.jobs import queue
from devplacepy.services.jobs.fork_service import ForkService
from tests.conftest import run_async
@pytest.fixture(autouse=True)
def _init_db_fork_jobs():
    init_db()
    yield
@pytest.fixture
def fork_env(tmp_path, monkeypatch):
    monkeypatch.setattr(
        "devplacepy.services.jobs.fork_service.FORK_STAGING_DIR", tmp_path / "staging"
    )
    monkeypatch.setattr("devplacepy.project_files.PROJECT_FILES_DIR", tmp_path / "pf")
    yield tmp_path
    jobs = get_table("jobs")
    for row in list(jobs.find(kind="fork")):
        jobs.delete(uid=row["uid"])
    projects = get_table("projects")
    files = get_table("project_files")
    for project in list(projects.find()):
        if str(project.get("user_uid", "")).startswith("forktest-owner"):
            for node in list(files.find(project_uid=project["uid"])):
                files.delete(uid=node["uid"])
            projects.delete(uid=project["uid"])
    for node in list(files.find()):
        if str(node.get("project_uid", "")).startswith("forktest"):
            files.delete(uid=node["uid"])
    forks = get_table("project_forks")
    for relation in list(forks.find()):
        if str(relation.get("forked_by_uid", "")).startswith("forktest-owner"):
            forks.delete(uid=relation["uid"])
    users = get_table("users")
    for user in list(users.find()):
        if str(user.get("uid", "")).startswith("forktest-owner"):
            users.delete(uid=user["uid"])
_counter_fork_jobs = [0]
def _make_source_project(*, is_private=False, binary=False):
    _counter_fork_jobs[0] += 1
    pid = f"forktest-{_counter_fork_jobs[0]}"
    owner_uid = f"forktest-owner-{_counter_fork_jobs[0]}"
    user = {"uid": owner_uid, "username": f"forktester{_counter_fork_jobs[0]}"}
    get_table("users").insert(
        {"uid": owner_uid, "username": user["username"], "xp": 0, "level": 1}
    )
    get_table("projects").insert(
        {
            "deleted_at": None,
            "deleted_by": None,
            "uid": pid,
            "user_uid": owner_uid,
            "slug": f"{pid}-source",
            "title": "Source Project",
            "description": "the original",
            "project_type": "software",
            "platforms": "linux",
            "status": "Released",
            "is_private": 1 if is_private else 0,
            "read_only": 0,
            "stars": 0,
            "created_at": datetime.now(timezone.utc).isoformat(),
        }
    )
    project_files.write_text_file(pid, user, "README.md", "# hello\nworld")
    project_files.write_text_file(pid, user, "src/app.py", "print(1)\n")
    if binary:
        project_files.store_upload(pid, user, "assets", "logo.bin", bytes(range(256)))
    return pid, owner_uid
def _tree(directory):
    root = Path(directory)
    out = {}
    for path in sorted(root.rglob("*")):
        if path.is_file():
            out[path.relative_to(root).as_posix()] = path.read_bytes()
    return out
def _process_fork_jobs():
    async def drive():
        svc = ForkService()
        for _ in range(400):
            await svc.run_once()
            refresh_snapshot()
            pending = [
                r
                for r in get_table("jobs").find(kind="fork")
                if r["status"] in ("pending", "running")
            ]
            if not pending and not svc._inflight:
                return
            await asyncio.sleep(0.05)

    run_async(drive())
def _enqueue(source_uid, owner_uid, title="My Fork"):
    return queue.enqueue(
        "fork",
        {"source_project_uid": source_uid, "title": title, "forked_by_uid": owner_uid},
        "user",
        owner_uid,
        title,
    )


def test_fork_status_http_unknown_returns_404(app_server):
    import requests
    from tests.conftest import BASE_URL
    r = requests.get(f"{BASE_URL}/forks/nonexistent-uid")
    assert r.status_code == 404
