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

ROOT_DIR="$(cd "$(dirname "$0")/../.." && pwd)"
cd "$ROOT_DIR"

SANDBOX="$ROOT_DIR/sandbox/rho-message-send"
REPO="$SANDBOX/repo"
OWNER_HOME="$SANDBOX/owner-rho-home"
COLLAB_HOME="$SANDBOX/collab-rho-home"
OWNER_ID="rho://id/github/rho-owner"
COLLAB_ID="rho://id/github/rho-collab"
MESSAGE_ID="msg-repo-message"
MESSAGE_DIR="rho/messages/inbox/id/github/rho-owner/$MESSAGE_ID"

rm -rf "$SANDBOX"
mkdir -p "$REPO"

git -C "$REPO" init >/dev/null
git -C "$REPO" config user.name "Rho Message Test"
git -C "$REPO" config user.email "message@example.test"
git -C "$REPO" config commit.gpgsign false

RHO_HOME="$OWNER_HOME" ./rho id init \
  --github rho-owner \
  --display-name "Rho Owner" \
  --generate-ssh-key >/dev/null
RHO_HOME="$COLLAB_HOME" ./rho id init \
  --github rho-collab \
  --display-name "Rho Collaborator" \
  --generate-ssh-key >/dev/null
RHO_HOME="$OWNER_HOME" ./rho id export \
  --identity "$OWNER_ID" \
  --out "$SANDBOX/rho-owner-public.yaml" >/dev/null
RHO_HOME="$COLLAB_HOME" ./rho id export \
  --identity "$COLLAB_ID" \
  --out "$SANDBOX/rho-collab-public.yaml" >/dev/null
RHO_HOME="$OWNER_HOME" ./rho id import "$SANDBOX/rho-collab-public.yaml" >/dev/null
RHO_HOME="$COLLAB_HOME" ./rho id import "$SANDBOX/rho-owner-public.yaml" >/dev/null

./rho repo init \
  --root "$REPO" \
  --repo-id rho://repo/local/message-send \
  --owner "$OWNER_ID" >/dev/null
RHO_HOME="$OWNER_HOME" ./rho id export \
  --identity "$OWNER_ID" \
  --out "$REPO/rho/participants/rho-owner.yaml" >/dev/null
RHO_HOME="$COLLAB_HOME" ./rho id export \
  --identity "$COLLAB_ID" \
  --out "$REPO/rho/participants/rho-collab.yaml" >/dev/null
cat > "$REPO/rho/membership.yaml" <<EOF
version: 1
members:
  - identity: $OWNER_ID
    role: owner
  - identity: $COLLAB_ID
    role: collaborator
EOF
RHO_HOME="$OWNER_HOME" ./rho repo protect-path \
  "rho/messages/inbox/id/github/rho-owner/**" \
  --root "$REPO" \
  --rho-bin "$ROOT_DIR/rho" \
  --recipient "$OWNER_ID" >/dev/null
RHO_HOME="$OWNER_HOME" ./rho repo sign-governance --root "$REPO" >/dev/null

RHO_HOME="$COLLAB_HOME" ./rho message send \
  --root "$REPO" \
  --from "$COLLAB_ID" \
  --to "$OWNER_ID" \
  --type note \
  --id "$MESSAGE_ID" \
  --text "sender can still read this note" \
  > "$SANDBOX/message-output.txt"

grep -q "message: $MESSAGE_ID" "$SANDBOX/message-output.txt"
grep -q "staged encrypted message files" "$SANDBOX/message-output.txt"
grep -q "path: $MESSAGE_DIR/message.yaml" "$SANDBOX/message-output.txt"
grep -q "signature: $MESSAGE_DIR/message.rhosig.yaml" "$SANDBOX/message-output.txt"
grep -q "purpose: rho.message" "$REPO/$MESSAGE_DIR/message.rhosig.yaml"
grep -q "message_id: $MESSAGE_ID" "$REPO/$MESSAGE_DIR/message.rhosig.yaml"

RHO_HOME="$COLLAB_HOME" ./rho crypto verify \
  "$REPO/$MESSAGE_DIR/message.yaml" \
  --signature "$REPO/$MESSAGE_DIR/message.rhosig.yaml" \
  --identity "$COLLAB_ID" \
  --repo-id rho://repo/local/message-send \
  --message-id "$MESSAGE_ID" \
  --recipient "$OWNER_ID" \
  --purpose rho.message >/dev/null

git -C "$REPO" show ":$MESSAGE_DIR/message.yaml" > "$SANDBOX/message-index.yaml"
git -C "$REPO" show ":$MESSAGE_DIR/message.rhosig.yaml" > "$SANDBOX/message-signature-index.yaml"
grep -q "kind: rho_recipient_envelope" "$SANDBOX/message-index.yaml"
grep -q "kind: rho_recipient_envelope" "$SANDBOX/message-signature-index.yaml"
grep -q "$OWNER_ID" "$SANDBOX/message-index.yaml"
grep -q "$COLLAB_ID" "$SANDBOX/message-index.yaml"
grep -q "$COLLAB_ID" "$SANDBOX/message-signature-index.yaml"
if grep -q "sender can still read this note" "$SANDBOX/message-index.yaml"; then
  echo "message index blob leaked plaintext" >&2
  exit 1
