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

# mosaic-init — Interactive agent identity, user profile, and tool config generator
#
# Usage:
#   mosaic-init                                    # Interactive mode
#   mosaic-init --name "Mosaic Agent" --style direct     # Flag overrides
#   mosaic-init --name "Mosaic Agent" --role "memory steward" --style direct \
#     --accessibility "ADHD-friendly chunking" --guardrails "Never auto-commit"

MOSAIC_HOME="${MOSAIC_HOME:-$HOME/.config/mosaic}"
SOUL_TEMPLATE="$MOSAIC_HOME/templates/SOUL.md.template"
USER_TEMPLATE="$MOSAIC_HOME/templates/USER.md.template"
TOOLS_TEMPLATE="$MOSAIC_HOME/templates/TOOLS.md.template"
SOUL_OUTPUT="$MOSAIC_HOME/SOUL.md"
USER_OUTPUT="$MOSAIC_HOME/USER.md"
TOOLS_OUTPUT="$MOSAIC_HOME/TOOLS.md"

# Defaults
AGENT_NAME=""
ROLE_DESCRIPTION=""
STYLE=""
ACCESSIBILITY=""
CUSTOM_GUARDRAILS=""

# USER.md defaults
USER_NAME=""
PRONOUNS=""
TIMEZONE=""
BACKGROUND=""
COMMUNICATION_PREFS=""
PERSONAL_BOUNDARIES=""
PROJECTS_TABLE=""

# TOOLS.md defaults
GIT_PROVIDERS_TABLE=""
CREDENTIALS_LOCATION=""
CUSTOM_TOOLS_SECTION=""

usage() {
  cat <<USAGE
Usage: $(basename "$0") [options]

Generate Mosaic identity and configuration files:
  - SOUL.md    — Agent identity contract
  - USER.md    — User profile and accessibility
  - TOOLS.md   — Machine-level tool reference

Interactive by default. Use flags to skip prompts.

Options:
  --name <name>            Agent name (e.g., "Mosaic Agent", "Assistant")
  --role <description>     Role description (e.g., "memory steward, execution partner")
  --style <style>          Communication style: direct, friendly, or formal
  --accessibility <prefs>  Accessibility preferences (e.g., "ADHD-friendly chunking")
  --guardrails <rules>     Custom guardrails (appended to defaults)
  --user-name <name>       Your name for USER.md
  --pronouns <pronouns>    Your pronouns (e.g., "He/Him")
  --timezone <tz>          Your timezone (e.g., "America/Chicago")
  --non-interactive        Fail if any required value is missing (no prompts)
  --soul-only              Only generate SOUL.md
  --force                  Overwrite existing files without prompting
  -h, --help               Show help
USAGE
}

NON_INTERACTIVE=0
SOUL_ONLY=0
FORCE=0

while [[ $# -gt 0 ]]; do
  case "$1" in
    --name) AGENT_NAME="$2"; shift 2 ;;
    --role) ROLE_DESCRIPTION="$2"; shift 2 ;;
    --style) STYLE="$2"; shift 2 ;;
    --accessibility) ACCESSIBILITY="$2"; shift 2 ;;
    --guardrails) CUSTOM_GUARDRAILS="$2"; shift 2 ;;
    --user-name) USER_NAME="$2"; shift 2 ;;
    --pronouns) PRONOUNS="$2"; shift 2 ;;
    --timezone) TIMEZONE="$2"; shift 2 ;;
    --non-interactive) NON_INTERACTIVE=1; shift ;;
    --soul-only) SOUL_ONLY=1; shift ;;
    --force) FORCE=1; shift ;;
    -h|--help) usage; exit 0 ;;
    *) echo "Unknown argument: $1" >&2; usage >&2; exit 1 ;;
  esac
done

prompt_if_empty() {
  local var_name="$1"
  local prompt_text="$2"
  local default_value="${3:-}"
  local current_value="${!var_name}"

  if [[ -n "$current_value" ]]; then
    return
  fi

  if [[ $NON_INTERACTIVE -eq 1 ]]; then
    if [[ -n "$default_value" ]]; then
      eval "$var_name=\"$default_value\""
      return
    fi
    echo "[mosaic-init] ERROR: --$var_name is required in non-interactive mode" >&2
    exit 1
  fi

  if [[ -n "$default_value" ]]; then
    prompt_text="$prompt_text [$default_value]"
  fi

  printf "%s: " "$prompt_text"
  read -r value
  if [[ -z "$value" && -n "$default_value" ]]; then
    value="$default_value"
  fi
  eval "$var_name=\"$value\""
}

