#!/usr/bin/env bash
set -euo pipefail

REPO_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
cd "$REPO_DIR"

RUNTIME_DIR="${CTB_COPY_RUNTIME_DIR:-/home/agent/.local/state/CryptoTradingBot/copy_research}"
DAY="$(date -u +%F)"
RUN_DIR="$RUNTIME_DIR/reports/observation_runs"
LOG_FILE="$RUN_DIR/${DAY}_24h.log"
STATUS_FILE="$RUN_DIR/${DAY}_24h_status.json"
SUMMARY_FILE="$RUN_DIR/${DAY}_24h_summary.md"
INTERVAL_SECONDS="${CTB_OBSERVATION_INTERVAL_SECONDS:-7200}"
EXPECTED_CYCLES="${CTB_OBSERVATION_EXPECTED_CYCLES:-12}"
MAX_SECONDS="${CTB_OBSERVATION_MAX_SECONDS:-86700}"
START_EPOCH="$(date -u +%s)"
START_ISO="$(date -u --iso-8601=seconds)"
END_EPOCH="$((START_EPOCH + 86400))"
END_ISO="$(date -u -d "@$END_EPOCH" --iso-8601=seconds)"

mkdir -p "$RUN_DIR"

echo "READ ONLY OBSERVATION RUN" | tee -a "$LOG_FILE"
echo "NO ORDERS" | tee -a "$LOG_FILE"
echo "NO VAULT DEPOSITS" | tee -a "$LOG_FILE"
echo "NO WALLET EXECUTION" | tee -a "$LOG_FILE"
echo "NO SIGNING" | tee -a "$LOG_FILE"
echo "DURATION MAX 24H" | tee -a "$LOG_FILE"
echo "INTERVAL 2H" | tee -a "$LOG_FILE"
echo "start=$START_ISO planned_end=$END_ISO log=$LOG_FILE" | tee -a "$LOG_FILE"

safety_check() {
  PYTHONPATH=. python3 - <<'PY'
from src.ctb_copy.read_only_guard import DEFAULT_READ_ONLY_GUARD
DEFAULT_READ_ONLY_GUARD.assert_safe()
print(DEFAULT_READ_ONLY_GUARD.as_dict())
PY
  local forbidden_re
  forbidden_re="create_""order|market_""open|set_""leverage|vault""Deposit|exchange\\.order|Account\\.from_""key|HL_AGENT_""PRIVATE_KEY|HL_API_""PRIVATE_KEY"
  if grep -RInE "$forbidden_re" src/ctb_copy >/tmp/ctb_copy_observation_safety_hits.txt; then
    echo "SAFETY VIOLATION: execution-capable pattern found in src/ctb_copy" | tee -a "$LOG_FILE"
    cat /tmp/ctb_copy_observation_safety_hits.txt >> "$LOG_FILE"
    return 1
  fi
}

write_status() {
  local cycle="$1"
  local cycle_status="$2"
  local cycle_at
  cycle_at="$(date -u --iso-8601=seconds)"
  RUN_DAY="$DAY" RUN_STARTED_AT="$START_ISO" LAST_CYCLE_AT="$cycle_at" CYCLES_COMPLETED="$cycle" EXPECTED_CYCLES_TOTAL="$EXPECTED_CYCLES" RUN_STATUS="$cycle_status" RUNTIME_DIR="$RUNTIME_DIR" STATUS_FILE="$STATUS_FILE" PYTHONPATH=. python3 - <<'PY'
import json, os
from pathlib import Path
from src.ctb_copy.runtime_paths import CopyResearchPaths

runtime = Path(os.environ["RUNTIME_DIR"])
day = os.environ["RUN_DAY"]
paths = CopyResearchPaths(runtime)

def load_json(path: Path) -> dict:
    if not path.exists():
        return {}
    return json.loads(path.read_text(encoding="utf-8"))

def snapshot_count_by_wallet(path: Path) -> dict[str, int]:
    counts: dict[str, int] = {}
    if not path.exists():
        return counts
    for line in path.read_text(encoding="utf-8").splitlines():
        if not line.strip():
            continue
        row = json.loads(line)
        label = str(row.get("label") or row.get("wallet_address") or row.get("leader_id") or "unknown")
        counts[label] = counts.get(label, 0) + 1
    return counts

collector = load_json(paths.collector_result_file(day))
shadow = load_json(paths.shadow_result_file(day))
counts = snapshot_count_by_wallet(paths.snapshot_file("wallets", day))
status = {
    "run_started_at": os.environ["RUN_STARTED_AT"],
    "last_cycle_at": os.environ["LAST_CYCLE_AT"],
    "cycles_completed": int(os.environ["CYCLES_COMPLETED"]),
    "expected_cycles_total": int(os.environ["EXPECTED_CYCLES_TOTAL"]),
    "run_status": os.environ["RUN_STATUS"],
    "wallet_snapshot_count_total": sum(counts.values()),
    "snapshot_count_by_wallet": counts,
    "position_delta_count": int(shadow.get("decisions_count", 0)),
    "shadow_decisions_count": int(shadow.get("decisions_count", 0)),
    "allowed_count": int(shadow.get("allowed_count", 0)),
    "blocked_count": int(shadow.get("blocked_count", 0)),
    "ignored_count": int(shadow.get("ignored_count", 0)),
    "top_block_reasons": shadow.get("top_block_reasons", {}),
    "data_quality": collector.get("data_quality", ["unknown"]),
    "safety_status": "read_only_ok",
    "collector_status": collector.get("status", "unknown"),
    "shadow_status": shadow.get("status", "unknown"),
}
Path(os.environ["STATUS_FILE"]).write_text(json.dumps(status, indent=2, sort_keys=True) + "\n", encoding="utf-8")
print(json.dumps(status, sort_keys=True))
PY
}

