#!/usr/bin/env bash
set +e
set +u
set +H 2>/dev/null

ROOT="/home/yeff/public_html/devon"
CANON="$ROOT/canon/execution"
STATE="$CANON/state"
BACKUP="$ROOT/_backup"
TS="$(date +%Y%m%d_%H%M%S)"

POLICY="$STATE/execution_contract_evolution_policy.json"
REGISTRY="$STATE/execution_observable_contract_registry.json"
GAP_QUEUE="$STATE/execution_contract_gap_queue.json"
GAP_LATEST="$STATE/execution_contract_gap_worker_latest.json"

PLAN="$STATE/execution_server_integration_plan.json"
JOBS="$STATE/yeffai_bootstrap_jobs.json"
PULL_LATEST="$STATE/yeffai_target_pull_worker_latest.json"
PROBE="$STATE/yeffai_target_probe_latest.json"
LIVE="$STATE/yeffai_target_live_runtime.json"
SCAN="$STATE/yeffai_target_operational_scan.json"
LEDGER="$STATE/execution_ledger.json"
LEDGER_JSONL="$STATE/execution_ledger.jsonl"
RUNTIME_PHP="$CANON/ui/runtime_status.php"

RUN_DIR="$BACKUP/execution_contract_gap_worker_run_$TS"
OUT="$RUN_DIR/execution_contract_gap_worker_$TS.txt"
mkdir -p "$RUN_DIR"

