#!/bin/bash
set -euo pipefail

SCRIPT_DIR=$(realpath "${BASH_SOURCE[0]%/*}")
BUILD_ROOT=$(realpath "$SCRIPT_DIR/..")

source "$BUILD_ROOT/helpers/message-helpers.sh"
source "$BUILD_ROOT/helpers/paths.sh"
source "$BUILD_ROOT/helpers/package-metadata.sh"

OUTPUT_JSON=false
LIST_REPO=false
SOURCE_FILTER=""
SYNC_FILTER=""
RING_FILTER=""

usage() {
  cat <<EOF
Usage: $0 [OPTIONS]

List package source metadata from pkgbuilds/<package>/.omarchy/package.json.

Options:
  --json                     Output JSON for agents/scripts
  --source <aur|local>       Filter by source
  --sync <true|false>        Filter by AUR sync state
  --release-ring <ring>      Filter by release ring, e.g. fast
  --repo                     List packages from the published repo database instead
  --arch <arch>              Target architecture for --repo (default: x86_64)
  --mirror <mirror>          Mirror for --repo (edge, rc, or stable, default: edge)
  -h, --help                 Show this help message

Examples:
  $0
  $0 --release-ring fast
  $0 --source aur --sync false
  $0 --json
  $0 --repo --mirror stable
EOF
}

while [[ $# -gt 0 ]]; do
  case $1 in
  --json)
    OUTPUT_JSON=true
    shift
    ;;
  --repo)
    LIST_REPO=true
    shift
    ;;
  --source)
    SOURCE_FILTER="$2"
    shift 2
    ;;
  --sync)
    SYNC_FILTER="$2"
    shift 2
    ;;
  --release-ring)
    RING_FILTER="$2"
    shift 2
    ;;
  --arch)
    ARCH="$2"
    update_arch_paths
    shift 2
    ;;
  --mirror)
    MIRROR="$2"
    update_arch_paths
    shift 2
    ;;
  -h | --help)
    usage
    exit 0
    ;;
  *)
    print_error "Unknown option: $1"
    exit 1
    ;;
  esac
done

list_repo_packages() {
  local db_file="$REPO_DIR/omarchy.db.tar.zst"

  if [[ ! -f "$db_file" ]]; then
    echo "Repository database not found: $db_file" >&2
    exit 1
  fi

  tar -xOf "$db_file" --wildcards "*/desc" 2>/dev/null |
    awk '/%NAME%/{getline; name=$0}
         /%VERSION%/{getline; print name "-" $0}' |
    sort
}

get_pkgbuild_version() {
  local pkgdir="$1"

  if [[ -f "$pkgdir/PKGBUILD" ]]; then
    (cd "$pkgdir" && bash -c 'source PKGBUILD 2>/dev/null; if [[ -n "$epoch" ]]; then echo "${epoch}:${pkgver}-${pkgrel}"; else echo "${pkgver}-${pkgrel}"; fi') || true
  fi
}

patch_count() {
  local pkgdir="$1"
  local patches_dir="$pkgdir/.omarchy/patches"

  [[ -d "$patches_dir" ]] || { echo 0; return; }
  find "$patches_dir" -maxdepth 1 -type f -name '*.patch' | wc -l
}

post_sync_hook_enabled() {
  local pkgdir="$1"

  [[ -f "$pkgdir/.omarchy/post-sync.sh" ]] && echo true || echo false
}

package_matches_filters() {
  local source="$1"
  local sync="$2"
  local ring="$3"

  [[ -z "$SOURCE_FILTER" || "$source" == "$SOURCE_FILTER" ]] || return 1
  [[ -z "$RING_FILTER" || "$ring" == "$RING_FILTER" ]] || return 1

  if [[ -n "$SYNC_FILTER" ]]; then
    [[ "$source" == "aur" ]] || return 1
    [[ "$sync" == "$SYNC_FILTER" ]] || return 1
  fi

  return 0
}

