#!/bin/bash
# Query model pricing & discounts GET /open-apis/v1/models/pricing
# Usage: SOPH_API_KEY=xxx ./curl_query_model_price.sh  (SOPH_BASE_URL overrides env)
set -e

BASE_URL="${SOPH_BASE_URL:-https://www.sophnet.com}"
API_KEY="${SOPH_API_KEY:-}"

GREEN='\033[0;32m'; RED='\033[0;31m'; YELLOW='\033[1;33m'; NC='\033[0m'
pass() { echo -e "${GREEN}[PASS]${NC} $1"; }
fail() { echo -e "${RED}[FAIL]${NC} $1"; }
warn() { echo -e "${YELLOW}[WARN]${NC} $1"; }

# 参数校验
ERR=0
if [ -z "$BASE_URL" ] || echo "$BASE_URL" | grep -qE "xxx\.com|localhost|请修改|example"; then
  warn "BASE_URL 未配置，请设置 SOPH_BASE_URL"; ERR=1
fi
if [ -z "$API_KEY" ]; then
  warn "SOPH_API_KEY 未设置，用法：SOPH_API_KEY=xxx $0"; ERR=1
fi
if [ "$ERR" = "1" ]; then
  echo ""; exit 1
fi

echo "========== /open-apis/v1/models/pricing =========="

RESP=$(curl -s -w "\n%{http_code}" "$BASE_URL/api/open-apis/v1/models/pricing" \
  -H "Authorization: Bearer $API_KEY")
HTTP_CODE=$(echo "$RESP" | tail -1)
BODY=$(echo "$RESP" | sed '$d')

if [ "$HTTP_CODE" != "200" ]; then
  fail "HTTP $HTTP_CODE"
  echo "$BODY"
  exit 1
fi

ORG_ID=$(echo "$BODY" | jq -r '.orgId')
COUNT=$(echo "$BODY" | jq '.models | length')
AIGC_COUNT=$(echo "$BODY" | jq '(.aigcModels // []) | length')
if [ "$(echo "$BODY" | jq 'has("aigcModels")')" = "true" ]; then
  pass "HTTP 200, orgId=$ORG_ID, models=$COUNT, AIGC models=$AIGC_COUNT"
else
  pass "HTTP 200, orgId=$ORG_ID, models=$COUNT (aigcModels not deployed yet)"
fi
echo ""

