#!/usr/bin/env bash

# SPDX-FileCopyrightText: 2025 Romain Maneschi <romain@gitroot.dev>
#
# SPDX-License-Identifier: EUPL-1.2

trap 'catch $LINENO' ERR

MY_LOG=${MY_LOG:-"/tmp/mylog.txt"}
EXPECTED_ERROR=0

catch() {
    if [[ $EXPECTED_ERROR == 0 ]]; then
        echo "🛑 unexpected error line $1"
        exit 1
    fi
    report "🟢 expected err line $1"
}

mySleep() {
    echo "🕐 wait $1"
    echo "🕐 $1" >> $MY_LOG
    sleep $1
}

function wait_for() {
    start=`date +%s`
    timeout=100
    until [ $timeout -le 0 ] || (grep -q $1 $2 &> /dev/null); do
        sleep 0.1
        timeout=$(( timeout - 1 ))
    done
    if [ $timeout -le 0 ]; then
        return 1
    fi
    end=`date +%s`
    echo "🕐 $@ in `expr $end - $start` seconds"
}

function wait_ls() {
    local start=$(date +%s)
    local timeout=500
    local target="$1"

    until [ $timeout -le 0 ]; do
        count=$(find "$target" -maxdepth 1 -mindepth 1 2>/dev/null | wc -l)
        if [ "$count" -eq 3 ]; then
            break
        fi
        sleep 0.1
        ((timeout--))
    done
    if [ $timeout -le 0 ]; then
        return 1
    fi
    local end=`date +%s`
    echo "🕐 $@ in `expr $end - $start` seconds"
    mySleep 0.3
}

function init_local_git() {
    git config commit.gpgSign true
    git config gpg.format ssh
    git config user.signingkey $3
    git config core.sshCommand "ssh -i ${4} -o IdentitiesOnly=yes"
    git config user.email "$1"
    git config user.name "$2"
    git config gpg.ssh.allowedSignersFile "$(pwd)/.gitroot/allowed_signers"
    echo "$1 $(cat $3)" >> "$(pwd)/.gitroot/allowed_signers"
}

EXIT_CODE=0

SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )

source "${SCRIPT_DIR}/lib/pushandwait.sh"
source "${SCRIPT_DIR}/lib/git.sh"
source "${SCRIPT_DIR}/lib/report.sh"

SERVER_PORT=${SERVER_PORT:-4545}
SERVER_PORT_HTTP=${SERVER_PORT_HTTP:-4546}
SERVER_URL=${1:-"127.0.0.1:$SERVER_PORT"}
SERVER_DATA_DIR="/tmp/gitrootData"

ROOT_REPO_NAME="root"
ROOT_REPO_URL="ssh://${SERVER_URL}/${ROOT_REPO_NAME}"
REPO1_NAME="repo1"
REPO1_URL="ssh://user@${SERVER_URL}/${REPO1_NAME}"
REPO2_NAME="repo2"
REPO2_URL="ssh://user@${SERVER_URL}/${REPO2_NAME}"
REPO3_NAME="repo3"
REPO3_URL="ssh://user@${SERVER_URL}/${REPO3_NAME}"

SSH_KEY="${SCRIPT_DIR}/user1/ed25519"
SSH_KEY2="${SCRIPT_DIR}/user2/ed25519"

LADYBUG_WASM="${SCRIPT_DIR}/../plugins/ladybug/ladybug-0.0.4.wasm"
SILO_WASM="${SCRIPT_DIR}/../plugins/silo/silo-0.0.4.wasm"
GRAFTER_WASM="${SCRIPT_DIR}/../plugins/grafter/grafter-0.0.4.wasm"
APEX_WASM="${SCRIPT_DIR}/../plugins/apex/apex-0.0.4.wasm"
APEX_MARKDOWN_WASM="${SCRIPT_DIR}/../plugins/apex/apex_markdown-0.0.4.wasm"
APEX_CODE_WASM="${SCRIPT_DIR}/../plugins/apex/apex_code-0.0.4.wasm"
APEX_CODE_MERMAID_WASM="${SCRIPT_DIR}/../plugins/apex_mermaid/apex_mermaid-0.0.1.wasm"
POLLEN_WASM="${SCRIPT_DIR}/../plugins/pollen/pollen-0.0.3.wasm"
HOP_WASM="${SCRIPT_DIR}/../plugins/hop/hop-0.0.2.wasm"
STIGMA_WASM="${SCRIPT_DIR}/../plugins/stigma/stigma-0.0.1.wasm"

##### clean
report "🏁 clean"

cd /tmp
rm -rf ${SERVER_DATA_DIR}
rm -rf ${ROOT_REPO_NAME}
rm -rf ${ROOT_REPO_NAME}_2
rm -rf ${REPO1_NAME}
rm -rf ${REPO2_NAME}
rm -rf ${REPO1_NAME}_2
rm -rf ${REPO2_NAME}_2
rm -rf ${REPO3_NAME}
rm -f ${MY_LOG}
APP=$(lsof -i tcp:${SERVER_PORT} | awk 'NR!=1 {print $2}') 
if [ -z "$APP" ]; then
    report "🟢 Gitroot not launched"
else 
    kill ${APP}
    report "🟢 Gitroot killed"
fi
ssh-keygen -f "$HOME/.ssh/known_hosts" -R "[127.0.0.1]:$SERVER_PORT"

##### launch gitroot
report "🏁 launch gitroot"

cd ${SCRIPT_DIR}/../server
mkdir -p "${SERVER_DATA_DIR}"
go run -race . -initConfig="${SERVER_DATA_DIR}/config"
sed -i -e "s/sshaddr: 0.0.0.0:4545/sshaddr: 0.0.0.0:$SERVER_PORT/g" "${SERVER_DATA_DIR}/config"
sed -i -e "s/httpaddr: 0.0.0.0:4546/httpaddr: 0.0.0.0:$SERVER_PORT_HTTP/g" "${SERVER_DATA_DIR}/config"
GIT_TRACE_PACKET=false go run -race . -data="${SERVER_DATA_DIR}" -config="${SERVER_DATA_DIR}/config" &>> $MY_LOG &

