import json
import subprocess
import sys
from datetime import datetime, timezone


def _write_adapter_dry_run_receipt(
    root,
    *,
    platform="coupang_tw",
    manifest_id="coupang-403",
    adapter_code="coupang",
    barrier_type="access_denied",
    capture_runtime_unavailable=False,
):
    receipt_dir = root / platform / manifest_id
    receipt_dir.mkdir(parents=True)
    field_contracts = [
        {"field": "platform", "mapped": True},
        {"field": "platform_product_id", "mapped": True, "requires_identity_match": True},
        {"field": "title", "mapped": True, "requires_identity_match": True},
        {"field": "url", "mapped": True, "requires_identity_match": True},
        {"field": "image_url", "mapped": True},
        {"field": "price", "mapped": True, "requires_promotion_gate": True},
        {"field": "currency", "mapped": True},
        {"field": "availability", "mapped": True},
        {"field": "seller", "mapped": True},
        {"field": "promotion_badges", "mapped": True, "requires_promotion_gate": True},
        {"field": "shipping_badges", "mapped": True, "requires_promotion_gate": True},
        {"field": "evidence_time", "mapped": True},
        {"field": "source_method", "mapped": True},
        {"field": "confidence", "mapped": True, "requires_promotion_gate": True},
    ]
    payload = {
        "generated_at": datetime.now(timezone.utc).isoformat(),
        "policy": "controlled_pixelrag_marketplace_source_contract_adapter_dry_run_v1",
        "worker_status": "executed_marketplace_adapter_dry_run_ready",
        "platform": platform,
        "manifest_id": manifest_id,
        "adapter_code": adapter_code,
        "adapter_dry_run_receipt_path": (
            f"runtime_artifacts/pixelrag_marketplace_adapter_dry_run_receipts/"
            f"{platform}/{manifest_id}/marketplace_adapter_dry_run_receipt.json"
        ),
        "adapter_preflight_receipt_path": (
            f"runtime_artifacts/pixelrag_marketplace_adapter_preflight_receipts/"
            f"{platform}/{manifest_id}/marketplace_adapter_preflight_receipt.json"
        ),
        "source_contract_replay_receipt_path": (
            f"runtime_artifacts/pixelrag_source_contract_replay_receipts/"
            f"{platform}/{manifest_id}/source_contract_replay_receipt.json"
        ),
        "source_worker_receipt_path": (
            f"runtime_artifacts/pixelrag_platform_probe_worker_receipts/"
            f"{platform}/{manifest_id}/platform_probe_worker_receipt.json"
        ),
        "source_receipt_path": (
            f"runtime_artifacts/pixelrag_visual_evidence/"
            f"{platform}/{manifest_id}/capture_receipt.json"
        ),
        "adapter_dry_run_check_count": 19,
        "adapter_dry_run_check_pass_count": 19,
        "adapter_dry_run_checks": {
            "adapter_code_present": True,
            "adapter_preflight_checks_all_passed": True,
            "adapter_preflight_ready": True,
            "adapter_preflight_version_supported": True,
            "blocked_page_not_product_data": True,
            "canonical_offer_fields_present": True,
            "database_write_disallowed": True,
            "direct_ai_insights_write_disallowed": True,
            "direct_price_write_disallowed": True,
            "dry_run_output_contract_generated": True,
            "dry_run_schema_generated": True,
            "model_call_disallowed": True,
            "network_call_disallowed": True,
            "price_write_blocked_until_promotion_gate": True,
            "promotion_gates_required": True,
            "receipt_fresh": True,
            "receipt_parse_ok": True,
            "source_contract_version_supported": True,
            "source_count_positive": True,
        },
        "adapter_dry_run": {
            "adapter_dry_run_version": "pixelrag_marketplace_adapter_dry_run_v1",
            "adapter_preflight_version": "pixelrag_marketplace_adapter_preflight_v1",
            "source_contract_version": "pixelrag_marketplace_source_contract_v1",
            "contract_id": f"{platform}:{manifest_id}:{adapter_code}",
            "adapter_code": adapter_code,
            "barrier_type": barrier_type,
            "capture_runtime_unavailable": capture_runtime_unavailable,
            "dry_run_execution_mode": "deterministic_mapping_only_no_network_no_db",
            "field_contract_count": 14,
            "field_contracts": field_contracts,
            "offer_candidate_contracts": [
                {
                    "candidate_index": 0,
                    "candidate_id": f"{platform}:{manifest_id}:0",
                    "field_count": 14,
                    "ready_for_identity_matcher_replay": True,
                    "ready_for_price_table_write": False,
                    "price_write_blocked_until_promotion_gate": True,
                },
                {
                    "candidate_index": 1,
                    "candidate_id": f"{platform}:{manifest_id}:1",
                    "field_count": 14,
                    "ready_for_identity_matcher_replay": True,
                    "ready_for_price_table_write": False,
                    "price_write_blocked_until_promotion_gate": True,
                },
            ],
            "required_before_data_promotion": [
                "public_source_boundary",
                "rate_limit_contract",
                "provenance_contract",
                "identity_matcher_replay",
                "promotion_gate",
                "embedding_signature_guard",
            ],
        },
        "promotion_boundary": {
            "direct_ai_insights_write_allowed": False,
            "direct_price_write_allowed": False,
        },
        "writes_database": False,
        "writes_database_count": 0,
        "network_call_performed": False,
        "model_call_performed": False,
    }
    path = receipt_dir / "marketplace_adapter_dry_run_receipt.json"
    path.write_text(json.dumps(payload, ensure_ascii=False), encoding="utf-8")
    return path


