#!/bin/bash
# mix-meta: Create and manage .mix.json metadata files
# Usage:
#   mix-meta init <name> [artist]           - Create new metadata file
#   mix-meta stems <file.wav> [file2.wav]   - Analyze and add stems
#   mix-meta track <id> <name> <start> <end> [section] - Add/update track
#   mix-meta get <path>                     - Get value (jq path)
#   mix-meta set <path> <value>             - Set value (jq path)
#   mix-meta show                           - Pretty print current metadata

set -euo pipefail

MIXFILE="${MIXFILE:-$(pwd)/project.mix.json}"

cmd_init() {
    local name="${1:?Usage: mix-meta init <name> [artist]}"
    local artist="${2:-Unknown}"

    cat > "$MIXFILE" <<EOF
{
  "version": 1,
  "project": {
    "name": "$name",
    "artist": "$artist",
    "date": "$(date -I)",
    "duration_s": 0,
    "sample_rate": 48000,
    "bit_depth": 16
  },
  "stems": [],
  "tracks": [],
  "transitions": [],
  "analysis": {},
  "mastering": {
    "target_lufs": -14,
    "eq_low_cut_hz": 20,
    "eq_high_cut_hz": 20000,
    "bass_mono_hz": 200,
    "limiter_ceiling_db": -0.3
  }
}
EOF
    echo "Created: $MIXFILE"
}

cmd_stems() {
    if [[ $# -eq 0 ]]; then
        echo "Usage: mix-meta stems <file.wav> [file2.wav ...]" >&2
        exit 1
    fi

    local stems="[]"
    local max_dur=0
    local idx=1

    for file in "$@"; do
        if [[ ! -f "$file" ]]; then
            echo "Warning: $file not found" >&2
            continue
        fi

        local stats=$(sox "$file" -n stats 2>&1)
        local dur=$(echo "$stats" | grep "Length s" | awk '{print $3}')
        local rms=$(echo "$stats" | grep "RMS lev dB" | head -1 | awk '{print $4}')
        local peak=$(echo "$stats" | grep "Pk lev dB" | head -1 | awk '{print $4}')
        local rms_pk=$(echo "$stats" | grep "RMS Pk dB" | head -1 | awk '{print $4}')
        local basename=$(basename "$file")

        # Track max duration
        if (( $(echo "$dur > $max_dur" | bc -l) )); then
            max_dur=$dur
        fi

        # Infer role from index
        local role="unknown"
        case $idx in
            1) role="kick" ;;
            2) role="snare" ;;
            3) role="hihat" ;;
            4) role="bass" ;;
            5) role="lead" ;;
            6) role="lead2" ;;
            7) role="breaks" ;;
            8) role="breaks" ;;
            9|10|11|12) role="ambient" ;;
        esac

        stems=$(echo "$stems" | jq --arg id "d$idx" \
            --arg file "$basename" \
            --arg role "$role" \
            --argjson rms "$rms" \
            --argjson peak "$peak" \
            --argjson rms_pk "$rms_pk" \
            '. + [{id: $id, file: $file, role: $role, rms_db: $rms, peak_db: $peak, rms_peak_db: $rms_pk}]')

        echo "Added: d$idx ($basename) - $role, RMS: ${rms}dB"
        ((idx++))
    done

    # Update mixfile
    local tmp=$(mktemp)
    jq --argjson stems "$stems" --argjson dur "$max_dur" \
        '.stems = $stems | .project.duration_s = $dur' "$MIXFILE" > "$tmp"
    mv "$tmp" "$MIXFILE"

    echo "Updated $MIXFILE with $((idx-1)) stems"
}

cmd_track() {
    local id="${1:?Usage: mix-meta track <id> <name> <start_s> <end_s> [section] [tidal_file]}"
    local name="${2:?}"
    local start="${3:?}"
    local end="${4:?}"
    local section="${5:-}"
    local tidal="${6:-}"

    local tmp=$(mktemp)
    jq --argjson id "$id" \
       --arg name "$name" \
       --argjson start "$start" \
       --argjson end "$end" \
       --arg section "$section" \
       --arg tidal "$tidal" \
       '
       .tracks = [.tracks[] | select(.id != $id)] + [{
         id: $id,
         name: $name,
         start_s: $start,
         end_s: $end,
         section: $section,
         tidal_file: $tidal,
         transition_in: "auto",
         transition_out: "auto"
       }] | .tracks |= sort_by(.id)
       ' "$MIXFILE" > "$tmp"
    mv "$tmp" "$MIXFILE"

    echo "Track $id: $name ($start - $end)"
}

cmd_get() {
    local path="${1:?Usage: mix-meta get <jq-path>}"
    jq -r "$path" "$MIXFILE"
}

cmd_set() {
    local path="${1:?Usage: mix-meta set <jq-path> <value>}"
    local value="${2:?}"

    local tmp=$(mktemp)
    jq "$path = $value" "$MIXFILE" > "$tmp"
    mv "$tmp" "$MIXFILE"
}

cmd_show() {
    if [[ ! -f "$MIXFILE" ]]; then
        echo "No mixfile found at: $MIXFILE" >&2
        exit 1
    fi
    jq '.' "$MIXFILE"
}

# Main dispatch
case "${1:-show}" in
    init)   shift; cmd_init "$@" ;;
    stems)  shift; cmd_stems "$@" ;;
    track)  shift; cmd_track "$@" ;;
    get)    shift; cmd_get "$@" ;;
    set)    shift; cmd_set "$@" ;;
    show)   cmd_show ;;
    *)      echo "Unknown command: $1" >&2; exit 1 ;;
esac
