#!/usr/bin/env bash
# report_execution_json — Genera un JSON de reporte de ejecucion siguiendo el estandar fn-registry.
#
# USO (sourced):
#   source report_execution_json.sh
#   report_execution_json "backup_db" "partial" 2 \
#       "2026-04-01T02:00:00Z" "2026-04-01T02:00:03Z" 3000 /tmp/steps.tsv
#
# USO (ejecutado directamente):
#   bash report_execution_json.sh "backup_db" "partial" 2 \
#       "2026-04-01T02:00:00Z" "2026-04-01T02:00:03Z" 3000 /tmp/steps.tsv
#
# FORMATO steps_file (TSV sin cabecera, 6 columnas):
#   name<TAB>action<TAB>status<TAB>elapsed_ms<TAB>output<TAB>error
#   Los campos output y error pueden estar vacios.
#   status valido: ok | error
#
# NOTA sobre IFS y tabs: bash trata tab como whitespace en IFS y colapsa
# campos vacios consecutivos. Se usa 'cut -f N' para parsear cada columna
# de forma correcta cuando hay campos vacios entre tabs.

report_execution_json() {
    local flow_name="$1"
    local status="$2"
    local exit_code="$3"
    local started_at="$4"
    local ended_at="$5"
    local duration_ms="$6"
    local steps_file="$7"

    if [[ -z "$flow_name" || -z "$status" || -z "$exit_code" || \
          -z "$started_at" || -z "$ended_at" || -z "$duration_ms" || \
          -z "$steps_file" ]]; then
        echo "report_execution_json: uso: report_execution_json <flow_name> <status> <exit_code> <started_at> <ended_at> <duration_ms> <steps_file>" >&2
        return 1
    fi

    if [[ ! -f "$steps_file" ]]; then
        echo "report_execution_json: archivo de pasos no encontrado: $steps_file" >&2
        return 1
    fi

    if command -v jq >/dev/null 2>&1; then
        _report_execution_json_jq \
            "$flow_name" "$status" "$exit_code" \
            "$started_at" "$ended_at" "$duration_ms" "$steps_file"
    else
        _report_execution_json_printf \
            "$flow_name" "$status" "$exit_code" \
            "$started_at" "$ended_at" "$duration_ms" "$steps_file"
    fi
}

# --- Implementacion con jq ---

_report_execution_json_jq() {
    local flow_name="$1" status="$2" exit_code="$3"
    local started_at="$4" ended_at="$5" duration_ms="$6" steps_file="$7"

    local steps_ok=0 steps_failed=0
    local steps_json="[]"

    while IFS= read -r line; do
        [[ -z "$line" ]] && continue

        local s_name s_action s_status s_elapsed s_output s_error
        s_name=$(printf '%s' "$line" | cut -f1)
        s_action=$(printf '%s' "$line" | cut -f2)
        s_status=$(printf '%s' "$line" | cut -f3)
        s_elapsed=$(printf '%s' "$line" | cut -f4)
        s_output=$(printf '%s' "$line" | cut -f5)
        s_error=$(printf '%s' "$line" | cut -f6)

        [[ -z "$s_name" ]] && continue

        local step_obj
        step_obj=$(jq -n \
            --arg   name     "$s_name" \
            --arg   action   "$s_action" \
            --arg   st       "$s_status" \
            --argjson ms     "${s_elapsed:-0}" \
            --arg   output   "$s_output" \
            --arg   error    "$s_error" \
            '{name: $name, action: $action, status: $st, elapsed_ms: $ms}
             + (if $output != "" then {output: $output} else {} end)
             + (if $error  != "" then {error:  $error}  else {} end)')

        steps_json=$(printf '%s' "$steps_json" | jq --argjson step "$step_obj" '. + [$step]')

        if [[ "$s_status" == "ok" ]]; then
            ((steps_ok++))
        else
            ((steps_failed++))
        fi
    done < "$steps_file"

    local steps_total=$(( steps_ok + steps_failed ))

    jq -n \
        --arg     name         "$flow_name" \
        --arg     st           "$status" \
        --argjson exit_code    "$exit_code" \
        --arg     started_at   "$started_at" \
        --arg     ended_at     "$ended_at" \
        --argjson duration_ms  "$duration_ms" \
        --argjson total        "$steps_total" \
        --argjson ok           "$steps_ok" \
        --argjson failed       "$steps_failed" \
        --argjson steps        "$steps_json" \
        '{
            name:         $name,
            status:       $st,
            exit_code:    $exit_code,
            started_at:   $started_at,
            ended_at:     $ended_at,
            duration_ms:  $duration_ms,
            steps_total:  $total,
            steps_ok:     $ok,
            steps_failed: $failed,
            steps:        $steps
        }'
}

# --- Implementacion con printf (fallback sin jq) ---

_json_escape_rj() {
    local s="$1"
    s="${s//\\/\\\\}"
    s="${s//\"/\\\"}"
    s="${s//$'\n'/\\n}"
    s="${s//$'\r'/\\r}"
    s="${s//$'\t'/\\t}"
    printf '%s' "$s"
}

_report_execution_json_printf() {
    local flow_name="$1" status="$2" exit_code="$3"
    local started_at="$4" ended_at="$5" duration_ms="$6" steps_file="$7"

    local steps_ok=0 steps_failed=0
    local steps_parts=()

    while IFS= read -r line; do
        [[ -z "$line" ]] && continue

        local s_name s_action s_status s_elapsed s_output s_error
        s_name=$(printf '%s' "$line" | cut -f1)
        s_action=$(printf '%s' "$line" | cut -f2)
        s_status=$(printf '%s' "$line" | cut -f3)
        s_elapsed=$(printf '%s' "$line" | cut -f4)
        s_output=$(printf '%s' "$line" | cut -f5)
        s_error=$(printf '%s' "$line" | cut -f6)

        [[ -z "$s_name" ]] && continue

        local part
        part=$(printf '{"name":"%s","action":"%s","status":"%s","elapsed_ms":%s' \
            "$(_json_escape_rj "$s_name")" \
            "$(_json_escape_rj "$s_action")" \
            "$(_json_escape_rj "$s_status")" \
            "${s_elapsed:-0}")

        if [[ -n "$s_output" ]]; then
            part+=",\"output\":\"$(_json_escape_rj "$s_output")\""
        fi
        if [[ -n "$s_error" ]]; then
            part+=",\"error\":\"$(_json_escape_rj "$s_error")\""
        fi
        part+="}"

        steps_parts+=("$part")

        if [[ "$s_status" == "ok" ]]; then
            ((steps_ok++))
        else
            ((steps_failed++))
        fi
    done < "$steps_file"

    local steps_total=$(( steps_ok + steps_failed ))

    local steps_array="["
    local first=1
    for part in "${steps_parts[@]}"; do
        if [[ $first -eq 1 ]]; then
            steps_array+="$part"
            first=0
        else
            steps_array+=",$part"
        fi
    done
    steps_array+="]"

    printf '{"name":"%s","status":"%s","exit_code":%s,"started_at":"%s","ended_at":"%s","duration_ms":%s,"steps_total":%s,"steps_ok":%s,"steps_failed":%s,"steps":%s}\n' \
        "$(_json_escape_rj "$flow_name")" \
        "$(_json_escape_rj "$status")" \
        "$exit_code" \
        "$(_json_escape_rj "$started_at")" \
        "$(_json_escape_rj "$ended_at")" \
        "$duration_ms" \
        "$steps_total" \
        "$steps_ok" \
        "$steps_failed" \
        "$steps_array"
}

# Permitir ejecucion directa (no solo sourced)
if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then
    report_execution_json "$@"
fi