def test_marketplace_identity_matcher_replay_reads_dry_run_receipts(tmp_path):
    from services.pixelrag_marketplace_identity_matcher_replay_service import (
        POLICY,
        run_pixelrag_marketplace_identity_matcher_replay,
    )

    dry_run_root = tmp_path / "adapter_dry_run"
    _write_adapter_dry_run_receipt(dry_run_root)
    _write_adapter_dry_run_receipt(
        dry_run_root,
        platform="shopee_tw",
        manifest_id="shopee-runtime-gap",
        adapter_code="shopee",
        barrier_type="language_or_region_interstitial",
        capture_runtime_unavailable=True,
    )

    payload = run_pixelrag_marketplace_identity_matcher_replay(
        adapter_dry_run_receipt_root=dry_run_root,
        platform=("coupang_tw", "shopee_tw"),
    )
    by_platform = {item["platform"]: item for item in payload["worker_items"]}

    assert payload["policy"] == POLICY
    assert payload["status"] == "ok"
    assert payload["summary"]["candidate_count"] == 2
    assert payload["summary"]["ready_count"] == 2
    assert payload["summary"]["dry_run_count"] == 2
    assert payload["summary"]["identity_candidate_count"] == 4
    assert payload["summary"]["capture_runtime_gap_count"] == 1
    assert payload["summary"]["writes_database_count"] == 0
    assert payload["controlled_apply"]["network_call"] is False
    assert payload["controlled_apply"]["writes_database"] is False
    assert payload["promotion_boundary"]["writes_price_tables"] is False
    assert payload["next_machine_action"] == (
        "run_marketplace_adapter_identity_matcher_replay_execute"
    )
    assert by_platform["coupang_tw"]["worker_status"] == (
        "dry_run_ready_for_marketplace_identity_matcher_replay"
    )
    first_identity = by_platform["coupang_tw"]["identity_matcher_replay"][
        "identity_candidate_contracts"
    ][0]
    assert first_identity["ready_for_promotion_gate_replay"] is True
    assert first_identity["ready_for_price_table_write"] is False
    assert first_identity["price_write_blocked_until_promotion_gate"] is True
    assert by_platform["shopee_tw"]["identity_matcher_replay"][
        "capture_runtime_unavailable"
    ] is True


