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

SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
LEADTECH_ROOT="${LEADTECH:-$(cd "$SCRIPT_DIR/.." && pwd)}"
PROJECTS_CONF="${PROJECTS_CONF:-$LEADTECH_ROOT/_projects.conf}"

PROJECT_ROOT=""
PROJECT_NAME=""
STACK_OVERRIDE=""
SCOPE_OVERRIDE=""
STATE_OVERRIDE=""
SYNC_EXISTING="false"

usage() {
  cat <<USAGE
Usage: sync-projects-conf.sh [options]

Options:
  --project-root <path>   Project root directory (default: current directory)
  --project-name <name>   Project name override (default: basename project-root)
  --stack <value>         Stack override
  --scope <value>         Scope override (perso|mindleaf|lab|archive)
  --state <value>         State override
  --sync-existing         Update existing line (safe mode: preserve scope/state unless explicit override)
  -h, --help              Show help
USAGE
}

while [ $# -gt 0 ]; do
  case "$1" in
    --project-root)
      PROJECT_ROOT="$2"
      shift 2
      ;;
    --project-name)
      PROJECT_NAME="$2"
      shift 2
      ;;
    --stack)
      STACK_OVERRIDE="$2"
      shift 2
      ;;
    --scope)
      SCOPE_OVERRIDE="$2"
      shift 2
      ;;
    --state)
      STATE_OVERRIDE="$2"
      shift 2
      ;;
    --sync-existing)
      SYNC_EXISTING="true"
      shift
      ;;
    -h|--help)
      usage
      exit 0
      ;;
    *)
      echo "Erreur: option inconnue: $1" >&2
      usage >&2
      exit 1
      ;;
  esac
done

PROJECT_ROOT="${PROJECT_ROOT:-$PWD}"
if [ ! -d "$PROJECT_ROOT" ]; then
  echo "Erreur: project-root introuvable: $PROJECT_ROOT" >&2
  exit 1
fi

if [ ! -f "$PROJECTS_CONF" ]; then
  echo "Erreur: _projects.conf introuvable: $PROJECTS_CONF" >&2
  exit 1
fi

trim() {
  local s="$1"
  # shellcheck disable=SC2001
  s="$(echo "$s" | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//')"
  printf '%s' "$s"
}

infer_stack() {
  local root="$1"
  local out=()

  if [ -f "$root/pnpm-workspace.yaml" ]; then
    out+=("pnpm monorepo")
  fi

  if [ -f "$root/package.json" ]; then
    if grep -Eq '"@nestjs/' "$root/package.json"; then out+=("NestJS"); fi
    if grep -Eq '"next"' "$root/package.json"; then out+=("Next.js"); fi
    if grep -Eq '"expo"' "$root/package.json"; then out+=("Expo"); fi
    if grep -Eq '"react-native"' "$root/package.json"; then out+=("React Native"); fi
    if grep -Eq '"prisma"|"@prisma/' "$root/package.json"; then out+=("Prisma"); fi
  fi

  if [ -f "$root/prisma/schema.prisma" ] && grep -qi 'provider *= *"postgresql"' "$root/prisma/schema.prisma"; then
    out+=("PostgreSQL")
  fi

  if [ -f "$root/CLAUDE.md" ]; then
    local from_claude
    from_claude="$(awk '
      BEGIN {in_stack=0}
      /^## Stack/ {in_stack=1; next}
      /^## / {if (in_stack) exit}
      in_stack && /^- / {sub(/^- /, ""); print}
    ' "$root/CLAUDE.md" | paste -sd ' + ' -)"
    from_claude="$(trim "$from_claude")"
    if [ -n "$from_claude" ]; then
      printf '%s' "$from_claude"
      return
    fi
  fi

  if [ ${#out[@]} -eq 0 ]; then
    printf '%s' "stack-a-completer"
  else
    local joined
    joined="$(printf '%s\n' "${out[@]}" | awk '!seen[$0]++' | paste -sd ' + ' -)"
    printf '%s' "$joined"
  fi
}

infer_scope() {
  local root="$1"
  case "$root" in
    *"/__Mindleaf/"*) printf '%s' "mindleaf" ;;
    *"/Labs/"*) printf '%s' "lab" ;;
    *"/Archives_Projets/"*) printf '%s' "archive" ;;
    *) printf '%s' "perso" ;;
  esac
}