{
  echo "modelFamily	币种	 输入上限	  输出上限	   输入/1M	    输出/1M	     缓存命中/1M	      显式缓存/1M	       缓存创建/1M	         折扣"
  echo "-----------	----	--------	--------	-------	-------	-----------	-----------	-----------	----"
  echo "$BODY" | jq -r '
    def perM($x): if $x == null then "-" else (($x | tonumber) * 10000000 | round | . / 10000 | tostring) end;
    def lim($x): if $x == null then "∞" else ($x | tostring) end;
    def disc($o): (if $o.discount == null then 1.0 else $o.discount end) | tostring | (if contains(".") then . else . + ".0" end);
    (.models | sort_by(.modelFamily | ascii_downcase))[] | . as $m |
    if (($m.price.rules // []) | length) == 0 then
      [$m.modelFamily, ($m.price.currency // "-"), "-", "-", "-", "-", "-", "-", "-", disc($m)]
    else
      ($m.price.rules[]) as $r |
      [$m.modelFamily, ($m.price.currency // "-"), lim($r.maxInputTokens), lim($r.maxOutputTokens),
       perM($r.inputCostPerThousandTokens), perM($r.outputCostPerThousandTokens),
       perM($r.inputCostPerThousandCachedTokens), perM($r.inputCostPerThousandExplicitCachedTokens),
       perM($r.inputCostPerThousandCacheCreationTokens), disc($m)]
    end | @tsv
  '
} | LC_ALL=C awk -F'\t' '
function dw(s,  n,i,b){ n=0; for(i=1;i<=length(s);i++){ b=substr(s,i,1); if(b>="\200"){ if(b=="\342" && substr(s,i+1,2)=="\210\236") n+=1; else if(b>="\340") n+=2; else if(b>="\300") n+=1; } else n+=1 } return n }
{
  for(i=1;i<=NF;i++){ w[i]=(dw($i)>w[i]?dw($i):w[i]); line[NR,i]=$i }
} END {
  for(r=1;r<=NR;r++){ printf "  "; for(c=1;c<=NF;c++){ printf "%s", line[r,c]; for(j=1;j<=w[c]-dw(line[r,c])+3;j++) printf " " } printf "\n" }
}'

echo ""
echo "  说明: 价格单位为每 1M token；∞ 表示该档位不设上限；每个阶梯档位(rule)单独一行"
echo "        缓存命中=隐式(inputCostPerThousandCachedTokens)；显式缓存=inputCostPerThousandExplicitCachedTokens"
echo "        缓存创建=inputCostPerThousandCacheCreationTokens"
HAS=$(echo "$BODY" | jq '[.models[] | select(.discount != null)] | length')
echo "  折扣: $HAS 个配置, $((COUNT - HAS)) 个默认(1.0)"
echo ""
echo "========== AIGC Models (Image/Video/Voice) =========="

{
  echo "Category	Model	Condition	Billing	Price	Discount"
  echo "--------	------	---------	-------	-----	--------"
  echo "$BODY" | jq -r '
    def cat($c): if $c == "IMAGE_GENERATOR" then "Image" elif $c == "VIDEO_GENERATOR" then "Video"
                 elif $c == "AUDIO_TTS" then "TTS" elif $c == "AUDIO_ASR" then "ASR" else $c end;
    def disc($d): if $d == null then "1.0" elif ($d | tostring) == "1" then "1.0" else ($d | tostring) end;
    def cond($c): if (($c // {}) | length) == 0 then "-" else ($c | to_entries | map(.key + "=" + (.value | tostring)) | join(" ")) end;
    def unit($u): {"PER_IMAGE":"per image","PER_IMAGE_WITH_INPUT":"per image + input img",
                   "PER_IMAGE_PIXEL_TIER_WITH_INPUT":"per image + pixel tier","PER_SECOND":"per second",
                   "FIXED":"fixed","PER_CREDIT":"per credit","PER_MILLION_TOKENS":"per 1M token",
                   "VIDEO_COMPOSITE":"video composite","PER_MILLION_MULTI_TOKENS":"multi-dim token"}[$u] // $u // "-";
    def pcell($r):
      if $r.priceUnit == "VIDEO_COMPOSITE" then
        "out " + (($r.outputSecondPrice // 0) | tostring) + "/s + in-video " + (($r.inputVideoSecondPrice // 0) | tostring) + "/s"
          + (if ($r.inputPrice // null) != null then " + input img " + ($r.inputPrice | tostring) + "/img" else "" end)
          + (if ($r.inputFreeCount // 0) > 0 then " (first " + ($r.inputFreeCount | tostring) + " free)" else "" end)
      elif $r.priceUnit == "PER_MILLION_MULTI_TOKENS" then
        (($r.prices // {}) | to_entries
          | map(if .key == "inputTextTokens" then "txt-in" elif .key == "inputImageTokens" then "img-in"
                elif .key == "outputTextTokens" then "txt-out" elif .key == "outputImageTokens" then "img-out" else .key end
                + "=" + (.value | tostring)) | join(" / "))
      elif $r.priceUnit == "PER_IMAGE_PIXEL_TIER_WITH_INPUT" then
        (($r.price // 0) | tostring) + "/img (px<=" + (($r.pixelThreshold // 0) | tostring)
          + (if ($r.highPrice // null) != null then ", over " + ($r.highPrice | tostring) + "/img" else "" end) + ")"
          + (if ($r.inputPrice // null) != null then " + input img " + ($r.inputPrice | tostring) + "/img" else "" end)
      elif $r.priceUnit == "PER_IMAGE_WITH_INPUT" then
        (($r.price // 0) | tostring) + "/img"
          + (if ($r.inputPrice // null) != null then " + input img " + ($r.inputPrice | tostring) + "/img" else "" end)
      elif $r.priceUnit == "PER_SECOND" then
        (($r.price // 0) | tostring) + "/s"
      elif $r.priceUnit == "PER_MILLION_TOKENS" then
        (($r.price // 0) | tostring) + "/1M tok"
      elif $r.price == null then "-"
      else ($r.price | tostring) end;
    (.aigcModels // []) | sort_by(.category, .modelFamily)[] | . as $m |
    if (($m.price.rules // []) | length) > 0 then
      ($m.price.rules[]) as $r |
      [cat($m.category), $m.modelFamily, cond($r.conditions), unit($r.priceUnit), pcell($r), disc($m.discount)]
    else
      [cat($m.category), $m.modelFamily, "-",
       (if $m.price.inputPricePerTenThousandChar != null then "per 10K chars"
        elif $m.price.inputPricePerHour != null then "per hour" else "-" end),
       (if $m.price.inputPricePerTenThousandChar != null then ($m.price.inputPricePerTenThousandChar | tostring)
        elif $m.price.inputPricePerHour != null then ($m.price.inputPricePerHour | tostring) else "-" end),
       disc($m.discount)]
    end | @tsv
  '
} | LC_ALL=C awk -F'\t' '
function dw(s,  n,i,b){ n=0; for(i=1;i<=length(s); i++){ b=substr(s,i,1); if(b>="\200"){ if(b=="\342" && substr(s,i+1,2)=="\210\236") n+=1; else if(b>="\340") n+=2; else if(b>="\300") n+=1; } else n+=1 } return n }
{
  for(i=1;i<=NF;i++){ w[i]=(dw($i)>w[i]?dw($i):w[i]); line[NR,i]=$i }
} END {
  for(r=1;r<=NR;r++){ printf "  "; for(c=1;c<=NF;c++){ printf "%s", line[r,c]; for(j=1;j<=w[c]-dw(line[r,c])+3;j++) printf " " } printf "\n" }
}'

V=$(echo "$BODY" | jq '[.aigcModels[]? | select(.category != "AUDIO_TTS" and .category != "AUDIO_ASR")] | length')
VD=$(echo "$BODY" | jq '[.aigcModels[]? | select(.category != "AUDIO_TTS" and .category != "AUDIO_ASR") | select(.discount != null)] | length')
T=$(echo "$BODY" | jq '[.aigcModels[]? | select(.category == "AUDIO_TTS")] | length')
A=$(echo "$BODY" | jq '[.aigcModels[]? | select(.category == "AUDIO_ASR")] | length')
echo ""
echo "  Note: one row per billing rule; Condition distinguishes tiers (e.g. duration=6 resolution=1080P);"
echo "        input img = per input reference image; 'first N free' = free input image quota"
echo "        Discount: 1.0 = default (no config); voice models (TTS/ASR) have no discount mechanism (always 1.0)"
echo "  AIGC Summary: Image+Video $V (discounted $VD, default-1.0 $((V - VD))), TTS $T, ASR $A"
echo "========== 测试完成 =========="
