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

# ====== Fill these values before running ======
GITHUB_TOKEN="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"
GITEA_TOKEN="1928666b31ab82a12a87a9050c764d0e534e2f21"

GH_ORG="ai-camerist"
GITEA_OWNER="banlv"
GITEA_URL="https://gitea.banlv-ai.com"

# Set to true if you want Gitea to keep pulling from GitHub after migration.
MIRROR=false
MIRROR_INTERVAL="8h"

# Migrated repository options.
MIGRATE_ISSUES=true
MIGRATE_LABELS=true
MIGRATE_MILESTONES=true
MIGRATE_PULL_REQUESTS=true
MIGRATE_RELEASES=true
MIGRATE_WIKI=true
MIGRATE_LFS=true

require_cmd() {
  if ! command -v "$1" >/dev/null 2>&1; then
    echo "Missing required command: $1" >&2
    exit 1
  fi
}

api_get() {
  curl -fsSL \
    -H "Accept: application/vnd.github+json" \
    -H "Authorization: Bearer ${GITHUB_TOKEN}" \
    "$1"
}

gitea_repo_status() {
  local repo_name="$1"

  curl -sS -o /dev/null -w "%{http_code}" \
    -H "Authorization: token ${GITEA_TOKEN}" \
    "${GITEA_URL}/api/v1/repos/${GITEA_OWNER}/${repo_name}"
}

migrate_repo() {
  local repo_json="$1"
  local repo_name clone_url description private status payload

  repo_name="$(echo "$repo_json" | jq -r '.name')"
  clone_url="$(echo "$repo_json" | jq -r '.clone_url')"
  description="$(echo "$repo_json" | jq -r '.description // ""')"
  private="$(echo "$repo_json" | jq -r '.private')"

  echo "==> Migrating ${GH_ORG}/${repo_name}"

  status="$(gitea_repo_status "$repo_name")"
  if [ "$status" = "200" ]; then
    echo "    Skip existing repository: ${GITEA_OWNER}/${repo_name}"
    return 0
  fi

  payload="$(jq -n \
    --arg clone_addr "$clone_url" \
    --arg repo_name "$repo_name" \
    --arg repo_owner "$GITEA_OWNER" \
    --arg description "$description" \
    --arg auth_token "$GITHUB_TOKEN" \
    --arg mirror_interval "$MIRROR_INTERVAL" \
    --argjson private "$private" \
    --argjson mirror "$MIRROR" \
    --argjson issues "$MIGRATE_ISSUES" \
    --argjson labels "$MIGRATE_LABELS" \
    --argjson milestones "$MIGRATE_MILESTONES" \
    --argjson pull_requests "$MIGRATE_PULL_REQUESTS" \
    --argjson releases "$MIGRATE_RELEASES" \
    --argjson wiki "$MIGRATE_WIKI" \
    --argjson lfs "$MIGRATE_LFS" \
    '{
      service: "github",
      clone_addr: $clone_addr,
      repo_name: $repo_name,
      repo_owner: $repo_owner,
      description: $description,
      auth_token: $auth_token,
      private: $private,
      issues: $issues,
      labels: $labels,
      milestones: $milestones,
      pull_requests: $pull_requests,
      releases: $releases,
      wiki: $wiki,
      lfs: $lfs,
      mirror: $mirror,
      mirror_interval: $mirror_interval
    }')"

  curl -fsSL -X POST \
    -H "Authorization: token ${GITEA_TOKEN}" \
    -H "Content-Type: application/json" \
    -d "$payload" \
    "${GITEA_URL}/api/v1/repos/migrate" >/dev/null

  echo "    Done: ${GITEA_OWNER}/${repo_name}"
}

main() {
  require_cmd curl
  require_cmd jq

  if [ "$GITHUB_TOKEN" = "ghp_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" ]; then
    echo "Please edit GITHUB_TOKEN in this script first." >&2
    exit 1
  fi

  if [ "$GITEA_TOKEN" = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" ]; then
    echo "Please edit GITEA_TOKEN in this script first." >&2
    exit 1
  fi

  local page repos_json count total
  page=1
  total=0

  while true; do
    echo "Fetching GitHub repositories page ${page}..."

    repos_json="$(api_get "https://api.github.com/orgs/${GH_ORG}/repos?type=all&per_page=100&page=${page}&sort=full_name&direction=asc")"
    count="$(echo "$repos_json" | jq 'length')"

    if [ "$count" -eq 0 ]; then
      break
    fi

    while IFS= read -r repo; do
      migrate_repo "$repo"
      total=$((total + 1))
    done < <(echo "$repos_json" | jq -c '.[]')

    page=$((page + 1))
  done

  echo "All done. Processed repositories: ${total}"
}

main "$@"