infer_state() {
  local root="$1"
  local sprint_status_file="$root/_bmad-output/implementation-artifacts/sprint-status.yaml"
  local stories_dir="$root/_bmad-output/implementation-artifacts/stories"
  local first_story
  local latest_story
  local epic_num

  if [ -f "$sprint_status_file" ]; then
    local in_dev="false"
    local line trimmed key val story_epic
    local active_epic="" active_ts="-1"
    local prep_epic=""
    local declared_in_progress_epic=""
    local story_file story_ts
    local -a matches=()

    while IFS= read -r line || [ -n "$line" ]; do
      if [ "$line" = "development_status:" ]; then
        in_dev="true"
        continue
      fi

      if [ "$in_dev" = "true" ] && [ -n "$(trim "$line")" ] && [[ ! "$line" =~ ^[[:space:]] ]]; then
        in_dev="false"
      fi
      [ "$in_dev" = "true" ] || continue

      trimmed="$(trim "$line")"
      [[ "$trimmed" == *:* ]] || continue
      key="$(trim "${trimmed%%:*}")"
      val="$(trim "${trimmed#*:}")"

      if [[ "$key" =~ ^epic-([0-9]+)$ ]]; then
        story_epic="${BASH_REMATCH[1]}"
        if [ "$val" = "in-progress" ]; then
          if [ -z "$declared_in_progress_epic" ] || [ "$story_epic" -lt "$declared_in_progress_epic" ]; then
            declared_in_progress_epic="$story_epic"
          fi
        fi
        continue
      fi

      if [[ "$key" =~ ^([0-9]+)-[0-9]+[a-z]?-.*$ ]]; then
        story_epic="${BASH_REMATCH[1]}"
        if [ "$val" = "in-progress" ] || [ "$val" = "review" ]; then
          matches=()
          shopt -s nullglob
          matches=( "$stories_dir/epic-$story_epic/${key}"*.md )
          shopt -u nullglob
          story_ts="0"
          if [ ${#matches[@]} -gt 0 ]; then
            story_file="${matches[0]}"
            story_ts="$(stat -c %Y "$story_file" 2>/dev/null || printf '0')"
          fi
          if [ "$story_ts" -gt "$active_ts" ] || { [ "$story_ts" -eq "$active_ts" ] && { [ -z "$active_epic" ] || [ "$story_epic" -gt "$active_epic" ]; }; }; then
            active_ts="$story_ts"
            active_epic="$story_epic"
          fi
        elif [ "$val" = "ready-for-dev" ] || [ "$val" = "backlog" ]; then
          if [ -z "$prep_epic" ] || [ "$story_epic" -lt "$prep_epic" ]; then
            prep_epic="$story_epic"
          fi
        fi
      fi
    done < "$sprint_status_file"

    if [ -n "$active_epic" ]; then
      printf 'Epic %s en cours' "$active_epic"
      return
    fi
    if [ -n "$prep_epic" ]; then
      printf 'Epic %s en préparation' "$prep_epic"
      return
    fi
    if [ -n "$declared_in_progress_epic" ]; then
      printf 'Epic %s en préparation' "$declared_in_progress_epic"
      return
    fi
  fi

  if [ -d "$stories_dir" ]; then
    first_story="$(find "$stories_dir" -maxdepth 2 -type f -name '*.md' \
      ! -name 'epic-*-retro*.md' -print -quit 2>/dev/null)"
    if [ -n "$first_story" ]; then
      latest_story="$(find "$stories_dir" -maxdepth 2 -type f -name '*.md' \
        ! -name 'epic-*-retro*.md' -print 2>/dev/null \
        | xargs ls -1t 2>/dev/null \
        | head -n 1)"
      if [ -n "$latest_story" ]; then
        epic_num="$(echo "$latest_story" | sed -n 's#.*\/epic-\([0-9][0-9]*\)\/.*#\1#p')"
        if [ -n "$epic_num" ]; then
          printf 'Epic %s en préparation' "$epic_num"
          return
        fi
      fi
    fi
  fi

  printf '%s' "dev"
}

is_progress_state() {
  local state="$1"
  [ -z "$state" ] && return 0
  case "$state" in
    dev|active) return 0 ;;
  esac
  echo "$state" | grep -Eq '^Epic [0-9]+ en (préparation|cours)$'
}

PROJECT_NAME="${PROJECT_NAME:-$(basename "$PROJECT_ROOT")}"
STACK_INFERRED="$(infer_stack "$PROJECT_ROOT")"
SCOPE_INFERRED="$(infer_scope "$PROJECT_ROOT")"
STATE_INFERRED="$(infer_state "$PROJECT_ROOT")"
STACK="${STACK_OVERRIDE:-$STACK_INFERRED}"
SCOPE="${SCOPE_OVERRIDE:-$SCOPE_INFERRED}"
STATE="${STATE_OVERRIDE:-$STATE_INFERRED}"

if ! [[ "$SCOPE" =~ ^(perso|mindleaf|lab|archive)$ ]]; then
  echo "Erreur: scope invalide '$SCOPE' (attendu: perso|mindleaf|lab|archive)" >&2
  exit 1
fi

if grep -q "^${PROJECT_NAME}|" "$PROJECTS_CONF"; then
  if [ "$SYNC_EXISTING" != "true" ]; then
    echo "OK: projet déjà présent dans _projects.conf: $PROJECT_NAME"
    exit 0
  fi

  existing_line="$(grep "^${PROJECT_NAME}|" "$PROJECTS_CONF" | head -n 1)"
  IFS='|' read -r _ existing_stack existing_scope existing_state <<EOF
$existing_line
EOF

  # Safe sync defaults for existing entries:
  # - stack: preserve existing unless explicit override, or existing is placeholder
  # - scope/state: keep existing unless explicitly overridden
  if [ -n "$STACK_OVERRIDE" ]; then
    TARGET_STACK="$STACK_OVERRIDE"
  elif [ -z "$existing_stack" ] || [ "$existing_stack" = "stack-a-completer" ]; then
    if [ "$STACK_INFERRED" = "stack-a-completer" ] || [ -z "$STACK_INFERRED" ]; then
      TARGET_STACK="$existing_stack"
    else
      TARGET_STACK="$STACK_INFERRED"
    fi
  else
    TARGET_STACK="$existing_stack"
  fi

  if [ -n "$SCOPE_OVERRIDE" ]; then
    TARGET_SCOPE="$SCOPE_OVERRIDE"
  else
    TARGET_SCOPE="$existing_scope"
  fi

  if [ -n "$STATE_OVERRIDE" ]; then
    TARGET_STATE="$STATE_OVERRIDE"
  elif is_progress_state "$existing_state"; then
    TARGET_STATE="$STATE_INFERRED"
  else
    TARGET_STATE="$existing_state"
  fi

  if ! [[ "$TARGET_SCOPE" =~ ^(perso|mindleaf|lab|archive)$ ]]; then
    echo "Erreur: scope invalide '$TARGET_SCOPE' (attendu: perso|mindleaf|lab|archive)" >&2
    exit 1
  fi

  tmp="$(mktemp)"
  awk -F'|' -v OFS='|' -v n="$PROJECT_NAME" -v st="$TARGET_STACK" -v sc="$TARGET_SCOPE" -v et="$TARGET_STATE" '
    $0 ~ /^#/ || NF < 4 { print; next }
    $1 == n { print $1, st, sc, et; next }
    { print }
  ' "$PROJECTS_CONF" > "$tmp"
  mv "$tmp" "$PROJECTS_CONF"
  echo "OK: projet synchronisé dans _projects.conf: $PROJECT_NAME"
  exit 0
fi

last_char="$(tail -c 1 "$PROJECTS_CONF" 2>/dev/null || true)"
if [ -n "$last_char" ]; then
  echo >> "$PROJECTS_CONF"
fi

printf '%s|%s|%s|%s\n' "$PROJECT_NAME" "$STACK" "$SCOPE" "$STATE" >> "$PROJECTS_CONF"
echo "OK: projet ajouté à _projects.conf: $PROJECT_NAME"