def test_marketplace_identity_matcher_replay_execute_writes_receipt(tmp_path):
    from services.pixelrag_marketplace_identity_matcher_replay_service import (
        run_pixelrag_marketplace_identity_matcher_replay,
    )

    dry_run_root = tmp_path / "adapter_dry_run"
    output_root = tmp_path / "identity_matcher"
    _write_adapter_dry_run_receipt(dry_run_root)

    payload = run_pixelrag_marketplace_identity_matcher_replay(
        adapter_dry_run_receipt_root=dry_run_root,
        output_root=output_root,
        platform="coupang_tw",
        execute=True,
        write_receipt=True,
    )

    assert payload["status"] == "ok"
    assert payload["summary"]["executed_count"] == 1
    assert payload["summary"]["receipt_written_count"] == 1
    assert payload["controlled_apply"]["artifact_write"] is True
    assert payload["controlled_apply"]["writes_database"] is False
    assert payload["next_machine_action"] == "run_marketplace_promotion_gate_replay"
    receipt_path = (
        output_root
        / "coupang_tw"
        / "coupang-403"
        / "marketplace_identity_matcher_replay_receipt.json"
    )
    assert receipt_path.exists()
    receipt = json.loads(receipt_path.read_text(encoding="utf-8"))
    assert receipt["worker_status"] == (
        "executed_marketplace_identity_matcher_replay_ready"
    )
    assert receipt["artifact_write_performed"] is True
    assert receipt["writes_database"] is False
    assert receipt["identity_matcher_replay_check_pass_count"] == (
        receipt["identity_matcher_replay_check_count"]
    )
    assert receipt["identity_matcher_replay"]["allowed_next_step"] == (
        "run_marketplace_promotion_gate_replay"
    )


def test_marketplace_identity_matcher_replay_cli_outputs_json(tmp_path):
    dry_run_root = tmp_path / "adapter_dry_run"
    _write_adapter_dry_run_receipt(dry_run_root)

    completed = subprocess.run(
        [
            sys.executable,
            "scripts/ops/run_pixelrag_marketplace_identity_matcher_replay.py",
            "--adapter-dry-run-receipt-root",
            str(dry_run_root),
            "--platform",
            "coupang_tw",
        ],
        capture_output=True,
        check=False,
        text=True,
    )

    assert completed.returncode == 0
    payload = json.loads(completed.stdout)
    assert payload["summary"]["candidate_count"] == 1
    assert payload["summary"]["ready_count"] == 1
    assert payload["summary"]["identity_candidate_count"] == 2
    assert payload["controlled_apply"]["writes_database"] is False


def test_marketplace_identity_matcher_replay_route_returns_readback(
    tmp_path,
    monkeypatch,
):
    from flask import Flask
    from routes import system_public_routes as routes
    from services import pixelrag_marketplace_identity_matcher_replay_service as service

    dry_run_root = tmp_path / "adapter_dry_run"
    _write_adapter_dry_run_receipt(dry_run_root)
    monkeypatch.setattr(
        service,
        "DEFAULT_ADAPTER_DRY_RUN_RECEIPT_ROOT",
        str(dry_run_root),
    )

    app = Flask(__name__)
    with app.test_request_context(
        "/api/ai-automation/pixelrag-marketplace-identity-matcher-replay?platform=coupang_tw"
    ):
        response = (
            routes
            .ai_automation_pixelrag_marketplace_identity_matcher_replay_api
            .__wrapped__()
        )
    payload = response.get_json()

    assert payload["policy"] == (
        "controlled_pixelrag_marketplace_identity_matcher_replay_v1"
    )
    assert payload["summary"]["candidate_count"] == 1
    assert payload["summary"]["ready_count"] == 1
    assert payload["controlled_apply"]["writes_database"] is False
