package s3client

import (
	"context"
	"fmt"
	"io"
	"net/http"
	"strings"
	"testing"
)

func TestAWSAppendLogOperationMetrics(t *testing.T) {
	for _, operation := range []string{"append_object", "get_object_range", "put_append_log_object", "copy_append_log_object"} {
		for _, result := range []string{"ok", "error", "invalid"} {
			if operation == "copy_append_log_object" && result == "invalid" {
				continue
			}
			t.Run(operation+"/"+result, func(t *testing.T) {
				calls := 0
				c := newTestAWSS3Client(t, func(w http.ResponseWriter, r *http.Request) {
					calls++
					if result == "error" {
						writeS3Error(w, http.StatusForbidden, "AccessDenied", "denied")
						return
					}
					switch operation {
					case "copy_append_log_object":
						w.Header().Set("Content-Type", "application/xml")
						_, _ = io.WriteString(w, `<CopyObjectResult><ETag>"test"</ETag><LastModified>2026-09-01T00:00:00Z</LastModified></CopyObjectResult>`)
					case "get_object_range":
						_, _ = io.WriteString(w, "x")
					}
				})
				wantResult := result
				if result == "invalid" {
					wantResult = "error"
				}
				before := operationCounter(t, "s3client", operation, wantResult)
				otherResult := "error"
				if wantResult == "error" {
					otherResult = "ok"
				}
				beforeOther := operationCounter(t, "s3client", operation, otherResult)
				size := int64(1)
				if result == "invalid" {
					size = -1
				}
				ctx := context.Background()
				var err error
				switch operation {
				case "append_object":
					err = c.AppendObject(ctx, "key", strings.NewReader("x"), size, 0)
				case "get_object_range":
					var body io.ReadCloser
					body, err = c.GetObjectRange(ctx, "key", 0, size-1)
					if body != nil {
						_ = body.Close()
					}
				case "put_append_log_object":
					err = c.PutAppendLogObject(ctx, "key", strings.NewReader("x"), size)
				case "copy_append_log_object":
					err = c.CopyAppendLogObject(ctx, "key", "copy")
				}
				if (err != nil) != (wantResult == "error") {
					t.Fatalf("result=%s error=%v", result, err)
				}
				if result == "invalid" && calls != 0 {
					t.Fatalf("invalid input sent %d requests", calls)
				}
				if got := operationCounter(t, "s3client", operation, wantResult) - before; got != 1 {
					t.Fatalf("%s metric delta=%d, want 1", wantResult, got)
				}
				if got := operationCounter(t, "s3client", operation, otherResult) - beforeOther; got != 0 {
					t.Fatalf("%s metric delta=%d, want 0", otherResult, got)
				}
				series := fmt.Sprintf(`drive9_service_operation_duration_seconds_count{component="s3client",operation=%q,result=%q} `, operation, wantResult)
				if !strings.Contains(readS3Metrics(), series) {
					t.Fatalf("duration metric missing: %s", series)
				}
			})
		}
	}
}
