from __future__ import annotations

import json
import os
import stat
import subprocess
import sys
from pathlib import Path

import pytest

from checkin_cli.nutrition_onboarding_cli import main
from checkin_cli.nutrition_onboarding_migration import (
    commit_legacy_migration,
    legacy_migration_preflight,
)
from checkin_cli.nutrition_restriction_kb import load_restriction_kb_template


def test_missing_status_is_concise_without_traceback(tmp_path: Path) -> None:
    result = subprocess.run(
        [
            sys.executable,
            "-m",
            "checkin_cli.nutrition_onboarding_cli",
            "status",
            "--profile-root",
            str(tmp_path),
            "--customer-key",
            "missing",
        ],
        check=False,
        capture_output=True,
        text=True,
    )

    assert result.returncode == 2
    assert result.stderr.strip() == "nutrition onboarding state not found"
    assert "Traceback" not in result.stderr


def test_seed_kb_requires_explicit_commit(
    tmp_path: Path,
    capsys,
) -> None:
    source = tmp_path / "template.json"
    source.write_text(json.dumps(load_restriction_kb_template()), encoding="utf-8")
    profile_root = tmp_path / "profile"
    common = [
        "seed-kb",
        "--profile-root",
        str(profile_root),
        "--source",
        str(source),
        "--owner-digest",
        "a" * 64,
        "--as-of",
        "2026-08-01",
    ]

    assert main(common) == 0
    dry = json.loads(capsys.readouterr().out)
    assert dry["committed"] is False
    assert not Path(dry["runtime_path"]).exists()

    assert main([*common, "--commit"]) == 0
    committed = json.loads(capsys.readouterr().out)
    assert committed["committed"] is True
    assert Path(committed["runtime_path"]).exists()


def test_legacy_migration_requires_exact_receipt_confirmation(
    tmp_path: Path,
    capsys,
) -> None:
    profile_root = tmp_path / "profile"
    registry_path = profile_root / "customers" / "registry.json"
    registry_path.parent.mkdir(parents=True)
    registry_path.write_text(
        json.dumps(
            {
                "customers": [
                    {
                        "customer_key": "legacy",
                        "enabled": True,
                        "nutrition_profile": {"status": "existing"},
                        "plan": {"weeks": []},
                    }
                ]
            }
        ),
        encoding="utf-8",
    )
    journal_path = profile_root / "data" / "customer-activation-journal.json"
    journal_path.parent.mkdir(parents=True)
    journal_path.write_text(
        json.dumps(
            {
                "version": 1,
                "state": "committed",
                "customer_id": "legacy",
                "transaction_id": "legacy-transaction",
            }
        ),
        encoding="utf-8",
    )
    registry_path.chmod(0o600)
    journal_path.chmod(0o600)
    registry_path.chmod(0o600)
    journal_path.chmod(0o600)
    common = [
        "--profile-root",
        str(profile_root),
        "--expected-enabled-customer",
        "legacy",
        "--owner-digest",
        "c" * 64,
    ]

    assert main(["migration-preflight", *common]) == 0
    preflight = json.loads(capsys.readouterr().out)
    assert preflight["customer_key"] == "legacy"
    assert len(preflight["activation_receipt_digest"]) == 64

    assert main(
        [
            "migration-commit",
            *common,
            "--confirm-activation-receipt-digest",
            preflight["activation_receipt_digest"],
        ]
    ) == 0
    committed = json.loads(capsys.readouterr().out)
    manifest_path = Path(committed["manifest_path"])
    assert manifest_path.exists()
    assert stat.S_IMODE(manifest_path.parent.stat().st_mode) == 0o700
    assert stat.S_IMODE(manifest_path.stat().st_mode) == 0o600

    escape_root = tmp_path / "escape-profile"
    (escape_root / "customers").mkdir(parents=True)
    (escape_root / "data").mkdir()
    (escape_root / "customers" / "registry.json").write_bytes(
        registry_path.read_bytes()
    )
    (escape_root / "data" / "customer-activation-journal.json").write_bytes(
        journal_path.read_bytes()
    )
    (escape_root / "customers" / "registry.json").chmod(0o600)
    (escape_root / "data" / "customer-activation-journal.json").chmod(0o600)
    outside = tmp_path / "outside-migrations"
    outside.mkdir()
    (escape_root / "data" / "migrations").symlink_to(
        outside,
        target_is_directory=True,
    )
    escaped_preflight = legacy_migration_preflight(
        profile_root=escape_root,
        expected_enabled_customer="legacy",
        owner_digest="c" * 64,
    )

    with pytest.raises(ValueError, match="symlink"):
        commit_legacy_migration(
            profile_root=escape_root,
            expected_enabled_customer="legacy",
            owner_digest="c" * 64,
            confirm_activation_receipt_digest=escaped_preflight[
                "activation_receipt_digest"
            ],
        )
    assert not (outside / "nutrition-readiness-v1").exists()

    hardlink_root = tmp_path / "hardlink-profile"
    (hardlink_root / "customers").mkdir(parents=True)
    (hardlink_root / "data").mkdir()
    os.link(
        registry_path,
        hardlink_root / "customers" / "registry.json",
    )
    journal_copy = hardlink_root / "data" / "customer-activation-journal.json"
    journal_copy.write_bytes(journal_path.read_bytes())
    journal_copy.chmod(0o600)

    with pytest.raises(ValueError, match="hard-linked"):
        legacy_migration_preflight(
            profile_root=hardlink_root,
            expected_enabled_customer="legacy",
            owner_digest="c" * 64,
        )
