package finance

import (
	"crypto/sha512"
	"encoding/hex"
	"testing"
)

// sign mirrors the Midtrans notification signature formula over the RAW
// gross_amount string.
func sign(orderID, statusCode, grossAmount, serverKey string) string {
	sum := sha512.Sum512([]byte(orderID + statusCode + grossAmount + serverKey))
	return hex.EncodeToString(sum[:])
}

func TestVerifyMidtransSignature(t *testing.T) {
	const key = "test-server-key"
	sig := sign("KM-INV-1-42", "200", "150000", key)
	if !VerifyMidtransSignature("KM-INV-1-42", "200", "150000", key, sig) {
		t.Error("valid signature rejected")
	}
	if VerifyMidtransSignature("KM-INV-1-42", "200", "150000", "other-key", sig) {
		t.Error("wrong server key accepted")
	}
	// Reformatted amount (e.g. \"150,000.00\" -> \"150000.00\") must fail: the
	// hash covers the exact raw provider string.
	if VerifyMidtransSignature("KM-INV-1-42", "200", "150000.00", key, sig) {
		t.Error("reformatted gross_amount accepted")
	}
	if VerifyMidtransSignature("KM-INV-1-42", "200", "150000", key, sig+"x") {
		t.Error("tampered signature accepted")
	}
}

func TestMidtransAction(t *testing.T) {
	cases := []struct {
		status, fraud, want string
	}{
		{"settlement", "", MidtransActionSettled},
		{"capture", "accept", MidtransActionSettled},
		// capture + challenge/missing fraud status must NOT settle.
		{"capture", "challenge", MidtransActionIgnored},
		{"capture", "", MidtransActionIgnored},
		{"pending", "", MidtransActionIgnored},
		{"deny", "", MidtransActionFailed},
		{"cancel", "", MidtransActionFailed},
		{"expire", "", MidtransActionFailed},
		{"failure", "", MidtransActionFailed},
		{"refund", "", MidtransActionIgnored},
		{"", "", MidtransActionIgnored},
	}
	for _, c := range cases {
		if got := MidtransAction(c.status, c.fraud); got != c.want {
			t.Errorf("MidtransAction(%q, %q) = %q, want %q", c.status, c.fraud, got, c.want)
		}
	}
}

func TestMidtransMethod(t *testing.T) {
	if MidtransMethod("qris") != "qris" {
		t.Error("qris should map to qris")
	}
	for _, p := range []string{"gopay", "bca_va", "credit_card", "shopeepay", ""} {
		if MidtransMethod(p) != "transfer" {
			t.Errorf("MidtransMethod(%q) should map to transfer", p)
		}
	}
}