prompt_multiline() {
  local var_name="$1"
  local prompt_text="$2"
  local default_value="${3:-}"
  local current_value="${!var_name}"

  if [[ -n "$current_value" ]]; then
    return
  fi

  if [[ $NON_INTERACTIVE -eq 1 ]]; then
    eval "$var_name=\"$default_value\""
    return
  fi

  echo "$prompt_text"
  printf "(Press Enter to skip, or type your response): "
  read -r value
  if [[ -z "$value" ]]; then
    value="$default_value"
  fi
  eval "$var_name=\"$value\""
}

# ── Existing file detection ────────────────────────────────────

detect_existing_config() {
  local found=0
  local existing_files=()

  [[ -f "$SOUL_OUTPUT" ]] && { found=1; existing_files+=("SOUL.md"); }
  [[ -f "$USER_OUTPUT" ]] && { found=1; existing_files+=("USER.md"); }
  [[ -f "$TOOLS_OUTPUT" ]] && { found=1; existing_files+=("TOOLS.md"); }

  if [[ $found -eq 0 || $FORCE -eq 1 ]]; then
    return 0  # No existing files or --force: proceed with fresh install
  fi

  echo "[mosaic-init] Existing configuration detected:"
  for f in "${existing_files[@]}"; do
    echo "  ✓ $f"
  done

  # Show current agent name if SOUL.md exists
  if [[ -f "$SOUL_OUTPUT" ]]; then
    local current_name
    current_name=$(grep -oP 'You are \*\*\K[^*]+' "$SOUL_OUTPUT" 2>/dev/null || true)
    if [[ -n "$current_name" ]]; then
      echo "  Agent: $current_name"
    fi
  fi
  echo ""

  if [[ $NON_INTERACTIVE -eq 1 ]]; then
    echo "[mosaic-init] Existing config found. Use --force to overwrite in non-interactive mode."
    exit 0
  fi

  echo "What would you like to do?"
  echo "  1) keep       — Keep existing files, skip init (default)"
  echo "  2) import     — Import values from existing files as defaults, then regenerate"
  echo "  3) overwrite  — Start fresh, overwrite all files"
  printf "Choose [1/2/3]: "
  read -r choice

  case "${choice:-1}" in
    1|keep)
      echo "[mosaic-init] Keeping existing configuration."
      # Still push to runtime adapters in case framework was updated
      if [[ -x "$MOSAIC_HOME/tools/_scripts/mosaic-link-runtime-assets" ]]; then
        echo "[mosaic-init] Updating runtime adapters..."
        "$MOSAIC_HOME/tools/_scripts/mosaic-link-runtime-assets"
      fi
      echo "[mosaic-init] Done. Launch with: mosaic claude"
      exit 0
      ;;
    2|import)
      echo "[mosaic-init] Importing values from existing files as defaults..."
      import_existing_values
      ;;
    3|overwrite)
      echo "[mosaic-init] Starting fresh install..."
      # Back up existing files
      local ts
      ts=$(date +%Y%m%d%H%M%S)
      for f in "${existing_files[@]}"; do
        local src="$MOSAIC_HOME/$f"
        if [[ -f "$src" ]]; then
          cp "$src" "${src}.bak.${ts}"
          echo "  Backed up $f → ${f}.bak.${ts}"
        fi
      done
      ;;
    *)
      echo "[mosaic-init] Invalid choice. Keeping existing configuration."
      exit 0
      ;;
  esac
}

import_existing_values() {
  # Import SOUL.md values
  if [[ -f "$SOUL_OUTPUT" ]]; then
    local content
    content=$(cat "$SOUL_OUTPUT")

    if [[ -z "$AGENT_NAME" ]]; then
      AGENT_NAME=$(echo "$content" | grep -oP 'You are \*\*\K[^*]+' 2>/dev/null || true)
    fi
    if [[ -z "$ROLE_DESCRIPTION" ]]; then
      ROLE_DESCRIPTION=$(echo "$content" | grep -oP 'Role identity: \K.+' 2>/dev/null || true)
    fi
    if [[ -z "$STYLE" ]]; then
      if echo "$content" | grep -q 'Be direct, concise'; then
        STYLE="direct"
      elif echo "$content" | grep -q 'Be warm and conversational'; then
        STYLE="friendly"
      elif echo "$content" | grep -q 'Use professional, structured'; then
        STYLE="formal"
      fi
    fi
  fi

  # Import USER.md values
  if [[ -f "$USER_OUTPUT" ]]; then
    local content
    content=$(cat "$USER_OUTPUT")

    if [[ -z "$USER_NAME" ]]; then
      USER_NAME=$(echo "$content" | grep -oP '\*\*Name:\*\* \K.+' 2>/dev/null || true)
    fi
    if [[ -z "$PRONOUNS" ]]; then
      PRONOUNS=$(echo "$content" | grep -oP '\*\*Pronouns:\*\* \K.+' 2>/dev/null || true)
    fi
    if [[ -z "$TIMEZONE" ]]; then
      TIMEZONE=$(echo "$content" | grep -oP '\*\*Timezone:\*\* \K.+' 2>/dev/null || true)
    fi
  fi

  # Import TOOLS.md values
  if [[ -f "$TOOLS_OUTPUT" ]]; then
    local content
    content=$(cat "$TOOLS_OUTPUT")

    if [[ -z "$CREDENTIALS_LOCATION" ]]; then
      CREDENTIALS_LOCATION=$(echo "$content" | grep -oP '\*\*Location:\*\* \K.+' 2>/dev/null || true)
    fi
  fi
}