wait_for "starting SSH server on" $MY_LOG

##### forgeConfig
report "🏁 forgeConfig"

cd /tmp
quiet_git clone --quiet -c "core.sshCommand=ssh -i ${SSH_KEY} -o IdentitiesOnly=yes -o StrictHostKeyChecking=accept-new" ${ROOT_REPO_URL}
cd ${ROOT_REPO_NAME}
init_local_git forgeConfig@gitroot.dev forgeConfig ${SSH_KEY}.pub ${SSH_KEY}

printf "${REPO1_NAME}:\n  defaultbranch: main" >> .gitroot/repositories.yml
quiet_git add .
quiet_git commit -m "create first repo"
quiet_git push origin main
report "🟢 ${ROOT_REPO_NAME} push first repo"

mySleep 0.05

##### Repo1
report "🏁 Repo1"

cd /tmp
GIT_SSH_COMMAND="ssh -i ${SSH_KEY} -o IdentitiesOnly=yes" quiet_git clone --quiet "${REPO1_URL}"
cd ${REPO1_NAME}
init_local_git repo1@gitroot.dev user1 ${SSH_KEY}.pub ${SSH_KEY}

quiet_git add .
quiet_git commit -m "init user"
report "🟢 ${REPO1_NAME} commit user"

quiet_git checkout -b "branch1"
quiet_git push origin main branch1
report "🟢 ${REPO1_NAME} push main+branch1"
quiet_git checkout main
quiet_git push origin :branch1
report "🟢 ${REPO1_NAME} delete :branch1"
quiet_git push origin main
report "🟢 ${REPO1_NAME} push empty main"

##### first plugin
report "🏁 first plugin"

cd /tmp/${ROOT_REPO_NAME}
echo "- url: '${LADYBUG_WASM}'" >> .gitroot/plugins.yml
quiet_git add .
quiet_git commit -m "init ladybug plugin"
printf "\n${REPO2_NAME}:\n  defaultbranch: main" >> .gitroot/repositories.yml
quiet_git add .
quiet_git commit -m "create second repo"
quiet_git push origin main
report "🟢 ${ROOT_REPO_NAME} push first plugin and second repo"

wait_ls "${SERVER_DATA_DIR}/data/plugins/ladybug"

if [[ $(ls "${SERVER_DATA_DIR}/data/plugins/ladybug" | wc -l) -eq 3 ]]; then
    report "🟢 ${SERVER_DATA_DIR}/data/plugins/ladybug loaded"
else
    report "🛑 ${SERVER_DATA_DIR}/data/plugins/ladybug not downloaded"
    EXIT_CODE=1
fi

quiet_git pull origin main

if grep -Fxq "  name: ladybug" .gitroot/plugins.yml
then
    report "🟢 ${ROOT_REPO_NAME} plugin ladybug initialized"
else
    report "🛑 ${ROOT_REPO_NAME} plugin ladybug not initialized"
    EXIT_CODE=1
fi

if grep -Fxq "  version: 0.0.4" .gitroot/plugins.yml
then
    report "🟢 ${ROOT_REPO_NAME} plugin ladybug version initialized"
else
    report "🛑 ${ROOT_REPO_NAME} plugin ladybug version not initialized"
    EXIT_CODE=1
fi

if grep -Fxq "      metadata:" .gitroot/plugins.yml
then
    report "🟢 ${ROOT_REPO_NAME} plugin config initialized"
else
    report "🛑 ${ROOT_REPO_NAME} not initialized"
    EXIT_CODE=1
fi

if grep -Fxq "    - ladybug@localhost" .gitroot/users.yml
then
    report "🟢 ${ROOT_REPO_NAME} plugin user initialized"
else
    report "🛑 ${ROOT_REPO_NAME}  plugin user not initialized"
    EXIT_CODE=1
fi

cd /tmp
GIT_SSH_COMMAND="ssh -i ${SSH_KEY} -o IdentitiesOnly=yes" quiet_git clone --quiet "${REPO2_URL}"
cd ${REPO2_NAME}
init_local_git repo2@gitroot.dev user1 ${SSH_KEY}.pub ${SSH_KEY}

if grep -Fxq "      metadata:" .gitroot/plugins.yml
then
    report "🟢 ${REPO2_NAME} plugin config initialized"
else
    report "🛑 ${REPO2_NAME} not initialized"
    EXIT_CODE=1
fi

if grep -q "      - path: issues/\\*\\*/\\*.md" .gitroot/plugins.yml
then
    report "🟢 ${REPO2_NAME} plugin path initialized"
else
    report "🛑 ${REPO2_NAME} not initialized"
    EXIT_CODE=1
fi

sed -i -e 's/active: false/active: true/g' .gitroot/plugins.yml

mkdir issues
echo "#my Issue" >> issues/1.md
echo "Beatiful issue" >> issues/1.md
quiet_git add .
quiet_git commit -m "first issue in second repo"
quiet_git push origin main
report "🟢 ${REPO2_NAME} first issue in second repo"

mySleep 0.05

quiet_git pull

if grep -q "priority: 50" issues/1.md
then
    report "🟢 issues/1.md initialized"
else
    report "🛑 issues/1.md not initialized"
    EXIT_CODE=1
fi

##### repo1 should have issue available
report "🏁 repo1 should have issue available"

cd /tmp/${REPO1_NAME}

quiet_git pull

if grep -q "      - path: issues/\\*\\*/\\*.md" .gitroot/plugins.yml
then
    report "🟢 ${REPO1_NAME} plugin path initialized"
