from __future__ import annotations

import json
import os
import subprocess
from pathlib import Path

import pytest


def _write_minimal_ph_root(ph_root: Path) -> None:
    ph_project_root = ph_root / ".project-handbook"
    config = ph_project_root / "config.json"
    config.parent.mkdir(parents=True, exist_ok=True)
    config.write_text(
        '{\n  "handbook_schema_version": 1,\n  "requires_ph_version": ">=0.0.1,<0.1.0",\n  "repo_root": "."\n}\n',
        encoding="utf-8",
    )

    (ph_project_root / "process" / "checks").mkdir(parents=True, exist_ok=True)
    (ph_project_root / "process" / "automation").mkdir(parents=True, exist_ok=True)
    (ph_project_root / "process" / "sessions" / "templates").mkdir(parents=True, exist_ok=True)

    (ph_project_root / "process" / "checks" / "validation_rules.json").write_text("{}", encoding="utf-8")
    (ph_project_root / "process" / "automation" / "system_scope_config.json").write_text(
        json.dumps({"routing_rules": {}}), encoding="utf-8"
    )
    (ph_project_root / "process" / "automation" / "reset_spec.json").write_text("{}", encoding="utf-8")


@pytest.mark.parametrize("scope", ["project", "system"])
def test_feature_status_updates_stage_and_date(tmp_path: Path, scope: str) -> None:
    _write_minimal_ph_root(tmp_path)

    create_env = dict(os.environ)
    create_env["PH_FAKE_TODAY"] = "2099-01-02"

    cmd = ["ph", "--root", str(tmp_path)]
    if scope == "system":
        cmd += ["--scope", "system"]
    cmd += ["--no-post-hook", "feature", "create", "--name", "feat-a"]
    created = subprocess.run(cmd, capture_output=True, text=True, env=create_env)
    assert created.returncode == 0

    status_env = dict(os.environ)
    status_env["PH_FAKE_TODAY"] = "2099-01-01"

    cmd = ["ph", "--root", str(tmp_path)]
    if scope == "system":
        cmd += ["--scope", "system"]
    cmd += ["--no-post-hook", "feature", "status", "--name", "feat-a", "--stage", "developing"]
    updated = subprocess.run(cmd, capture_output=True, text=True, env=status_env)
    assert updated.returncode == 0
    assert updated.stdout.strip() == "✅ Updated 'feat-a' stage to 'developing'"

    base = (tmp_path / ".project-handbook") if scope == "project" else (tmp_path / ".project-handbook" / "system")
    status_md = (base / "features" / "feat-a" / "status.md").read_text(encoding="utf-8")
    assert "Stage: developing" in status_md
    assert "date: 2099-01-01" in status_md


@pytest.mark.parametrize("scope", ["project", "system"])
def test_feature_status_not_found(tmp_path: Path, scope: str) -> None:
    _write_minimal_ph_root(tmp_path)

    env = dict(os.environ)
    env["PH_FAKE_TODAY"] = "2099-01-01"

    cmd = ["ph", "--root", str(tmp_path)]
    if scope == "system":
        cmd += ["--scope", "system"]
    cmd += ["--no-post-hook", "feature", "status", "--name", "missing", "--stage", "developing"]
    missing = subprocess.run(cmd, capture_output=True, text=True, env=env)
    assert missing.returncode == 1
    assert missing.stdout.strip() == "❌ Feature 'missing' not found"


def test_feature_status_project_scope_emits_pnpm_make_preamble_when_package_json_present(tmp_path: Path) -> None:
    _write_minimal_ph_root(tmp_path)
    (tmp_path / "package.json").write_text(
        '{\n  "name": "project-handbook",\n  "version": "0.0.0"\n}\n',
        encoding="utf-8",
    )

    create_env = dict(os.environ)
    create_env["PH_FAKE_TODAY"] = "2099-01-02"
    created = subprocess.run(
        ["ph", "--root", str(tmp_path), "--no-post-hook", "feature", "create", "--name", "feat-a"],
        capture_output=True,
        text=True,
        env=create_env,
    )
    assert created.returncode == 0

    status_env = dict(os.environ)
    status_env["PH_FAKE_TODAY"] = "2099-01-01"
    updated = subprocess.run(
        [
            "ph",
            "--root",
            str(tmp_path),
            "--no-post-hook",
            "feature",
            "status",
            "--name",
            "feat-a",
            "--stage",
            "developing",
        ],
        capture_output=True,
        text=True,
        env=status_env,
    )
    assert updated.returncode == 0

    expected_root = str(tmp_path.resolve())
    assert updated.stdout.splitlines() == [
        "",
        f"> project-handbook@0.0.0 ph {expected_root}",
        "> ph feature status --name feat-a --stage developing",
        "",
        "✅ Updated 'feat-a' stage to 'developing'",
    ]


def test_feature_status_not_found_emits_pnpm_make_preamble_when_package_json_present(tmp_path: Path) -> None:
    _write_minimal_ph_root(tmp_path)
    (tmp_path / "package.json").write_text(
        '{\n  "name": "project-handbook",\n  "version": "0.0.0"\n}\n',
        encoding="utf-8",
    )

    env = dict(os.environ)
    env["PH_FAKE_TODAY"] = "2099-01-01"
    missing = subprocess.run(
        [
            "ph",
            "--root",
            str(tmp_path),
            "--no-post-hook",
            "feature",
            "status",
            "--name",
            "missing",
            "--stage",
            "developing",
        ],
        capture_output=True,
        text=True,
        env=env,
    )
    assert missing.returncode == 1

    expected_root = str(tmp_path.resolve())
    assert missing.stdout.splitlines() == [
        "",
        f"> project-handbook@0.0.0 ph {expected_root}",
        "> ph feature status --name missing --stage developing",
        "",
        "❌ Feature 'missing' not found",
    ]