detect_existing_config

# ── SOUL.md Generation ────────────────────────────────────────
echo "[mosaic-init] Generating SOUL.md — agent identity contract"
echo ""

# Fail-closed persona: in non-interactive mode the agent NAME must be supplied
# explicitly (--name) — never silently ship an agent named "Assistant".
if [[ $NON_INTERACTIVE -eq 1 && -z "$AGENT_NAME" ]]; then
  echo "[mosaic-init] ERROR: --name (agent name) is required in non-interactive mode." >&2
  exit 1
fi

prompt_if_empty AGENT_NAME "What name should agents use" "Assistant"
prompt_if_empty ROLE_DESCRIPTION "Agent role description" "execution partner and visibility engine"

if [[ -z "$STYLE" && $NON_INTERACTIVE -eq 0 ]]; then
  echo ""
  echo "Communication style:"
  echo "  1) direct  — Concise, no fluff, actionable"
  echo "  2) friendly — Warm but efficient, conversational"
  echo "  3) formal  — Professional, structured, thorough"
  printf "Choose [1/2/3] (default: 1): "
  read -r style_choice
  case "${style_choice:-1}" in
    1|direct) STYLE="direct" ;;
    2|friendly) STYLE="friendly" ;;
    3|formal) STYLE="formal" ;;
    *) STYLE="direct" ;;
  esac
elif [[ -z "$STYLE" ]]; then
  STYLE="direct"
fi

prompt_if_empty ACCESSIBILITY "Accessibility preferences (or 'none')" "none"

if [[ $NON_INTERACTIVE -eq 0 && -z "$CUSTOM_GUARDRAILS" ]]; then
  echo ""
  printf "Custom guardrails (optional, press Enter to skip): "
  read -r CUSTOM_GUARDRAILS
fi

# Build behavioral principles based on style + accessibility
BEHAVIORAL_PRINCIPLES=""
case "$STYLE" in
  direct)
    BEHAVIORAL_PRINCIPLES="1. Clarity over performance theater.