else
    report "🛑 ${REPO1_NAME} not initialized"
    EXIT_CODE=1
fi

sed -i -e 's/active: false/active: true/g' .gitroot/plugins.yml

mkdir issues
echo "#my Issue" >> issues/1.md
echo "Beatiful issue" >> issues/1.md
quiet_git add .
quiet_git commit -m "first issue in first repo"
quiet_git push origin main
report "🟢 ${REPO1_NAME} first issue in first repo"

mySleep 0.05

quiet_git pull

if grep -q "priority: 50" issues/1.md
then
    report "🟢 issues/1.md initialized"
else
    report "🛑 issues/1.md not initialized"
    EXIT_CODE=1
fi

##### user2 rights
report "🏁 user2 rights"

cd /tmp
GIT_SSH_COMMAND="ssh -i ${SSH_KEY2} -o IdentitiesOnly=yes" quiet_git clone --quiet "${REPO1_URL}" ${REPO1_NAME}_2
cd ${REPO1_NAME}_2
git config core.sshCommand "ssh -i ${SSH_KEY2} -o IdentitiesOnly=yes"
git config user.email user2repo1@gitroot.dev
git config user.name user2

echo "# my Issue" >> issues/cac-1.md
echo "Beatiful issue" >> issues/cac-1.md

quiet_git add .
quiet_git commit -m "user2 config and add an issue"
EXPECTED_ERROR=1
quiet_git push origin main
if [[ "$?" == "0" ]]; then
    report "🛑 user2 has push on main in repo1"
    EXIT_CODE=1
else
    report "🟢 user2 can not push on main in repo1"
fi
EXPECTED_ERROR=0

quiet_git reset --soft HEAD~1 
quiet_git checkout -b user2_branch_on_repo1
quiet_git add .
quiet_git commit -m "user2 config and an issue"
quiet_git push origin user2_branch_on_repo1

if [[ "$?" == "0" ]]; then
    report "🟢 user2 can push on user2_branch_on_repo1 branch in repo1"
else
    report "🛑 user2 can not push on user2_branch_on_repo1 branch in repo1"
    EXIT_CODE=1
fi

mySleep 0.05
quiet_git pull origin user2_branch_on_repo1

if grep -q "priority: 50" issues/cac-1.md
then
    report "🟢 issues/cac-1.md initialized"
else
    report "🛑 issues/cac-1.md not initialized"
    EXIT_CODE=1
fi

echo "New readme" > "README.md"
quiet_git add .
quiet_git commit -m "update readme"
quiet_git push origin user2_branch_on_repo1

if [[ "$?" == "0" ]]; then
    report "🟢 user2 can push on user2_branch_on_repo1 branch in repo1 second time"
else
    report "🛑 user2 can not push on user2_branch_on_repo1 branch in repo1 second time"
    EXIT_CODE=1
fi

quiet_git checkout main

cd /tmp/${REPO1_NAME}
quiet_git fetch origin user2_branch_on_repo1
quiet_git checkout user2_branch_on_repo1

echo "New readme by user 1" > "README.md"
quiet_git add .
quiet_git commit -m "update readme"
quiet_git push origin user2_branch_on_repo1
report "🟢 user1 can push on user2_branch_on_repo1 branch in repo1"

quiet_git checkout main

##### second plugin
report "🏁 second plugin"

cd /tmp/${ROOT_REPO_NAME}
echo "- url: '${SILO_WASM}'" >> .gitroot/plugins.yml
quiet_git add .
quiet_git commit -m "init silo plugin"
quiet_git push origin main
echo "🟢 ${ROOT_REPO_NAME} push second plugin"

wait_ls "${SERVER_DATA_DIR}/data/plugins/silo"

quiet_git pull origin main

cd /tmp/${REPO1_NAME}

quiet_git pull

if grep -q "title: "Roadmaps"" .gitroot/plugins.yml
then
    report "🟢 ${REPO1_NAME} plugin path initialized"
else
    report "🛑 ${REPO1_NAME} not initialized"
    EXIT_CODE=1
fi

sed -i -e 's/active: false/active: true/g' .gitroot/plugins.yml

echo "---" >> issues/roadmap1.md
echo "id: 22C3" >> issues/roadmap1.md
echo "priority: 50" >> issues/roadmap1.md
echo "assignee: null" >> issues/roadmap1.md
echo "kind: 'roadmap'" >> issues/roadmap1.md
echo "---" >> issues/roadmap1.md
echo "# step 1: conquers the world" >> issues/roadmap1.md
echo "" >> issues/roadmap1.md
echo "To do that just imagine the world is small." >> issues/roadmap1.md

echo "---" >> issues/roadmap2.md
echo "id: 22C3" >> issues/roadmap2.md
echo "priority: 10" >> issues/roadmap2.md
echo "assignee: null" >> issues/roadmap2.md
echo "kind: 'roadmap'" >> issues/roadmap2.md
echo "---" >> issues/roadmap2.md
echo "# step 2: profit" >> issues/roadmap2.md
echo "" >> issues/roadmap2.md
echo "Finally take in peace." >> issues/roadmap2.md

quiet_git add .
quiet_git commit -m "active silo and build first roadmap ticket"
quiet_git push origin main

mySleep 0.1

quiet_git pull

if grep -q "issues/roadmap1.md" boards/roadmap.md
then
    report "🟢 ${REPO1_NAME} roadmap initialized"
else
    report "🛑 ${REPO1_NAME} roadmap not initialized"
    EXIT_CODE=1
fi

if grep -q "issues/1.md" boards/issues.md
then
    report "🟢 ${REPO1_NAME} issues board initialized"
else
    report "🛑 ${REPO1_NAME} issues board not initialized"
    EXIT_CODE=1
fi

if grep -q "issues/1.md" boards/triage.md
then
    report "🟢 ${REPO1_NAME} triage board initialized"