write_summary() {
  local final_status="$1"
  RUN_DAY="$DAY" FINAL_STATUS="$final_status" RUNTIME_DIR="$RUNTIME_DIR" STATUS_FILE="$STATUS_FILE" SUMMARY_FILE="$SUMMARY_FILE" PYTHONPATH=. python3 - <<'PY'
import json, os
from pathlib import Path
from src.ctb_copy.runtime_paths import CopyResearchPaths

runtime = Path(os.environ["RUNTIME_DIR"])
day = os.environ["RUN_DAY"]
paths = CopyResearchPaths(runtime)
status_path = Path(os.environ["STATUS_FILE"])
summary_path = Path(os.environ["SUMMARY_FILE"])
status = json.loads(status_path.read_text(encoding="utf-8")) if status_path.exists() else {}
collector_path = paths.collector_result_file(day)
shadow_path = paths.shadow_result_file(day)
collector = json.loads(collector_path.read_text(encoding="utf-8")) if collector_path.exists() else {}
shadow = json.loads(shadow_path.read_text(encoding="utf-8")) if shadow_path.exists() else {}
counts = status.get("snapshot_count_by_wallet", {})
cycles = int(status.get("cycles_completed", 0))
decisions = int(status.get("shadow_decisions_count", 0))
api_issues = collector.get("partial_errors", [])
data_quality = status.get("data_quality", collector.get("data_quality", []))
active_enough = all(int(v) >= 2 for v in counts.values()) and bool(counts)
recommendation = "weiter beobachten: 24h Datenqualität prüfen und bei stabilen Snapshots 7 Tage Observation mit 5-10 Wallets erwägen" if active_enough else "weiter beobachten oder Wallets austauschen: zunächst fehlen genügend vergleichbare Snapshots/Deltas"
content = f"""# Copy Observation 24h Summary – {day}

## Status

- final_status: {os.environ['FINAL_STATUS']}
- run_started_at: {status.get('run_started_at', 'unknown')}
- last_cycle_at: {status.get('last_cycle_at', 'unknown')}
- cycles_completed: {cycles}
- expected_cycles_total: {status.get('expected_cycles_total', 12)}

## Snapshots

- wallet_snapshot_count_total: {status.get('wallet_snapshot_count_total', 0)}
- snapshot_count_by_wallet: {counts}

## Position-Deltas und Shadow-Decisions

- position_delta_count: {status.get('position_delta_count', decisions)}
- shadow_decisions_count: {decisions}
- allowed_count: {shadow.get('allowed_count', status.get('allowed_count', 0))}
- blocked_count: {shadow.get('blocked_count', status.get('blocked_count', 0))}
- ignored_count: {shadow.get('ignored_count', status.get('ignored_count', 0))}
- top_block_reasons: {shadow.get('top_block_reasons', status.get('top_block_reasons', {}))}

## API und Datenqualität

- collector_status: {collector.get('status', status.get('collector_status', 'unknown'))}
- shadow_status: {shadow.get('status', status.get('shadow_status', 'unknown'))}
- api_problems: {api_issues}
- data_quality: {data_quality}
- safety_status: {status.get('safety_status', 'read_only_ok')}

## Aktivitätsbewertung

- wallets_active_enough_for_delta_analysis: {str(active_enough).lower()}
- recommendation: {recommendation}

## Safety

Keine Live-Entscheidung. Keine Live-Copy. Keine Vault-Deposits. Keine Wallet/API-Wallet-Execution. Keine Orders. Kein Signing. Diese Auswertung bewertet nur Datenqualität und Delta-Erkennung.
"""
summary_path.write_text(content, encoding="utf-8")
print(summary_path)
PY
}

trap 'echo "aborted_at=$(date -u --iso-8601=seconds)" | tee -a "$LOG_FILE"; write_status "${cycle:-0}" "aborted" || true; write_summary "aborted" || true' ERR

safety_check | tee -a "$LOG_FILE"
write_status 0 "started" | tee -a "$LOG_FILE"

cycle=1
while [ "$cycle" -le "$EXPECTED_CYCLES" ]; do
  now_epoch="$(date -u +%s)"
  elapsed="$((now_epoch - START_EPOCH))"
  if [ "$elapsed" -gt "$MAX_SECONDS" ]; then
    echo "max duration exceeded before cycle $cycle" | tee -a "$LOG_FILE"
    break
  fi

  echo "cycle=$cycle started_at=$(date -u --iso-8601=seconds)" | tee -a "$LOG_FILE"
  safety_check | tee -a "$LOG_FILE"
  PYTHONPATH=. python3 -m src.ctb_copy.run_collector_once 2>&1 | tee -a "$LOG_FILE"
  PYTHONPATH=. python3 -m src.ctb_copy.run_shadow_once 2>&1 | tee -a "$LOG_FILE"
  PYTHONPATH=. python3 -m src.ctb_copy.reports.daily_copy_report 2>&1 | tee -a "$LOG_FILE"
  write_status "$cycle" "running" | tee -a "$LOG_FILE"
  echo "cycle=$cycle completed_at=$(date -u --iso-8601=seconds)" | tee -a "$LOG_FILE"

  if [ "$cycle" -ge "$EXPECTED_CYCLES" ]; then
    break
  fi
  sleep "$INTERVAL_SECONDS"
  cycle="$((cycle + 1))"
done

write_status "$cycle" "completed" | tee -a "$LOG_FILE"
write_summary "completed" | tee -a "$LOG_FILE"
echo "completed_at=$(date -u --iso-8601=seconds)" | tee -a "$LOG_FILE"
