package billing

import (
	"encoding/json"
	"testing"
)

func TestCalculateTextPointsRoundsUpToPointCent(t *testing.T) {
	pricing := TextPricing{Mode: TextBillingPerToken, InputPerM: "100.0000", OutputPerM: "300.0000"}
	amount, err := CalculateTextPoints(pricing, TextUsage{Input: 120, Output: 30})
	if err != nil {
		t.Fatal(err)
	}
	if amount != "0.03" {
		t.Fatalf("expected 0.03 points, got %s", amount)
	}
	amount, err = CalculateTextPoints(pricing, TextUsage{Input: 1})
	if err != nil {
		t.Fatal(err)
	}
	if amount != "0.01" {
		t.Fatalf("expected minimum positive charge 0.01, got %s", amount)
	}
}

func TestTextPricingSnapshot(t *testing.T) {
	pricing := TextPricing{Mode: TextBillingPerToken, InputPerM: "1250.0000", OutputPerM: "2500.0000"}
	parsed, err := ParseTextPricingSnapshot(pricing.MarshalSnapshot())
	if err != nil {
		t.Fatal(err)
	}
	if parsed != pricing {
		t.Fatalf("unexpected snapshot: %s", json.RawMessage(pricing.MarshalSnapshot()))
	}
}

func TestTextPricingSnapshotRejectsLegacyThousandTokenRates(t *testing.T) {
	_, err := ParseTextPricingSnapshot(json.RawMessage(`{"mode":"per_token","input_per_k":"0.1000","output_per_k":"0.3000","max_output_tokens":1000}`))
	if err == nil {
		t.Fatal("expected legacy thousand-token snapshot to be rejected")
	}
}

func TestCalculateTextPointsUsesMillionTokens(t *testing.T) {
	pricing := TextPricing{Mode: TextBillingPerToken, InputPerM: "10", OutputPerM: "20"}
	amount, err := CalculateTextPoints(pricing, TextUsage{Input: 1_000_000})
	if err != nil {
		t.Fatal(err)
	}
	if amount != "10.00" {
		t.Fatalf("expected 10.00 points for one million input tokens, got %s", amount)
	}
}

func TestCalculateTextReservePointsUsesDoubleInputAsEstimatedOutput(t *testing.T) {
	pricing := TextPricing{Mode: TextBillingPerToken, InputPerM: "10", OutputPerM: "20"}
	amount, err := CalculateTextReservePoints(pricing, 1_000_000)
	if err != nil {
		t.Fatal(err)
	}
	if amount != "50.00" {
		t.Fatalf("expected 50.00 points for input plus double-input output estimate, got %s", amount)
	}
}

func TestEstimateTextTokens(t *testing.T) {
	if got := EstimateTextTokens("中文ABCD"); got != 3 {
		t.Fatalf("expected 3 estimated tokens, got %d", got)
	}
}