else
    report "🛑 ${REPO1_NAME} triage board not initialized"
    EXIT_CODE=1
fi

quiet_git pull --rebase origin main

for (( i=0; i<=50; i++ ))
do
    echo "# My issue $i" >> issues/issue_$i.md
    echo "" >> issues/issue_$i.md
    echo "Beatiful issue" >> issues/issue_$i.md
done

quiet_git add .
quiet_git commit -m "create lot of issues"
quiet_git push origin main

mySleep 0.5

quiet_git pull

for (( i=0; i<=50; i++ ))
do
    PRIO=$(shuf -i 0-99 -n 1)
    sed -i -e "s/priority: 50/priority: $PRIO/g" issues/issue_$i.md
done

quiet_git add .
quiet_git commit -m "update random prio of lot of issues"
quiet_git push origin main

mySleep 0.05

quiet_git pull

##### Repo2 don't allow anonymous contrib
report "🏁 Repo2 don't allow anonymous contrib"

cd /tmp/${REPO2_NAME}

quiet_git pull

echo "" >> .gitroot/users.yml
echo "\"*\":" >> .gitroot/users.yml
echo "  branches:" >> .gitroot/users.yml
echo "    - name: \"*\"" >> .gitroot/users.yml
echo "  users: []" >> .gitroot/users.yml

quiet_git add .
quiet_git commit -m "block all modifications of anonymous users"
quiet_git push origin main

cd /tmp
GIT_SSH_COMMAND="ssh -i ${SSH_KEY2} -o IdentitiesOnly=yes" quiet_git clone --quiet "${REPO2_URL}" ${REPO2_NAME}_2
cd ${REPO2_NAME}_2
init_local_git user2repo2@gitroot.dev user2 ${SSH_KEY2}.pub ${SSH_KEY2}

quiet_git checkout -b tryToAddMe
quiet_git add .
quiet_git commit -m "user2 config"

EXPECTED_ERROR=1
quiet_git push origin tryToAddMe
if [[ "$?" == "0" ]]; then
    report "🛑 user2 can push on tryToAddMe branch in repo2"
    EXIT_CODE=1
else
    report "🟢 user2 can not push on tryToAddMe branch in repo2"
fi
EXPECTED_ERROR=0

##### User2 can add issue in repo1 on branch user2_issue_on_repo1
report "🏁 User2 can add issue in repo1 on branch user2_issue_on_repo1"

cd /tmp/${REPO1_NAME}_2

quiet_git pull origin main

quiet_git checkout -b user2_issue_on_repo1

echo "# My issue" >> issues/2.md
echo "" >> issues/2.md
echo "This is my issue" >> issues/2.md

quiet_git add .
quiet_git commit -m "user2 issue 1"

echo "---" >> issues/roadmap3.md
echo "id: 22E3" >> issues/roadmap3.md
echo "priority: 40" >> issues/roadmap3.md
echo "assignee: null" >> issues/roadmap3.md
echo "kind: 'roadmap'" >> issues/roadmap3.md
echo "---" >> issues/roadmap3.md
echo "# step 3: give" >> issues/roadmap3.md
echo "" >> issues/roadmap3.md
echo "Just fun." >> issues/roadmap3.md

quiet_git add .
quiet_git commit -m "user2 roadmap 3"

quiet_git push origin user2_issue_on_repo1 :user2_branch_on_repo1
push_and_wait origin user2_issue_on_repo1

quiet_git pull origin user2_issue_on_repo1

if grep -q "id:" issues/2.md
then
    report "🟢 ${REPO1_NAME}_2 issues/2.md initialized"
else
    report "🛑 ${REPO1_NAME}_2 issues/2.md not initialized"
    EXIT_CODE=1
fi

if grep -q "step 3: give" boards/roadmap.md
then
    report "🛑 ${REPO1_NAME}_2 boards/roadmap should not be updated has silo is only on main"
    EXIT_CODE=1
else
    report "🟢 ${REPO1_NAME}_2 boards/roadmap not updated"
fi

quiet_git checkout -b user2_issue2_on_repo1

echo "# My issue" >> issues/3.md
echo "" >> issues/3.md
echo "This is my issue" >> issues/3.md

quiet_git add .
quiet_git commit -m "user2 issue 2"
push_and_wait origin user2_issue2_on_repo1

quiet_git pull origin user2_issue2_on_repo1

if grep -q "id:" issues/3.md
then
    report "🟢 ${REPO1_NAME}_2 issues/3.md initialized"
else
    report "🛑 ${REPO1_NAME}_2 issues/3.md not initialized"
    EXIT_CODE=1
fi

NB_SILO=$(grep "step 3: give" boards/roadmap.md | wc -l)
if [[ "$NB_SILO" == "0" ]]; then
    report "🟢 ${REPO1_NAME}_2 silo has not been called"
else
    report "🛑 ${REPO1_NAME}_2 silo has been called $NB_SILO times"
    EXIT_CODE=1
fi

##### User1 push force in repo1 on main
report "🏁 User1 push force in repo1 on main"
cd /tmp/${REPO1_NAME}
mySleep 0.1
quiet_git pull
echo "not authorized" > issues/1.md
quiet_git add .
quiet_git commit --amend --no-edit

EXPECTED_ERROR=1
quiet_git push -f origin main
if [[ "$?" == "0" ]]; then
    report "🛑 user1 can push force on main"
    EXIT_CODE=1
else
    report "🟢 user1 can not push force on main"
fi
EXPECTED_ERROR=0
quiet_git reset --hard origin/HEAD

##### User2 push force in repo1 on branch user2_branch2_on_repo1
report "🏁 User2 push force in repo1 on branch user2_branch2_on_repo1"

cd /tmp/${REPO1_NAME}_2
quiet_git checkout main
quiet_git checkout -b user2_branch2_on_repo1

