# retoor <retoor@molodetz.nl>

from datetime import datetime, timezone
from devplacepy.content import (
    is_owner,
    canonical_redirect,
    first_image_url,
    enrich_items,
)
from devplacepy.database import get_table, get_users_by_uids
from devplacepy.utils import generate_uid
import time
import pytest
import requests
from tests.conftest import BASE_URL
from devplacepy.database import get_table
from devplacepy.utils import clear_user_cache
from devplacepy import project_files
from devplacepy.project_files import ProjectFileError
from devplacepy.services.devii.actions.dispatcher import (
    confirmation_error,
    _is_confirmed,
)
_counter_project_visibility = [0]
def _signup_project_visibility():
    _counter_project_visibility[0] += 1
    name = f"pv{int(time.time() * 1000)}{_counter_project_visibility[0]}"
    session = requests.Session()
    session.post(
        f"{BASE_URL}/auth/signup",
        data={
            "username": name,
            "email": f"{name}@t.dev",
            "password": "secret123",
            "confirm_password": "secret123",
        },
        allow_redirects=True,
    )
    row = get_table("users").find_one(username=name)
    return name, row["uid"], row["api_key"]
def _make_admin_project_visibility():
    name, uid, key = _signup_project_visibility()
    get_table("users").update({"uid": uid, "role": "Admin"}, ["uid"])
    clear_user_cache(uid)
    return name, uid, key
def _h_project_visibility(key=None):
    headers = {"Accept": "application/json"}
    if key:
        headers["X-API-KEY"] = key
    return headers
def _create_project_project_visibility(key, title, is_private=False):
    data = {
        "title": title,
        "description": "visibility test",
        "project_type": "software",
        "status": "In Development",
    }
    if is_private:
        data["is_private"] = "on"
    r = requests.post(f"{BASE_URL}/projects/create", headers=_h_project_visibility(key), data=data)
    assert r.status_code == 200, r.text
    return r.json()["data"]
def _project_uid(slug):
    return get_table("projects").find_one(slug=slug)["uid"]
def _write_project_visibility(key, slug, path, content):
    return requests.post(
        f"{BASE_URL}/projects/{slug}/files/write",
        headers=_h_project_visibility(key),
        data={"path": path, "content": content},
        allow_redirects=False,
    )
def _set_private(key, slug, value):
    return requests.post(
        f"{BASE_URL}/projects/{slug}/private",
        headers=_h_project_visibility(key),
        data={"value": 1 if value else 0},
        allow_redirects=False,
    )
def _set_readonly(key, slug, value):
    return requests.post(
        f"{BASE_URL}/projects/{slug}/readonly",
        headers=_h_project_visibility(key),
        data={"value": 1 if value else 0},
        allow_redirects=False,
    )
def _list_slugs(key=None, user_uid=None):
    params = {"user_uid": user_uid} if user_uid else None
    r = requests.get(f"{BASE_URL}/projects", headers=_h_project_visibility(key), params=params)
    return [p["slug"] for p in r.json()["projects"]]


def test_is_owner_matches_user_uid():
    assert is_owner({"user_uid": "u1"}, {"uid": "u1"}) is True
    assert is_owner({"user_uid": "u1"}, {"uid": "u2"}) is False
    assert is_owner(None, {"uid": "u1"}) is False
    assert is_owner({"user_uid": "u1"}, None) is False


def test_canonical_redirect_when_slug_differs():
    item = {"slug": "abcd1234-title", "uid": "abcd1234"}
    assert canonical_redirect("posts", item, "abcd1234-title") is None
    response = canonical_redirect("posts", item, "abcd1234")
    assert response is not None
    assert response.status_code == 301
    assert response.headers["location"] == "/posts/abcd1234-title"


def test_first_image_url_prefers_inline():
    assert first_image_url({"image": "pic.png"}, None) == "/static/uploads/pic.png"


def test_first_image_url_uses_first_image_attachment():
    item = {"image": None}
    attachments = [{"is_image": False, "url": "/a"}, {"is_image": True, "url": "/b"}]
    assert first_image_url(item, attachments) == "/b"


def test_first_image_url_none_when_absent():
    assert first_image_url({}, []) is None


def test_enrich_items_attaches_author_and_extras(local_db):
    uid = generate_uid()
    username = f"enrich_{uid[:8]}"
    get_table("users").insert(
        {
            "uid": uid,
            "username": username,
            "email": f"{username}@t.dev",
            "created_at": datetime.now(timezone.utc).isoformat(),
        }
    )
    item_uid = generate_uid()
    items = [
        {
            "uid": item_uid,
            "user_uid": uid,
            "created_at": datetime.now(timezone.utc).isoformat(),
        }
    ]
    authors = get_users_by_uids([uid])
    enriched = enrich_items(
        items,
        "post",
        authors,
        extra_maps={"comment_count": {item_uid: 4}, "flag": lambda item: "ok"},
    )
    entry = enriched[0]
    assert entry["post"] is items[0]
    assert entry["author"]["username"] == username
    assert entry["time_ago"] == "just now"
    assert entry["my_vote"] == 0
    assert entry["comment_count"] == 4
    assert entry["flag"] == "ok"


def test_readonly_action_requires_confirmation():
    assert confirmation_error("project_set_readonly", {}) is not None
    assert confirmation_error("project_set_readonly", {"confirm": "false"}) is not None
    assert confirmation_error("project_set_readonly", {"confirm": "true"}) is None


def test_private_action_requires_confirmation():
    assert confirmation_error("project_set_private", {"value": "true"}) is not None
    assert confirmation_error("project_set_private", {"value": "true", "confirm": "true"}) is None
    assert confirmation_error("vote", {}) is None


def test_is_confirmed_accepts_common_truthy():
    assert _is_confirmed({"confirm": True})
    assert _is_confirmed({"confirm": "yes"})
    assert not _is_confirmed({"confirm": ""})
    assert not _is_confirmed({})


def test_delete_actions_require_confirmation():
    assert confirmation_error("project_delete_file", {"path": "a.py"}) is not None
    assert confirmation_error("project_delete_file", {"path": "a.py", "confirm": "true"}) is None
    assert confirmation_error("delete_project", {"project_slug": "p"}) is not None
    assert confirmation_error("delete_project", {"project_slug": "p", "confirm": "true"}) is None


def test_container_delete_requires_confirmation_but_not_other_actions():
    assert confirmation_error("container_instance_action", {"action": "delete"}) is not None
    assert confirmation_error("container_instance_action", {"action": "restart"}) is None
    assert confirmation_error("container_instance_action", {"action": "start"}) is None


def test_destructive_container_exec_requires_confirmation():
    assert confirmation_error("container_exec", {"command": "rm -f /app/cms/cms.db"}) is not None
    assert confirmation_error("container_exec", {"command": "sudo rm -rf /app"}) is not None
    assert confirmation_error("container_exec", {"command": "find . -delete"}) is not None
    assert confirmation_error("container_exec", {"command": "echo x > /etc/hosts"}) is not None
    assert (
        confirmation_error("container_exec", {"command": "rm -rf /app", "confirm": "true"})
        is None
    )


def test_benign_container_exec_runs_without_confirmation():
    assert confirmation_error("container_exec", {"command": "pip install requests"}) is None
    assert confirmation_error("container_exec", {"command": "ls -la /app"}) is None
    assert confirmation_error("container_exec", {"command": "grep -rm 5 foo ."}) is None