emit_package_json() {
  local name="$1" source="$2" aur="$3" sync="$4" skip_build="$5" ring="$6" pkgrel="$7" upstream_commit="$8" patches="$9" hook="${10}" version="${11}" path="${12}"

  jq -n \
    --arg name "$name" \
    --arg source "$source" \
    --arg aur "$aur" \
    --arg sync "$sync" \
    --arg skip_build "$skip_build" \
    --arg release_ring "$ring" \
    --argjson pkgrel "$pkgrel" \
    --arg upstream_commit "$upstream_commit" \
    --argjson patches "$patches" \
    --arg hook "$hook" \
    --arg version "$version" \
    --arg path "$path" \
    '{name: $name, source: $source, aur: $aur, sync: (if $sync == "" then null else $sync == "true" end), skip_build: ($skip_build == "true"), release_ring: $release_ring, pkgrel: $pkgrel, upstream_commit: $upstream_commit, patches: $patches, post_sync_hook: ($hook == "true"), version: $version, path: $path}'
}

if [[ "$LIST_REPO" == true ]]; then
  list_repo_packages
  exit 0
fi

rows_file=$(mktemp)
json_file=$(mktemp)
trap 'rm -f "$rows_file" "$json_file"' EXIT

first_json=true
printf '[\n' > "$json_file"

while IFS= read -r pkgdir; do
  name=$(basename "$pkgdir")
  metadata=$(metadata_file_for_dir "$pkgdir")
  source=$(jq -r '.source // ""' "$metadata")
  ring=$(jq -r '.release_ring // ""' "$metadata")
  aur=$(jq -r --arg name "$name" '.aur // $name' "$metadata")
  aur_display="$aur"
  [[ "$aur_display" == "$name" ]] && aur_display=""

  if [[ "$source" == "aur" ]]; then
    sync=$(jq -r 'if has("sync") then .sync else true end' "$metadata")
  else
    sync=""
  fi
  skip_build=$(jq -r 'if has("skip_build") then .skip_build else false end' "$metadata")

  package_matches_filters "$source" "$sync" "$ring" || continue

  pkgrel=$(jq -c '.pkgrel // {}' "$metadata")
  pkgrel_display=$(jq -r '.pkgrel // {} | to_entries | map("\(.key)=\(.value)") | join(",")' "$metadata")
  upstream_commit=$(jq -r '.upstream_commit // ""' "$metadata")
  upstream_display="${upstream_commit:0:7}"
  patches=$(patch_count "$pkgdir" | tr -d ' ')
  hook=$(post_sync_hook_enabled "$pkgdir")
  hook_display="$([[ "$hook" == true ]] && echo yes || echo no)"
  version=$(get_pkgbuild_version "$pkgdir")
  relpath=${pkgdir#"$BUILD_ROOT/"}

  printf '%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\n' \
    "$name" \
    "$source" \
    "$aur_display" \
    "$([[ -n "$sync" ]] && [[ "$sync" == true ]] && echo yes || ([[ "$sync" == false ]] && echo no || echo -))" \
    "$([[ "$skip_build" == true ]] && echo yes || echo no)" \
    "$ring" \
    "$pkgrel_display" \
    "$upstream_display" \
    "$patches" \
    "$hook_display" \
    "$version" \
    "$relpath" >> "$rows_file"

  if [[ "$first_json" == false ]]; then
    printf ',\n' >> "$json_file"
  fi
  emit_package_json "$name" "$source" "$aur" "$sync" "$skip_build" "$ring" "$pkgrel" "$upstream_commit" "$patches" "$hook" "$version" "$relpath" >> "$json_file"
  first_json=false
done < <(package_dirs)

printf '\n]\n' >> "$json_file"

if [[ "$OUTPUT_JSON" == true ]]; then
  jq . "$json_file"
  exit 0
fi

if command -v gum >/dev/null 2>&1; then
  gum table --print --separator $'\t' \
    --columns Package,Source,AUR,Sync,Skip_Build,Release_Ring,Pkgrel,Upstream,Patches,Post_Sync,Version,Path \
    < "$rows_file"
else
  {
    printf 'Package\tSource\tAUR\tSync\tSkip_Build\tRelease_Ring\tPkgrel\tUpstream\tPatches\tPost_Sync\tVersion\tPath\n'
    cat "$rows_file"
  } | column -t -s $'\t'
fi