#add a commit
cd /tmp/${REPO1_NAME}
quiet_git checkout main
echo "hello" >> README.md
quiet_git add .
quiet_git commit -m "fake commit"
quiet_git push origin main

mySleep 0.1

cd /tmp/${REPO1_NAME}_2
echo "---" >> issues/roadmap4.md
echo "id: 22C3" >> issues/roadmap4.md
echo "priority: 50" >> issues/roadmap4.md
echo "assignee: null" >> issues/roadmap4.md
echo "kind: 'roadmap'" >> issues/roadmap4.md
echo "---" >> issues/roadmap4.md
echo "# step 1: conquers the world" >> issues/roadmap4.md
echo "" >> issues/roadmap4.md
echo "To do that just imagine the world is small." >> issues/roadmap4.md

quiet_git add .
quiet_git commit -m "roadmap4"
quiet_git push origin user2_branch2_on_repo1

quiet_git checkout main
quiet_git pull --rebase origin main
quiet_git checkout user2_branch2_on_repo1

quiet_git rebase -X ours main
report "🟢 Rebase ok"

quiet_git push -f origin user2_branch2_on_repo1
mySleep 0.05
report "🟢 Push -f ok"

NB_SILO=$(grep "step 1:" boards/roadmap.md | wc -l)
if [[ "$NB_SILO" == "1" ]]; then
    report "🟢 ${REPO1_NAME}_2 silo has not been called"
else
    report "🛑 ${REPO1_NAME}_2 silo has been called $NB_SILO times"
    EXIT_CODE=1
fi

##### Add grafter plugin in repo1
report "🏁 Add grafter plugin in repo1"

cd /tmp/${ROOT_REPO_NAME}
echo "- url: '${GRAFTER_WASM}'" >> .gitroot/plugins.yml
quiet_git add .
quiet_git commit -m "init grafter plugin"
quiet_git push origin main

wait_ls "${SERVER_DATA_DIR}/data/plugins/grafter"
quiet_git pull origin main

cd /tmp/${REPO1_NAME}
quiet_git pull origin main
sed -i -e 's/active: false/active: true/g' .gitroot/plugins.yml
report "🟢 ${REPO1_NAME} grafter plugin initialized"
quiet_git add .
quiet_git commit -m "active grafter plugin"
quiet_git push origin main

report "🟢 ${REPO1_NAME} grafter plugin activated"
quiet_git checkout -b graft_something
echo "hello" >> tada.md
quiet_git add .
quiet_git commit -m "first graft"
push_and_wait origin graft_something
quiet_git pull origin graft_something

NB_STATUS_DRAFT=$(grep "status: draft" grafts/graft_something.md | wc -l)
if [[ $NB_STATUS_DRAFT -ge 1 ]]; then
    report "🟢 ${REPO1_NAME} status: draft ok"
else
    report "🛑 ${REPO1_NAME} status: draft ko"
    EXIT_CODE=1
fi
report "🟢 ${REPO1_NAME} first graft created"

rm issues/1.md
quiet_git add .
quiet_git commit -m "rm issue first graft"
echo "second" > issues/2.md
quiet_git add .
quiet_git commit -m "second issue first graft"
mv issues/roadmap1.md issues/roadmap.md
quiet_git add .
quiet_git commit -m "move roadmap first graft"
push_and_wait origin graft_something
quiet_git pull origin graft_something

NB_PUSH=$(grep "Push " grafts/graft_something.md | wc -l)
NB_COMMIT=$(grep "### " grafts/graft_something.md | wc -l)
if [[ "$NB_COMMIT" == "6" ]] && [[ "$NB_PUSH" == "3" ]]; then
    report "🟢 ${REPO1_NAME} graft has 3 push and 6 commits"
else
    report "🛑 ${REPO1_NAME} graft has $NB_PUSH push and $NB_COMMIT commits"
    EXIT_CODE=1
fi

NB_COMMIT=$(git log --oneline graft_something ^main | wc -l)
if [[ $NB_COMMIT -eq 9 ]]; then
    report "🟢 ${REPO1_NAME} has 9 commits on branch graft_something"
else
    report "🛑 ${REPO1_NAME} has $NB_COMMIT commits on branch graft_something"
    EXIT_CODE=1
fi

sed -i -e 's/status: draft/status: review/g' grafts/graft_something.md
quiet_git add .
quiet_git commit -m "review first graft"
push_and_wait origin graft_something
quiet_git pull origin graft_something

NB_STATUS_DRAFT=$(grep "status: draft" grafts/graft_something.md | wc -l)
if [[ "$NB_STATUS_DRAFT" == "0" ]]; then
    report "🟢 ${REPO1_NAME} status no more draft"
else
    report "🛑 ${REPO1_NAME} status: draft ko"
    EXIT_CODE=1
fi
NB_REVIEWERS=$(grep "reviewers: " grafts/graft_something.md | wc -l)
if [[ "$NB_REVIEWERS" == "1" ]]; then
    report "🟢 ${REPO1_NAME} reviewers added"
else
    report "🛑 ${REPO1_NAME} reviewers ko"
    EXIT_CODE=1
fi
NB_MENTION_OF_REVIEW=$(grep "review first graft" grafts/graft_something.md | wc -l)
if [[ "$NB_MENTION_OF_REVIEW" == "0" ]]; then
    report "🟢 ${REPO1_NAME} commit review skipped"
else
    report "🛑 ${REPO1_NAME} commit review not skipped"
    EXIT_CODE=1
fi
report "🟢 ${REPO1_NAME} first graft ready to review"

echo "second is 2" > issues/2.md
quiet_git add .
quiet_git commit -m "second issue review first graft"
push_and_wait origin graft_something
quiet_git pull origin graft_something

NB_DIFF=$(grep -F '```diff' grafts/graft_something.md | wc -l)
if [[ "$NB_DIFF" == "2" ]]; then
    report "🟢 ${REPO1_NAME} diff added"