{
  echo "===== EXECUTION CONTRACT GAP WORKER RUN ====="
  echo "DATE=$(date)"
  echo "SERVER=WARESITES"
  echo "LOCAL_HOSTNAME=$(hostname 2>/dev/null)"
  echo "LOCAL_WHOAMI=$(whoami 2>/dev/null)"
  echo "POLICY=LOCAL_CONTRACT_GAP_SCAN"
  echo "REMOTE_YEFFAI_MUTATION=NO"
  echo "YEFFAI_INSTALLATION_COMMAND_EXECUTED=NO"
  echo "INSTALLATION_STARTED=NO"
  echo

  if ! command -v python3 >/dev/null 2>&1; then
    echo "PYTHON3_STATUS=FAIL"
    echo "STATUS=FAIL"
    echo "CAUSE=python3 missing."
    exit 0
  fi

  for f in "$POLICY" "$REGISTRY" "$GAP_QUEUE" "$PLAN" "$JOBS" "$PULL_LATEST" "$PROBE" "$LIVE" "$SCAN" "$LEDGER" "$LEDGER_JSONL"; do
    if [ ! -f "$f" ]; then
      echo "REQUIRED_FILE_MISSING=$f"
      echo "STATUS=FAIL"
      echo "CAUSE=Required contract gap input missing."
      exit 0
    fi
  done

  RUNTIME_JSON="$RUN_DIR/runtime_status_cli.json"
  if [ -f "$RUNTIME_PHP" ] && command -v php >/dev/null 2>&1; then
    php "$RUNTIME_PHP" > "$RUNTIME_JSON" 2>"$RUN_DIR/runtime_status_cli.err" || true
  fi

  python3 - "$POLICY" "$REGISTRY" "$GAP_QUEUE" "$GAP_LATEST" "$PLAN" "$JOBS" "$PULL_LATEST" "$PROBE" "$LIVE" "$SCAN" "$LEDGER" "$LEDGER_JSONL" "$RUNTIME_JSON" "$TS" <<'PY'
import json, sys, pathlib, datetime, hashlib

(
    policy_path,
    registry_path,
    gap_queue_path,
    latest_path,
    plan_path,
    jobs_path,
    pull_path,
    probe_path,
    live_path,
    scan_path,
    ledger_path,
    ledger_jsonl_path,
    runtime_json_path,
    ts
) = sys.argv[1:]

def load(path, default=None):
    p = pathlib.Path(path)
    if not p.is_file():
        return default if default is not None else {}
    try:
        with p.open("r", encoding="utf-8") as fh:
            return json.load(fh)
    except Exception as e:
        return {"__json_error__": str(e), "__path__": path}

def dump(path, data, indent=2):
    with open(path, "w", encoding="utf-8") as fh:
        json.dump(data, fh, indent=indent, ensure_ascii=False)
        fh.write("\n")

def norm(v):
    return str(v or "").strip().upper()

def fingerprint(parts):
    raw = "|".join(str(x) for x in parts)
    return hashlib.sha256(raw.encode("utf-8")).hexdigest()[:24]

now = datetime.datetime.now(datetime.timezone.utc).replace(microsecond=0).isoformat().replace("+00:00", "Z")

policy = load(policy_path, {})
registry = load(registry_path, {})
queue = load(gap_queue_path, {})
plan = load(plan_path, {})
jobs = load(jobs_path, {})
pull = load(pull_path, {})
probe = load(probe_path, {})
live = load(live_path, {})
scan = load(scan_path, {})
ledger = load(ledger_path, {})
runtime = load(runtime_json_path, {}) if pathlib.Path(runtime_json_path).is_file() else {}

known_actions = registry.get("known_actions", {}) if isinstance(registry.get("known_actions"), dict) else {}

observed_actions = []

for source_name, value in [
    ("plan.next_required_action", plan.get("next_required_action")),
    ("jobs.next_required_action", jobs.get("next_required_action")),
    ("scan.next_required_action", scan.get("next_required_action")),
    ("ledger.required_next_action", ledger.get("required_next_action")),
    ("runtime.next_required_action", runtime.get("next_required_action")),
    ("pull.next_required_action", pull.get("next_required_action")),
    ("plan.first_yeffai_installation_step", plan.get("first_yeffai_installation_step")),
    ("plan.first_yeffai_installation_step_raw_action", plan.get("first_yeffai_installation_step_raw_action"))
]:
    action = norm(value)
    if action and action not in ("MISSING", "NONE", "NOOP"):
        observed_actions.append({"source": source_name, "action": action})

job_list = jobs.get("jobs") if isinstance(jobs.get("jobs"), list) else []
for job in job_list[-20:]:
    if isinstance(job, dict):
        action = norm(job.get("action"))
        if action and action not in ("MISSING", "NONE", "NOOP"):
            observed_actions.append({"source": "jobs.jobs[].action", "action": action})

existing_gaps = queue.get("gaps") if isinstance(queue.get("gaps"), list) else []
existing_by_id = {g.get("gap_id"): g for g in existing_gaps if isinstance(g, dict) and g.get("gap_id")}

new_gaps = []

def add_gap(kind, source, observed, reason, required_contract_fields):
    gap_id = "gap_" + fingerprint([kind, source, observed, reason])
    if gap_id in existing_by_id:
        return
    new_gaps.append({
        "gap_id": gap_id,
        "kind": kind,
        "source": source,
        "observed": observed,
        "reason": reason,
        "status": "OPEN",
        "created_at": now,
        "required_before_execution": required_contract_fields,
        "blocking_policy": "BLOCK_UNTIL_CONTRACTED",
        "remote_yeffai_mutation": "NO",
        "installation_command_executed": "NO",
        "installation_started": "NO"
    })

for item in observed_actions:
    action = item["action"]
    if action not in known_actions:
        add_gap(
            "UNKNOWN_ACTION",
            item["source"],
            action,
            "Observed action is not registered in execution_observable_contract_registry. Execution must not proceed until it has expected evidence, validation rule, failure rule and runtime/UI binding rule.",
            [
                "action_id",
                "execution_class",
                "remote_mutation_allowed",
                "installation_command_allowed",
                "expected_evidence",
                "expected_remote_delta",
                "validation_rule",
                "failure_rule",
                "rollback_rule",
                "canon_outputs",
                "runtime_fields",
                "ui_visibility_rule"
            ]
        )

# detecta sinais de instalação futura sem contrato filho específico
advanced = "BEGIN_CONTROLLED_YEFFAI_INSTALL_STEPS_OR_PROVIDE_CATEGORY_RUNTIME_EVIDENCE"
if any(x["action"] == advanced for x in observed_actions):
    child_step_keys = [
        "current_controlled_installation_step",
        "next_controlled_installation_step",
        "specific_child_step_id",
        "next_installation_step_contract"
    ]
    has_child = any(plan.get(k) for k in child_step_keys) or any(jobs.get(k) for k in child_step_keys)
    if not has_child:
        add_gap(
            "MISSING_CHILD_INSTALLATION_STEP_CONTRACT",
            "plan/jobs",
            advanced,
            "Control gate advanced, but no concrete child installation step contract is present yet.",
            [
                "specific_child_step_id",
                "child_step_contract_file",
                "authorized_command_template",
                "expected_remote_delta",
                "rollback_rule",
                "scanner_rule",
                "runtime_binding_rule",
                "ui_operator_label"
            ]
        )

# detecta /opt/yeffai aparecendo sem contrato de delta
opt_yeffai = None
for source in (probe, live, scan):
    evidence = source.get("evidence") if isinstance(source.get("evidence"), dict) else {}
    if evidence.get("OPT_YEFFAI_EXISTS") is not None:
        opt_yeffai = evidence.get("OPT_YEFFAI_EXISTS")

if norm(opt_yeffai) == "YES":
    has_delta_contract = "YEFFAI_OPT_DIRECTORY_CREATED" in known_actions
    if not has_delta_contract:
        add_gap(
            "UNCONTRACTED_REMOTE_DELTA",
            "remote.evidence.OPT_YEFFAI_EXISTS",
            "YES",
            "/opt/yeffai exists but registry has no YEFFAI_OPT_DIRECTORY_CREATED contract.",
            [
                "delta_id",
                "expected_owner",
                "expected_permissions",
                "expected_files",
                "creation_command_contract",
                "rollback_rule",
                "healthcheck_rule",
                "runtime_binding_rule"
            ]
        )

all_gaps = existing_gaps + new_gaps
open_count = sum(1 for g in all_gaps if isinstance(g, dict) and g.get("status") == "OPEN")
resolved_count = sum(1 for g in all_gaps if isinstance(g, dict) and g.get("status") == "RESOLVED")

queue_out = {
    "contract_id": "execution_contract_gap_queue",
    "version": "v1",
    "created_at": queue.get("created_at") or now,
    "updated_at": now,
    "status": "PASS" if open_count == 0 else "MISSING",
    "open_gap_count": open_count,
    "resolved_gap_count": resolved_count,
    "policy": "BLOCK_UNCONTRACTED_EXECUTION",
    "gaps": all_gaps,
    "remote_yeffai_mutation": "NO",
    "installation_command_executed": "NO",
    "installation_started": "NO"
}

latest = {
    "worker_id": "execution_contract_gap_worker",
    "status": queue_out["status"],
    "updated_at": now,
    "open_gap_count": open_count,
    "resolved_gap_count": resolved_count,
    "new_gap_count": len(new_gaps),
    "observed_action_count": len(observed_actions),
    "observed_actions": observed_actions,
    "new_gaps": new_gaps,
    "gap_queue": gap_queue_path,
    "policy": policy_path,
    "registry": registry_path,
    "remote_yeffai_mutation": "NO",
    "installation_command_executed": "NO",
    "installation_started": "NO"
}

dump(gap_queue_path, queue_out, 2)
dump(latest_path, latest, 2)

print("CONTRACT_GAP_WORKER_STATUS=" + queue_out["status"])
print("OPEN_GAP_COUNT=" + str(open_count))
print("RESOLVED_GAP_COUNT=" + str(resolved_count))
print("NEW_GAP_COUNT=" + str(len(new_gaps)))
print("OBSERVED_ACTION_COUNT=" + str(len(observed_actions)))
PY

  for f in "$POLICY" "$REGISTRY" "$GAP_QUEUE" "$GAP_LATEST"; do
    python3 -m json.tool "$f" >/dev/null 2>&1 && echo "JSON_VALIDATION=PASS path=$f" || echo "JSON_VALIDATION=FAIL path=$f"
  done

  echo "STATUS=PASS"
  echo "CAUSE=Contract gap worker completed local scan."
  echo "REMOTE_YEFFAI_MUTATION=NO"
  echo "YEFFAI_INSTALLATION_COMMAND_EXECUTED=NO"
  echo "INSTALLATION_STARTED=NO"
} | tee "$OUT"

exit 0
