package virustotal

import (
	"context"
	"crypto/sha256"
	"encoding/hex"
	"encoding/json"
	"net/http"
	"net/http/httptest"
	"strings"
	"testing"
)

func TestScannerLookupMalicious(t *testing.T) {
	sha := sha256.Sum256([]byte("evil"))
	shaHex := hex.EncodeToString(sha[:])

	srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		if r.Method == http.MethodGet && strings.Contains(r.URL.Path, "/files/"+shaHex) {
			_ = json.NewEncoder(w).Encode(map[string]any{
				"data": map[string]any{
					"attributes": map[string]any{
						"last_analysis_stats": map[string]any{
							"malicious":  2,
							"suspicious": 0,
						},
					},
				},
			})
			return
		}
		http.NotFound(w, r)
	}))
	defer srv.Close()

	sc := NewScanner("test-key", nil)
	sc.client.baseURL = srv.URL + "/api/v3"

	_, err := sc.ScanBytes(context.Background(), "evil.bin", []byte("evil"), shaHex)
	if err == nil {
		t.Fatal("expected ErrMalicious")
	}
	if err != ErrMalicious {
		t.Fatalf("err = %v, want ErrMalicious", err)
	}
}

func TestScannerUploadAndPollClean(t *testing.T) {
	pollCount := 0
	srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		switch {
		case r.Method == http.MethodGet && strings.HasSuffix(r.URL.Path, "/files/"+SHA256Hex([]byte("clean"))):
			http.NotFound(w, r)
		case r.Method == http.MethodPost && strings.HasSuffix(r.URL.Path, "/files"):
			_ = json.NewEncoder(w).Encode(map[string]any{
				"data": map[string]any{"id": "analysis-1"},
			})
		case r.Method == http.MethodGet && strings.Contains(r.URL.Path, "/analyses/analysis-1"):
			pollCount++
			status := "queued"
			if pollCount >= 2 {
				status = "completed"
			}
			_ = json.NewEncoder(w).Encode(map[string]any{
				"data": map[string]any{
					"attributes": map[string]any{
						"status": status,
						"stats": map[string]any{
							"malicious":  0,
							"suspicious": 0,
						},
					},
				},
			})
		default:
			http.NotFound(w, r)
		}
	}))
	defer srv.Close()

	sc := NewScanner("test-key", nil)
	sc.client.baseURL = srv.URL + "/api/v3"

	result, err := sc.ScanBytes(context.Background(), "clean.txt", []byte("clean"), "")
	if err != nil {
		t.Fatalf("ScanBytes: %v", err)
	}
	if result.Status != "clean" {
		t.Fatalf("status = %q, want clean", result.Status)
	}
}

func TestScannerFailOpenOnUnavailable(t *testing.T) {
	srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		http.Error(w, "down", http.StatusServiceUnavailable)
	}))
	defer srv.Close()

	sc := NewScanner("test-key", nil)
	sc.client.baseURL = srv.URL + "/api/v3"

	result, err := sc.ScanBytes(context.Background(), "file.bin", []byte("payload"), "")
	if err != nil {
		t.Fatalf("expected fail-open, got err %v", err)
	}
	if result.Status != "skipped" {
		t.Fatalf("status = %q, want skipped", result.Status)
	}
}