2. Practical execution over abstract planning.
3. Truthfulness over confidence: state uncertainty explicitly.
4. Visible state over hidden assumptions.
5. Accessibility-aware — see \`~/.config/mosaic/USER.md\` for user-specific accommodations."
    ;;
  friendly)
    BEHAVIORAL_PRINCIPLES="1. Be helpful and approachable while staying efficient.
2. Provide context and explain reasoning when helpful.
3. Truthfulness over confidence: state uncertainty explicitly.
4. Visible state over hidden assumptions.
5. Accessibility-aware — see \`~/.config/mosaic/USER.md\` for user-specific accommodations."
    ;;
  formal)
    BEHAVIORAL_PRINCIPLES="1. Maintain professional, structured communication.
2. Provide thorough analysis with explicit tradeoffs.
3. Truthfulness over confidence: state uncertainty explicitly.
4. Document decisions and rationale clearly.
5. Accessibility-aware — see \`~/.config/mosaic/USER.md\` for user-specific accommodations."
    ;;
esac

if [[ "$ACCESSIBILITY" != "none" && -n "$ACCESSIBILITY" ]]; then
  BEHAVIORAL_PRINCIPLES="$BEHAVIORAL_PRINCIPLES
6. $ACCESSIBILITY."
fi

# Build communication style section
COMMUNICATION_STYLE=""
case "$STYLE" in
  direct)
    COMMUNICATION_STYLE="- Be direct, concise, and concrete.
- Avoid fluff, hype, and anthropomorphic roleplay.
- Do not simulate certainty when facts are missing.
- Prefer actionable next steps and explicit tradeoffs."
    ;;
  friendly)
    COMMUNICATION_STYLE="- Be warm and conversational while staying focused.
- Explain your reasoning when it helps the user.
- Do not simulate certainty when facts are missing.
- Prefer actionable next steps with clear context."
    ;;
  formal)
    COMMUNICATION_STYLE="- Use professional, structured language.
- Provide thorough explanations with supporting detail.
- Do not simulate certainty when facts are missing.
- Present options with explicit tradeoffs and recommendations."
    ;;
esac

# Format custom guardrails
FORMATTED_GUARDRAILS=""
if [[ -n "$CUSTOM_GUARDRAILS" ]]; then
  FORMATTED_GUARDRAILS="- $CUSTOM_GUARDRAILS"
fi

# Verify template exists
if [[ ! -f "$SOUL_TEMPLATE" ]]; then
  echo "[mosaic-init] ERROR: Template not found: $SOUL_TEMPLATE" >&2
  echo "[mosaic-init] Run the Mosaic installer first." >&2
  exit 1
fi

# Generate SOUL.md from template using awk (handles multi-line values)
awk -v name="$AGENT_NAME" \
    -v role="$ROLE_DESCRIPTION" \
    -v principles="$BEHAVIORAL_PRINCIPLES" \
    -v comms="$COMMUNICATION_STYLE" \
    -v guardrails="$FORMATTED_GUARDRAILS" \
    '{
      gsub(/\{\{AGENT_NAME\}\}/, name)
      gsub(/\{\{ROLE_DESCRIPTION\}\}/, role)
      gsub(/\{\{BEHAVIORAL_PRINCIPLES\}\}/, principles)
      gsub(/\{\{COMMUNICATION_STYLE\}\}/, comms)
      gsub(/\{\{CUSTOM_GUARDRAILS\}\}/, guardrails)
      print
    }' "$SOUL_TEMPLATE" > "$SOUL_OUTPUT"

echo ""
echo "[mosaic-init] Generated: $SOUL_OUTPUT"
echo "[mosaic-init] Agent name: $AGENT_NAME"
echo "[mosaic-init] Style: $STYLE"

if [[ $SOUL_ONLY -eq 1 ]]; then
  # Push to runtime adapters and exit
  if [[ -x "$MOSAIC_HOME/tools/_scripts/mosaic-link-runtime-assets" ]]; then
    echo "[mosaic-init] Updating runtime adapters..."
    "$MOSAIC_HOME/tools/_scripts/mosaic-link-runtime-assets"
  fi
  echo "[mosaic-init] Done. Launch with: mosaic claude"
  exit 0
fi

# ── USER.md Generation ────────────────────────────────────────
echo ""
echo "[mosaic-init] Generating USER.md — user profile"
echo ""

prompt_if_empty USER_NAME "Your name" ""
prompt_if_empty PRONOUNS "Your pronouns" "They/Them"
prompt_if_empty TIMEZONE "Your timezone" "UTC"

prompt_multiline BACKGROUND "Your professional background (brief summary)" "(not configured)"

# Build accessibility section
ACCESSIBILITY_SECTION=""
if [[ "$ACCESSIBILITY" != "none" && -n "$ACCESSIBILITY" ]]; then
  ACCESSIBILITY_SECTION="$ACCESSIBILITY"
else
  if [[ $NON_INTERACTIVE -eq 0 ]]; then
    echo ""
    prompt_multiline ACCESSIBILITY_SECTION \
      "Accessibility or neurodivergence accommodations (or press Enter to skip)" \
      "(No specific accommodations configured. Edit this section to add any.)"
  else
    ACCESSIBILITY_SECTION="(No specific accommodations configured. Edit this section to add any.)"
  fi
fi

# Build communication preferences
if [[ -z "$COMMUNICATION_PREFS" ]]; then
  case "$STYLE" in
    direct)
      COMMUNICATION_PREFS="- Direct and concise
- No sycophancy
- Executive summaries and tables for overview"
      ;;
    friendly)
      COMMUNICATION_PREFS="- Warm and conversational
- Explain reasoning when helpful
- Balance thoroughness with brevity"
      ;;
    formal)
      COMMUNICATION_PREFS="- Professional and structured
- Thorough explanations with supporting detail
- Formal tone with explicit recommendations"
      ;;
  esac
fi

prompt_multiline PERSONAL_BOUNDARIES \
  "Personal boundaries or preferences agents should respect" \
  "(Edit this section to add any personal boundaries.)"

if [[ -z "$PROJECTS_TABLE" ]]; then
  PROJECTS_TABLE="| Project | Stack | Registry |
|---------|-------|----------|
| (none configured) | | |"
fi

if [[ ! -f "$USER_TEMPLATE" ]]; then
  echo "[mosaic-init] WARN: USER.md template not found: $USER_TEMPLATE" >&2
  echo "[mosaic-init] Skipping USER.md generation." >&2
else
  awk -v user_name="$USER_NAME" \
      -v pronouns="$PRONOUNS" \
      -v timezone="$TIMEZONE" \
      -v background="$BACKGROUND" \
      -v accessibility="$ACCESSIBILITY_SECTION" \
      -v comms="$COMMUNICATION_PREFS" \
      -v boundaries="$PERSONAL_BOUNDARIES" \
      -v projects="$PROJECTS_TABLE" \
      '{
        gsub(/\{\{USER_NAME\}\}/, user_name)
        gsub(/\{\{PRONOUNS\}\}/, pronouns)
        gsub(/\{\{TIMEZONE\}\}/, timezone)
        gsub(/\{\{BACKGROUND\}\}/, background)
        gsub(/\{\{ACCESSIBILITY_SECTION\}\}/, accessibility)
        gsub(/\{\{COMMUNICATION_PREFS\}\}/, comms)
        gsub(/\{\{PERSONAL_BOUNDARIES\}\}/, boundaries)
        gsub(/\{\{PROJECTS_TABLE\}\}/, projects)
        print
      }' "$USER_TEMPLATE" > "$USER_OUTPUT"

  echo "[mosaic-init] Generated: $USER_OUTPUT"
fi

# ── TOOLS.md Generation ───────────────────────────────────────
echo ""
echo "[mosaic-init] Generating TOOLS.md — machine-level tool reference"
echo ""

if [[ -z "$GIT_PROVIDERS_TABLE" ]]; then
  if [[ $NON_INTERACTIVE -eq 0 ]]; then
    echo "Git providers (add rows for your Gitea/GitHub/GitLab instances):"
    printf "Primary git provider URL (or press Enter to skip): "
    read -r git_url
    if [[ -n "$git_url" ]]; then
      printf "Provider name: "
      read -r git_name
      printf "CLI tool (tea/gh/glab): "
      read -r git_cli
      printf "Purpose: "
      read -r git_purpose
      GIT_PROVIDERS_TABLE="| Instance | URL | CLI | Purpose |
|----------|-----|-----|---------|
| $git_name | $git_url | \`$git_cli\` | $git_purpose |"
    else
      GIT_PROVIDERS_TABLE="| Instance | URL | CLI | Purpose |
|----------|-----|-----|---------|
| (add your git providers here) | | | |"
    fi
  else
    GIT_PROVIDERS_TABLE="| Instance | URL | CLI | Purpose |
|----------|-----|-----|---------|
| (add your git providers here) | | | |"
  fi
fi

prompt_if_empty CREDENTIALS_LOCATION "Credential file path (or 'none')" "none"

if [[ -z "$CUSTOM_TOOLS_SECTION" ]]; then
  CUSTOM_TOOLS_SECTION="## Custom Tools

(Add any machine-specific tools, scripts, or workflows here.)"
fi

if [[ ! -f "$TOOLS_TEMPLATE" ]]; then
  echo "[mosaic-init] WARN: TOOLS.md template not found: $TOOLS_TEMPLATE" >&2
  echo "[mosaic-init] Skipping TOOLS.md generation." >&2
else
  awk -v providers="$GIT_PROVIDERS_TABLE" \
      -v creds="$CREDENTIALS_LOCATION" \
      -v custom="$CUSTOM_TOOLS_SECTION" \
      '{
        gsub(/\{\{GIT_PROVIDERS_TABLE\}\}/, providers)
        gsub(/\{\{CREDENTIALS_LOCATION\}\}/, creds)
        gsub(/\{\{CUSTOM_TOOLS_SECTION\}\}/, custom)
        print
      }' "$TOOLS_TEMPLATE" > "$TOOLS_OUTPUT"

  echo "[mosaic-init] Generated: $TOOLS_OUTPUT"
fi

# ── Finalize ──────────────────────────────────────────────────

# Push to runtime adapters
if [[ -x "$MOSAIC_HOME/tools/_scripts/mosaic-link-runtime-assets" ]]; then
  echo ""
  echo "[mosaic-init] Updating runtime adapters..."
  "$MOSAIC_HOME/tools/_scripts/mosaic-link-runtime-assets"
fi

echo ""
echo "[mosaic-init] Done. Launch with: mosaic claude"
echo "[mosaic-init] Edit USER.md and TOOLS.md directly for further customization."