fi

cp "$REPO/$MESSAGE_DIR/message.yaml" "$SANDBOX/message-plain.yaml"
cp "$REPO/$MESSAGE_DIR/message.rhosig.yaml" "$SANDBOX/message-signature-plain.yaml"
git -C "$REPO" show ":$MESSAGE_DIR/message.yaml" > "$REPO/$MESSAGE_DIR/message.yaml"
git -C "$REPO" show ":$MESSAGE_DIR/message.rhosig.yaml" > "$REPO/$MESSAGE_DIR/message.rhosig.yaml"
grep -q "kind: rho_recipient_envelope" "$REPO/$MESSAGE_DIR/message.yaml"
grep -q "kind: rho_recipient_envelope" "$REPO/$MESSAGE_DIR/message.rhosig.yaml"
RHO_HOME="$OWNER_HOME" RHO_IDENTITY="$OWNER_ID" ./rho message verify "$MESSAGE_ID" \
  --root "$REPO" \
  --to "$OWNER_ID" \
  > "$SANDBOX/message-verify-encrypted-worktree-pass.txt"
grep -q "refreshed protected file: $MESSAGE_DIR/message.yaml" "$SANDBOX/message-verify-encrypted-worktree-pass.txt"
grep -q "refreshed protected file: $MESSAGE_DIR/message.rhosig.yaml" "$SANDBOX/message-verify-encrypted-worktree-pass.txt"
grep -q "message: verified $MESSAGE_DIR/message.yaml" "$SANDBOX/message-verify-encrypted-worktree-pass.txt"
grep -q "from: $COLLAB_ID" "$SANDBOX/message-verify-encrypted-worktree-pass.txt"

awk '
  /^[[:space:]]+ciphertext_base64:/ && !done {
    prefix = substr($0, 1, index($0, "ciphertext_base64:") - 1)
    value = $2
    first = substr(value, 1, 1)
    replacement = first == "A" ? "B" : "A"
    print prefix "ciphertext_base64: " replacement substr(value, 2)
    done = 1
    next
  }
  { print }
' "$SANDBOX/message-index.yaml" > "$REPO/$MESSAGE_DIR/message.yaml"
git -C "$REPO" show ":$MESSAGE_DIR/message.rhosig.yaml" > "$REPO/$MESSAGE_DIR/message.rhosig.yaml"
if RHO_HOME="$OWNER_HOME" RHO_IDENTITY="$OWNER_ID" ./rho message verify "$MESSAGE_ID" \
  --root "$REPO" \
  --to "$OWNER_ID" \
  > "$SANDBOX/message-verify-tampered-message-stdout.txt" \
  2> "$SANDBOX/message-verify-tampered-message-stderr.txt"; then
  echo "message verify accepted tampered encrypted message ciphertext" >&2
  exit 1
fi
grep -q "rho crypto smudge failed for $MESSAGE_DIR/message.yaml" "$SANDBOX/message-verify-tampered-message-stderr.txt"
grep -q "recipient envelope decrypt failed for $OWNER_ID" "$SANDBOX/message-verify-tampered-message-stderr.txt"
grep -q "decrypt" "$SANDBOX/message-verify-tampered-message-stderr.txt"
cp "$SANDBOX/message-plain.yaml" "$REPO/$MESSAGE_DIR/message.yaml"
cp "$SANDBOX/message-signature-plain.yaml" "$REPO/$MESSAGE_DIR/message.rhosig.yaml"

RHO_HOME="$COLLAB_HOME" ./rho crypto smudge \
  --repo-root "$REPO" \
  --path "$MESSAGE_DIR/message.yaml" \
  < "$SANDBOX/message-index.yaml" \
  > "$SANDBOX/collab-smudged-message.yaml"
grep -q "sender can still read this note" "$SANDBOX/collab-smudged-message.yaml"

if RHO_HOME="$COLLAB_HOME" ./rho crypto verify \
  "$REPO/$MESSAGE_DIR/message.yaml" \
  --signature "$REPO/$MESSAGE_DIR/message.rhosig.yaml" \
  --identity "$COLLAB_ID" \
  --repo-id rho://repo/local/message-send \
  --message-id msg-other \
  --recipient "$OWNER_ID" \
  --purpose rho.message \
  > "$SANDBOX/bad-context-verify-stdout.txt" \
  2> "$SANDBOX/bad-context-verify-stderr.txt"; then
  echo "message verification accepted wrong message context" >&2
  exit 1
fi
grep -q "signature context mismatch for message_id" "$SANDBOX/bad-context-verify-stderr.txt"

echo "inspect sandbox: $SANDBOX"
find "$SANDBOX" \
  -path "*/.git" -prune -o \
  -maxdepth 7 -type f -print | sort
echo "rho message send e2e passed"
