package backend

import (
	"context"
	"testing"
)

func TestProcessImageExtractTaskSkipsNonImageBytes(t *testing.T) {
	extractor := &countingImageExtractor{text: "caption"}
	b := newTestBackendWithOptions(t, Options{
		AsyncImageExtract: AsyncImageExtractOptions{
			Enabled:   true,
			Extractor: extractor,
		},
	})

	// AppleDouble junk declared as jpeg: skipped without a provider call.
	junk := append([]byte{0x00, 0x05, 0x16, 0x07}, []byte("appledouble-junk")...)
	fileID := insertImageFileForExtractTest(t, b, "/img/junk.jpg", "image/jpeg", junk)
	result, err := b.ProcessImageExtractTask(context.Background(), ImageExtractTaskSpec{
		FileID:      fileID,
		Path:        "/img/junk.jpg",
		ContentType: "image/jpeg",
		Revision:    1,
	})
	if err != nil {
		t.Fatal(err)
	}
	if result != ImageExtractResultNotImage {
		t.Fatalf("result=%q, want %q", result, ImageExtractResultNotImage)
	}
	if extractor.calls != 0 {
		t.Fatalf("extractor calls = %d, want 0 for non-image bytes", extractor.calls)
	}

	// Magic-prefixed content still extracts.
	fileID = insertImageFileForExtractTest(t, b, "/img/real.jpg", "image/jpeg", fakePNG)
	result, err = b.ProcessImageExtractTask(context.Background(), ImageExtractTaskSpec{
		FileID:      fileID,
		Path:        "/img/real.jpg",
		ContentType: "image/jpeg",
		Revision:    1,
	})
	if err != nil {
		t.Fatal(err)
	}
	if result != ImageExtractResultWritten {
		t.Fatalf("result=%q, want %q", result, ImageExtractResultWritten)
	}
	if extractor.calls != 1 {
		t.Fatalf("extractor calls = %d, want 1 for image bytes", extractor.calls)
	}
}

// The basic extractor accepts arbitrary declared-image bytes (it only emits
// metadata text), so the sniff must stay off for it.
func TestProcessImageExtractTaskBasicExtractorSkipsSniff(t *testing.T) {
	b := newTestBackendWithOptions(t, Options{
		AsyncImageExtract: AsyncImageExtractOptions{
			Enabled:   true,
			Extractor: NewBasicImageTextExtractor(),
		},
	})

	junk := append([]byte{0x00, 0x05, 0x16, 0x07}, []byte("appledouble-junk")...)
	fileID := insertImageFileForExtractTest(t, b, "/img/junk.bmp", "image/bmp", junk)
	result, err := b.ProcessImageExtractTask(context.Background(), ImageExtractTaskSpec{
		FileID:      fileID,
		Path:        "/img/junk.bmp",
		ContentType: "image/bmp",
		Revision:    1,
	})
	if err != nil {
		t.Fatal(err)
	}
	if result != ImageExtractResultWritten {
		t.Fatalf("result=%q, want %q (basic extractor keeps metadata fallback)", result, ImageExtractResultWritten)
	}
}

func TestRasterImageMagicOK(t *testing.T) {
	cases := []struct {
		name string
		data []byte
		want bool
	}{
		{"jpeg", []byte{0xFF, 0xD8, 0xFF, 0xE0, 1, 2}, true},
		{"png", fakePNG, true},
		{"gif", []byte("GIF89a...."), true},
		{"webp", []byte("RIFF\x00\x00\x00\x00WEBPVP8 "), true},
		{"appledouble", []byte{0x00, 0x05, 0x16, 0x07, 1, 2}, false},
		{"heic", []byte("\x00\x00\x00\x18ftypheic"), false},
		{"tiff", []byte("II*\x00xxxx"), false},
		{"svg", []byte(`<?xml version="1.0"?><svg>`), false},
		{"ico", []byte{0x00, 0x00, 0x01, 0x00, 1, 2}, false},
		{"bmp", []byte("BMxxxx"), false},
		{"empty", nil, false},
		{"text", []byte("hello world"), false},
	}
	for _, tc := range cases {
		if got := rasterImageMagicOK(tc.data); got != tc.want {
			t.Errorf("rasterImageMagicOK(%s) = %v, want %v", tc.name, got, tc.want)
		}
	}
}