else
    report "🛑 ${REPO1_NAME} diff ko $NB_DIFF"
    EXIT_CODE=1
fi

sed -i -e 's/status: review/status: merge/g' grafts/graft_something.md
quiet_git add .
quiet_git commit -m "merge first graft"
quiet_git push origin graft_something

mySleep 0.5

quiet_git checkout main
quiet_git pull --rebase origin main
quiet_git fetch --prune
BRANCH_EXIST=$(git branch -r | grep "origin/graft_something" | wc -l)
if [[ "$BRANCH_EXIST" == "0" ]]; then
    report "🟢 ${REPO1_NAME} branch graft_something deleted"
else
    report "🛑 ${REPO1_NAME} branch graft_something no deleted"
    EXIT_CODE=1
fi

# TODO reactive after go-git v6
# report "🟢 ${REPO1_NAME} recreate branch graft_something for test shallow-exclude"
# quiet_git push origin graft_something

##### Add apex plugin in repo1
report "🏁 Add apex plugin in repo1"

cd /tmp/${ROOT_REPO_NAME}
echo "- url: '${APEX_WASM}'" >> .gitroot/plugins.yml
echo "- url: '${APEX_CODE_MERMAID_WASM}'" >> .gitroot/plugins.yml
echo "- url: '${APEX_CODE_WASM}'" >> .gitroot/plugins.yml
echo "- url: '${APEX_MARKDOWN_WASM}'" >> .gitroot/plugins.yml
quiet_git add .
quiet_git commit -m "init apex plugin"
quiet_git push origin main

wait_ls "${SERVER_DATA_DIR}/data/plugins/apex_markdown"
wait_ls "${SERVER_DATA_DIR}/data/plugins/apex"
wait_ls "${SERVER_DATA_DIR}/data/plugins/apex_code"
quiet_git pull origin main
report "🟢 ${ROOT_REPO_NAME} apex plugin installed"

cd /tmp/${REPO1_NAME}
quiet_git pull origin main
sed -i -e 's/active: false/active: true/g' .gitroot/plugins.yml
sed -i -e 's/layout: \[\]/layout:\
      \- glob: issues\/**\
        path: layout.html/g' .gitroot/plugins.yml
echo "<dl>" > layout.html
echo "  <dt>priority</dt><dd>{{priority}}</dd>" >> layout.html
echo "  <dt>status</dt><dd>{{status}}</dd>" >> layout.html
echo "  <dt>kind</dt><dd>{{kind}}</dd>" >> layout.html
echo "</dl>" >> layout.html
echo "<br />" >> layout.html
echo "{{content}}" >> layout.html
report "🟢 ${REPO1_NAME} apex plugin initialized"
quiet_git add .
quiet_git commit -m "active apex plugin"

push_and_wait origin main

META_FOUND=$(wget -q http://127.0.0.1:$SERVER_PORT_HTTP/repo1/issues/issue_9.html -O - | grep "<dt>" | wc -l)
if [[ $META_FOUND -eq 3 ]]; then
    report "🟢 issue_9.html has 3 meta"
else
    report "🛑 issue_9.html has no meta"
    EXIT_CODE=1
fi

quiet_git pull origin main

report "🟢 ${REPO1_NAME} apex plugin activated"
echo "# hello" > hello2.md
echo "## hello2" >> hello2.md
echo "### hello3" >> hello2.md
quiet_git add .
quiet_git commit -m "first html"

quiet_git push origin main

sed -i -e 's/style: simple.min.css/style: style.css/g' .gitroot/plugins.yml
sed -i -e 's/header: <h1>{{repo.name}}/header: <h1>{{repo.name}} <small>{{page.title}}<\/small>/g' .gitroot/plugins.yml

cp ${SCRIPT_DIR}/../server/resources/styles/simple.min.css style.css
cat ${SCRIPT_DIR}/../plugins/apex/resources/styles/add.css >> style.css
echo "body { background-color: 010409 }" >> style.css
echo "body > header { background-color: 010409; text-align: left; padding: 0 1rem }" >> style.css
echo "body > header h1 { font-size: 1rem }" >> style.css
echo "header > nav  ul { place-content: normal }" >> style.css
echo "header > nav  a { margin: 0 .5rem; border: 0 }" >> style.css

echo "# Mermaid" >> apex.md
echo "" >> apex.md
echo "Examples of rendering mermaid..." >> apex.md
echo "" >> apex.md
echo "## Mermaid flowchart" >> apex.md
echo "" >> apex.md
echo "\`\`\`mermaid" >> apex.md
echo "flowchart LR;" >> apex.md
echo "ssh-->runtime-->plugin" >> apex.md
echo "\`\`\`" >> apex.md
echo "" >> apex.md
echo "## Mermaid flowchart complexe" >> apex.md
echo "\`\`\`mermaid" >> apex.md
echo "flowchart TB" >> apex.md
echo "    subgraph Git" >> apex.md
echo "        A[ssh conn] --> B[plugin manager]" >> apex.md
echo "    end" >> apex.md
echo "    subgraph Runtime" >> apex.md
echo "        C[runtime] --> D[wasm]" >> apex.md
echo "    end" >> apex.md
echo "    subgraph Plugin" >> apex.md
echo "        E[guest] --> F[host]" >> apex.md
echo "    end" >> apex.md
echo "    B --> C" >> apex.md
echo "    D --> E" >> apex.md
echo "" >> apex.md
echo "\`\`\`" >> apex.md
echo "## Mermaid pie" >> apex.md
echo "\`\`\`mermaid" >> apex.md
echo "pie title Plugins sdk" >> apex.md
echo "         "Stable" : 20" >> apex.md
echo "         "Need work" : 80" >> apex.md
echo "\`\`\`" >> apex.md
echo "## Mermaid sequence" >> apex.md
echo "\`\`\`mermaid" >> apex.md
echo "sequenceDiagram" >> apex.md
echo "    Alice ->> Bob: Hello Bob, how are you?" >> apex.md
echo "    Bob-->>John: How about you John?" >> apex.md
echo "    Bob--x Alice: I am good thanks!" >> apex.md
echo "    Bob-x John: I am good thanks!" >> apex.md
echo "    Note right of John: Bob thinks a long<br/>long time, so long<br/>that the text does<br/>not fit on a row." >> apex.md
echo "    Bob-->Alice: Checking with John..." >> apex.md
echo "    Alice->John: Yes... John, how are you?" >> apex.md
echo "\`\`\`" >> apex.md

quiet_git add .
quiet_git commit -m "perso style"
quiet_git push origin main

##### User2 can create repo3
report "🏁 User2 can create repo3 with master branch"

cd /tmp/${ROOT_REPO_NAME}
sed -i -e 's/active: false/active: true/g' .gitroot/plugins.yml
report "🟢 ${ROOT_REPO_NAME} plugins will activate"
quiet_git add .
quiet_git commit -m "active all plugins"

push_and_wait origin main

quiet_git pull origin main
report "🟢 ${ROOT_REPO_NAME} plugins activated"

cd /tmp
GIT_SSH_COMMAND="ssh -i ${SSH_KEY2} -o IdentitiesOnly=yes" quiet_git clone --quiet "${ROOT_REPO_URL}" ${ROOT_REPO_NAME}_2
cd ${ROOT_REPO_NAME}_2
quiet_git checkout -b create_repo3
init_local_git user2root@gitroot.dev user2 ${SSH_KEY2}.pub ${SSH_KEY2}
PUB=$(cat ${SSH_KEY2}.pub)
printf "\n${REPO3_NAME}:\n  defaultbranch: master\n  owners:\n   - ${PUB}" >> .gitroot/repositories.yml
quiet_git add .
quiet_git commit -m "create repo3"
push_and_wait origin create_repo3
report "🟢 ${ROOT_REPO_NAME}_2 push create_repo3 repo"

cd /tmp/${ROOT_REPO_NAME}
quiet_git pull --rebase origin main
quiet_git fetch origin create_repo3
quiet_git checkout create_repo3
sed -i -e 's/status: draft/status: merge/g' grafts/create_repo3.md
quiet_git add .
quiet_git commit -m "merge create_repo3 graft"

push_and_wait origin create_repo3

cd /tmp
GIT_SSH_COMMAND="ssh -i ${SSH_KEY2} -o IdentitiesOnly=yes" quiet_git clone --quiet "${REPO3_URL}"

cd ${REPO3_NAME}
init_local_git user2repo3@gitroot.dev user2 ${SSH_KEY2}.pub ${SSH_KEY2}
echo "works" > README.md
quiet_git add .
quiet_git commit -m "mine readme"
quiet_git push origin master

##### Shallow
report "🏁 Shallow"

cd /tmp
rm -rf repo1_shallow
GIT_SSH_COMMAND="ssh -i ${SSH_KEY2} -o IdentitiesOnly=yes" quiet_git clone --quiet --depth 1 ssh://git@127.0.0.1:$SERVER_PORT/repo1 repo1_shallow
cd repo1_shallow
init_local_git user2repo1Shallow@gitroot.dev user2 ${SSH_KEY2}.pub ${SSH_KEY2}

NB_COMMIT=$(git rev-list HEAD --count)
if [[ $NB_COMMIT -eq 1 ]]; then
    report "🟢 repo1_shallow has 1 commit"
else
    report "🛑 repo1_shallow has $NB_COMMIT commits"
    EXIT_CODE=1
fi

quiet_git fetch --deepen 1 origin main
NB_COMMIT=$(git rev-list HEAD --count)
if [[ $NB_COMMIT -eq 2 ]]; then
    report "🟢 repo1_shallow has 2 commits"
else
    report "🛑 repo1_shallow has $NB_COMMIT commits"
    EXIT_CODE=1
fi

# TODO reactive after go-git v6
# quiet_git fetch --shallow-exclude=graft_something origin main
# NB_COMMIT=$(git rev-list HEAD --count)
# if [[ $NB_COMMIT -eq 11 ]]; then
#     report "🟢 repo1_shallow has 11 commits"
# else
#     report "🛑 repo1_shallow has $NB_COMMIT commits"
#     EXIT_CODE=1
# fi

##### User2 hack repo1
report "🏁 User2 hack repo1"

cd /tmp/${REPO1_NAME}_2
quiet_git checkout main
quiet_git pull --rebase origin main

NB_NOT_FOUND=$(wget -q http://127.0.0.1:$SERVER_PORT_HTTP/repo1/index2.html -O - | grep "Not found" | wc -l)
if [[ $NB_NOT_FOUND -eq 1 ]]; then
    report "🟢 index2.html is not found"
else
    report "🛑 index2.html exist"
    EXIT_CODE=1
fi

quiet_git checkout -b hack

#sed -i -e 's/path: branches\/\*\*\/\*/path: "\*\*\/\*"/g' .gitroot/plugins.yml
sed -i -e 's/- main/- hack/g' .gitroot/plugins.yml
sed -i -e 's/- "!main"/- "!hack"/g' .gitroot/plugins.yml

echo "powned!" > index2.md
quiet_git add .
quiet_git commit -m "hack"
push_and_wait origin hack

NB_NOT_FOUND=$(wget -q http://127.0.0.1:$SERVER_PORT_HTTP/repo1/index2.html -O - | grep "Not found" | wc -l)
if [[ $NB_NOT_FOUND -eq 1 ]]; then
    report "🟢 index2.html is not found"
else
    report "🛑 index2.html exist"
    EXIT_CODE=1
fi

HACK_LINK=$(wget -q http://127.0.0.1:$SERVER_PORT_HTTP/repo1/branches/ -O - | grep "branches/hack.html" | wc -l)
if [[ $HACK_LINK -eq 1 ]]; then
    report "🟢 hack branch is referenced"
else
    report "🛑 hack branch is not referenced"
    EXIT_CODE=1
fi

HACK_LINK=$(wget -q http://127.0.0.1:$SERVER_PORT_HTTP/repo1/branches/hack/grafts/hack.html -O - | grep "Not found" | wc -l)
if [[ $HACK_LINK -eq 1 ]]; then
    report "🛑 hack branch has no graft"
    EXIT_CODE=1
else
    report "🟢 hack branch has graft"
fi

##### install pollen plugin
report "🏁 pollen plugin"

cd /tmp/${ROOT_REPO_NAME}
quiet_git checkout main
quiet_git pull origin main
echo "- url: '${POLLEN_WASM}'" >> .gitroot/plugins.yml
quiet_git add .
quiet_git commit -m "init pollen plugin"
push_and_wait origin main
wait_ls "${SERVER_DATA_DIR}/data/plugins/pollen"
mySleep 0.1
quiet_git pull origin main
report "🟢 ${ROOT_REPO_NAME} pollen plugin installed"

cd /tmp/${REPO1_NAME}
push_and_wait origin main
quiet_git pull origin main
sed -i -e 's/active: false/active: true/g' .gitroot/plugins.yml
quiet_git add .
quiet_git commit -m "active pollen plugin"
quiet_git push origin main

echo "With rss" > README.md
quiet_git add .
quiet_git commit -m "with rss"
quiet_git push origin main

mySleep 4

RSS_CONTENT=$(wget -q http://127.0.0.1:$SERVER_PORT_HTTP/repo1/rss/all.xml -O - | grep "with rss" | wc -l)
if [[ $RSS_CONTENT -eq 2 ]]; then
    report "🟢 rss ok"
else
    report "🛑 rss ko with $RSS_CONTENT commits"
    EXIT_CODE=1
fi

##### install hop plugin
report "🏁 hop plugin"

cd /tmp/${ROOT_REPO_NAME}
echo "- url: '${HOP_WASM}'" >> .gitroot/plugins.yml
quiet_git add .
quiet_git commit -m "init hop plugin"
push_and_wait origin main
wait_ls "${SERVER_DATA_DIR}/data/plugins/hop"
mySleep 0.1
quiet_git pull origin main
report "🟢 ${ROOT_REPO_NAME} hop plugin installed"

cd /tmp/${REPO1_NAME}
push_and_wait origin main
quiet_git pull origin main
sed -i -e 's/active: false/active: true/g' .gitroot/plugins.yml
quiet_git add .
quiet_git commit -m "active hop plugin"
quiet_git push origin main

mySleep 4

quiet_git checkout -b testHop
echo "Hello from hop" >> README.md
quiet_git add .
quiet_git commit -m "test hop plugin"
push_and_wait origin testHop

quiet_git pull origin testHop
NB_REPORT=$(grep "❌ No commands executed." grafts/testHop.md | wc -l)
if [[ $NB_REPORT -eq 1 ]]; then
    report "🟢 report ok"
else
    report "🛑 report ko with $NB_REPORT reports"
    EXIT_CODE=1
fi

quiet_git checkout main

##### verify commit
report "🏁 verify commits"

cd /tmp/${ROOT_REPO_NAME}
quiet_git checkout main
quiet_git pull origin main
echo "- url: '${STIGMA_WASM}'" >> .gitroot/plugins.yml
echo "  active: true" >> .gitroot/plugins.yml
quiet_git add .
quiet_git commit -m "init stigma plugin"
push_and_wait origin main
wait_ls "${SERVER_DATA_DIR}/data/plugins/stigma"
mySleep 0.1
quiet_git pull origin main
push_and_wait origin main
quiet_git pull origin main
report "🟢 ${ROOT_REPO_NAME} stigma plugin installed"

cd /tmp/${ROOT_REPO_NAME}
cat .gitroot/allowed_signers >> $MY_LOG
git reflog show main |  awk '{ print $1 }' | xargs git verify-commit &>> $MY_LOG
report "🟢 ${ROOT_REPO_NAME}"

cd /tmp/${REPO1_NAME}
push_and_wait origin main
quiet_git pull origin main
sed -i -e 's/active: false/active: true/g' .gitroot/plugins.yml
quiet_git add .
quiet_git commit -m "active stigma plugin"
push_and_wait origin main

quiet_git pull origin main
cat .gitroot/allowed_signers >> $MY_LOG
git reflog show main |  awk '{ print $1 }' | xargs git verify-commit &>> $MY_LOG
report "🟢 ${REPO1_NAME}"

cd /tmp/${REPO2_NAME}
push_and_wait origin main
quiet_git pull origin main
sed -i -e 's/active: false/active: true/g' .gitroot/plugins.yml
quiet_git add .
quiet_git commit -m "active stigma plugin"
quiet_git push origin main
mySleep 1
quiet_git pull origin main
cat .gitroot/allowed_signers >> $MY_LOG
# TODO reactive when stigma plugin can add old user
# git reflog show main |  awk '{ print $1 }' | xargs git verify-commit &>> $MY_LOG
# report "🟢 ${REPO2_NAME}" 

##### Finish
report "🏁 Finish"
if grep -q -i "level=ERROR" $MY_LOG
then
    report "🛑 Logs contains error"
    EXIT_CODE=1
else
    report "🟢 Logs no error"
fi

if grep -q -i "WARNING: DATA RACE" $MY_LOG
then
    report "🛑 Logs contains data race"
    EXIT_CODE=1
else
    report "🟢 Logs no data race"
fi

report ""
report "✎ Find all logs in $MY_LOG"
exit $EXIT_CODE